|
|
|
@ -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); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this->pixelSize = subset_view.source_device_record->pixelSize; |
|
|
|
|
this->maxWidth = subset_view.source_device_record->maxWidth; |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
unsigned length = it.len (); |
|
|
|
|
|
|
|
|
|
if (unlikely (!c->extend (*this, length))) return_trace (false); |
|
|
|
|
|
|
|
|
|
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 ()); |
|
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < source_hdmx->numRecords; i++) |
|
|
|
|
{ |
|
|
|
|
DeviceRecord::SubsetView subset_view; |
|
|
|
|
subset_view.init (&(*source_hdmx)[i], source_hdmx->sizeDeviceRecord, plan); |
|
|
|
|
this->version = version; |
|
|
|
|
this->numRecords = it.len (); |
|
|
|
|
this->sizeDeviceRecord = |
|
|
|
|
it ? DeviceRecord::get_size ((*it).second.len ()) : DeviceRecord::get_size (0); |
|
|
|
|
|
|
|
|
|
if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view)) |
|
|
|
|
return_trace (false); |
|
|
|
|
} |
|
|
|
|
using pair_t = decltype (*it); |
|
|
|
|
+ it |
|
|
|
|
| hb_apply ([&] (const pair_t& _) { |
|
|
|
|
c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|