[subset] WIP convert hdmx subsetting to use iterators.
This commit is contained in:
parent
d5decf9bf7
commit
e8ef0e627c
@ -41,71 +41,30 @@ namespace OT {
|
||||
|
||||
struct DeviceRecord
|
||||
{
|
||||
struct SubsetView
|
||||
{
|
||||
const DeviceRecord *source_device_record;
|
||||
unsigned int sizeDeviceRecord;
|
||||
hb_subset_plan_t *subset_plan;
|
||||
|
||||
void init (const DeviceRecord *source_device_record,
|
||||
unsigned int sizeDeviceRecord,
|
||||
hb_subset_plan_t *subset_plan)
|
||||
{
|
||||
this->source_device_record = source_device_record;
|
||||
this->sizeDeviceRecord = sizeDeviceRecord;
|
||||
this->subset_plan = subset_plan;
|
||||
}
|
||||
|
||||
unsigned int len () const
|
||||
{ return this->subset_plan->num_output_glyphs (); }
|
||||
|
||||
const HBUINT8* operator [] (unsigned int new_gid) const
|
||||
{
|
||||
if (unlikely (new_gid >= len ())) return nullptr;
|
||||
|
||||
hb_codepoint_t old_gid;
|
||||
if (!this->subset_plan->old_gid_for_new_gid (new_gid, &old_gid))
|
||||
return &Null(HBUINT8);
|
||||
|
||||
if (old_gid >= sizeDeviceRecord - DeviceRecord::min_size)
|
||||
return nullptr;
|
||||
return &(this->source_device_record->widthsZ[old_gid]);
|
||||
}
|
||||
};
|
||||
|
||||
static unsigned int get_size (unsigned int count)
|
||||
static unsigned int get_size (unsigned count)
|
||||
{ return hb_ceil_to_4 (min_size + count * HBUINT8::static_size); }
|
||||
|
||||
bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view)
|
||||
template<typename Iterator>
|
||||
bool serialize (hb_serialize_context_t *c, unsigned pixelSize, Iterator it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
unsigned int size = get_size (subset_view.len ());
|
||||
if (unlikely (!c->allocate_size<DeviceRecord> (size)))
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Couldn't allocate enough space for DeviceRecord: %d.",
|
||||
size);
|
||||
return_trace (false);
|
||||
}
|
||||
unsigned length = it.len ();
|
||||
|
||||
this->pixelSize = subset_view.source_device_record->pixelSize;
|
||||
this->maxWidth = subset_view.source_device_record->maxWidth;
|
||||
if (unlikely (!c->extend (*this, length))) return_trace (false);
|
||||
|
||||
for (unsigned int i = 0; i < subset_view.len (); i++)
|
||||
{
|
||||
const HBUINT8 *width = subset_view[i];
|
||||
if (!width)
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "HDMX width for new gid %d is missing.", i);
|
||||
return_trace (false);
|
||||
}
|
||||
widthsZ[i] = *width;
|
||||
}
|
||||
this->pixelSize = pixelSize;
|
||||
this->maxWidth =
|
||||
+ it
|
||||
| hb_reduce (hb_max, 0u);
|
||||
|
||||
+ it
|
||||
| hb_sink (widthsZ.as_array (length));
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int sizeDeviceRecord) const
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned sizeDeviceRecord) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
@ -135,26 +94,25 @@ struct hdmx
|
||||
return StructAtOffset<DeviceRecord> (&this->firstDeviceRecord, i * sizeDeviceRecord);
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
|
||||
template<typename Iterator>
|
||||
bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
if (unlikely (!c->extend_min ((*this)))) return_trace (false);
|
||||
|
||||
this->version = source_hdmx->version;
|
||||
this->numRecords = source_hdmx->numRecords;
|
||||
this->sizeDeviceRecord = DeviceRecord::get_size (plan->num_output_glyphs ());
|
||||
this->version = version;
|
||||
this->numRecords = it.len ();
|
||||
this->sizeDeviceRecord =
|
||||
it ? DeviceRecord::get_size ((*it).second.len ()) : DeviceRecord::get_size (0);
|
||||
|
||||
for (unsigned int i = 0; i < source_hdmx->numRecords; i++)
|
||||
{
|
||||
DeviceRecord::SubsetView subset_view;
|
||||
subset_view.init (&(*source_hdmx)[i], source_hdmx->sizeDeviceRecord, plan);
|
||||
using pair_t = decltype (*it);
|
||||
+ it
|
||||
| hb_apply ([&] (const pair_t& _) {
|
||||
c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
|
||||
});
|
||||
|
||||
if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
return_trace (c->successful);
|
||||
}
|
||||
|
||||
|
||||
@ -165,10 +123,33 @@ struct hdmx
|
||||
hdmx *hdmx_prime = c->serializer->start_embed <hdmx> ();
|
||||
if (unlikely (!hdmx_prime)) return_trace (false);
|
||||
|
||||
hdmx_prime->serialize (c->serializer, this, c->plan);
|
||||
auto it =
|
||||
+ hb_iota ((unsigned) numRecords)
|
||||
| hb_map ([&] (unsigned _) {
|
||||
const DeviceRecord *device_record =
|
||||
&StructAtOffset<DeviceRecord> (&firstDeviceRecord,
|
||||
_ * sizeDeviceRecord);
|
||||
auto row =
|
||||
+ hb_iota (c->plan->num_output_glyphs ())
|
||||
| hb_map (c->plan->reverse_glyph_map)
|
||||
| hb_map ([=] (hb_codepoint_t _) {
|
||||
if (c->plan->is_empty_glyph (_))
|
||||
return Null(HBUINT8);
|
||||
return device_record->widthsZ.as_array (get_num_glyphs ()) [_];
|
||||
})
|
||||
;
|
||||
return hb_pair ((unsigned) device_record->pixelSize, +row);
|
||||
});
|
||||
|
||||
hdmx_prime->serialize (c->serializer, version, it);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
unsigned get_num_glyphs () const
|
||||
{
|
||||
return sizeDeviceRecord - DeviceRecord::min_size;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -91,28 +91,6 @@ test_subset_hdmx_invalid (void)
|
||||
hb_face_destroy (face);
|
||||
}
|
||||
|
||||
static void
|
||||
test_subset_hdmx_fails_sanitize (void)
|
||||
{
|
||||
hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016");
|
||||
|
||||
hb_subset_input_t *input = hb_subset_input_create_or_fail ();
|
||||
hb_set_t *codepoints = hb_subset_input_unicode_set (input);
|
||||
hb_face_t *subset;
|
||||
|
||||
hb_set_add (codepoints, 'a');
|
||||
hb_set_add (codepoints, 'b');
|
||||
hb_set_add (codepoints, 'c');
|
||||
|
||||
subset = hb_subset (face, input);
|
||||
g_assert (subset);
|
||||
g_assert (subset == hb_face_get_empty ());
|
||||
|
||||
hb_subset_input_destroy (input);
|
||||
hb_face_destroy (subset);
|
||||
hb_face_destroy (face);
|
||||
}
|
||||
|
||||
static void
|
||||
test_subset_hdmx_noop (void)
|
||||
{
|
||||
@ -140,7 +118,6 @@ main (int argc, char **argv)
|
||||
hb_test_add (test_subset_hdmx_simple_subset);
|
||||
hb_test_add (test_subset_hdmx_multiple_device_records);
|
||||
hb_test_add (test_subset_hdmx_invalid);
|
||||
hb_test_add (test_subset_hdmx_fails_sanitize);
|
||||
hb_test_add (test_subset_hdmx_noop);
|
||||
|
||||
return hb_test_run();
|
||||
|
Loading…
Reference in New Issue
Block a user