diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 384cdb76e..152105bd0 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -428,6 +428,40 @@ struct hb_serialize_context_t bool ran_out_of_room; }; +template +struct Supplier +{ + /* For automatic wrapping of bare arrays */ + inline Supplier (const Type *array) + { + head = array; + len = (unsigned int) -1; + } + + inline Supplier (const Type *array, unsigned int len_) + { + head = array; + len = len_; + } + inline const Type operator [] (unsigned int i) const + { + if (unlikely (i >= len)) return Type (); + return head[i]; + } + + inline void advance (unsigned int count) { + if (unlikely (count > len)) + count = len; + len -= count; + head += count; + } + + private: + unsigned int len; + const Type *head; +}; + + /* @@ -687,7 +721,7 @@ struct GenericArrayOf } inline bool serialize (hb_serialize_context_t *c, - const Type *items, + Supplier &items, unsigned int items_len) { TRACE_SERIALIZE (); @@ -697,6 +731,7 @@ struct GenericArrayOf unsigned int count = items_len; for (unsigned int i = 0; i < count; i++) array[i].set (items[i]); + items.advance (items_len); return TRACE_RETURN (true); } @@ -803,6 +838,22 @@ struct HeadlessArrayOf inline unsigned int get_size (void) const { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } + inline bool serialize (hb_serialize_context_t *c, + Supplier &items, + unsigned int items_len) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + len.set (items_len); /* TODO(serialize) Overflow? */ + if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); + if (unlikely (!items_len)) return TRACE_RETURN (true); + unsigned int count = items_len; + for (unsigned int i = 1; i < count; i++) + array[i-1].set (items[i]); + items.advance (items_len - 1); + return TRACE_RETURN (true); + } + inline bool sanitize_shallow (hb_sanitize_context_t *c) { return c->check_struct (this) && c->check_array (this, Type::static_size, len); diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 6c5e42332..a0b8b5232 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -356,7 +356,7 @@ struct CoverageFormat1 } inline bool serialize (hb_serialize_context_t *c, - const USHORT *glyphs, + Supplier &glyphs, unsigned int num_glyphs) { TRACE_SERIALIZE (); @@ -365,6 +365,7 @@ struct CoverageFormat1 if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false); for (unsigned int i = 0; i < num_glyphs; i++) glyphArray[i].set (glyphs[i]); + glyphs.advance (num_glyphs); return TRACE_RETURN (true); } @@ -420,7 +421,7 @@ struct CoverageFormat2 } inline bool serialize (hb_serialize_context_t *c, - const USHORT *glyphs, + Supplier &glyphs, unsigned int num_glyphs) { TRACE_SERIALIZE (); @@ -446,6 +447,7 @@ struct CoverageFormat2 } else { rangeRecord[range].end = glyphs[i]; } + glyphs.advance (num_glyphs); return TRACE_RETURN (true); } @@ -526,7 +528,7 @@ struct Coverage } inline bool serialize (hb_serialize_context_t *c, - const USHORT *glyphs, + Supplier &glyphs, unsigned int num_glyphs) { TRACE_SERIALIZE (); diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 2ab54e448..c4245ced2 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -73,7 +73,7 @@ struct SingleSubstFormat1 } inline bool serialize (hb_serialize_context_t *c, - const USHORT *glyphs, + Supplier &glyphs, unsigned int num_glyphs, int delta) { @@ -137,8 +137,8 @@ struct SingleSubstFormat2 } inline bool serialize (hb_serialize_context_t *c, - const USHORT *glyphs, - const USHORT *substitutes, + Supplier &glyphs, + Supplier &substitutes, unsigned int num_glyphs) { TRACE_SERIALIZE (); @@ -201,8 +201,8 @@ struct SingleSubst } inline bool serialize (hb_serialize_context_t *c, - const USHORT *glyphs, - const USHORT *substitutes, + Supplier &glyphs, + Supplier &substitutes, unsigned int num_glyphs) { TRACE_SERIALIZE (); @@ -277,7 +277,7 @@ struct Sequence } inline bool serialize (hb_serialize_context_t *c, - const USHORT *glyphs, + Supplier &glyphs, unsigned int num_glyphs) { TRACE_SERIALIZE (); @@ -331,19 +331,20 @@ struct MultipleSubstFormat1 } inline bool serialize (hb_serialize_context_t *c, - const USHORT *glyphs, - unsigned int *substitute_len_list, + Supplier &glyphs, + Supplier &substitute_len_list, unsigned int num_glyphs, - const USHORT *substitute_glyphs_list) + Supplier &substitute_glyphs_list) { TRACE_SERIALIZE (); if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); if (unlikely (!sequence.serialize (c, num_glyphs))) return TRACE_RETURN (false); - for (unsigned int i = 0; i < num_glyphs; i++) { - if (unlikely (!sequence[i].serialize (c, this).serialize (c, substitute_glyphs_list, substitute_len_list[i]))) return TRACE_RETURN (false); - substitute_glyphs_list += substitute_len_list[i]; - } + for (unsigned int i = 0; i < num_glyphs; i++) + if (unlikely (!sequence[i].serialize (c, this).serialize (c, + substitute_glyphs_list, + substitute_len_list[i]))) return TRACE_RETURN (false); + substitute_len_list.advance (num_glyphs); return TRACE_RETURN (true); } @@ -397,10 +398,10 @@ struct MultipleSubst } inline bool serialize (hb_serialize_context_t *c, - const USHORT *glyphs, - unsigned int *substitute_len_list, + Supplier &glyphs, + Supplier &substitute_len_list, unsigned int num_glyphs, - const USHORT *substitute_glyphs_list) + Supplier &substitute_glyphs_list) { TRACE_SERIALIZE (); if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); @@ -486,19 +487,20 @@ struct AlternateSubstFormat1 } inline bool serialize (hb_serialize_context_t *c, - const USHORT *glyphs, - unsigned int *alternate_len_list, + Supplier &glyphs, + Supplier &alternate_len_list, unsigned int num_glyphs, - const USHORT *alternate_glyphs_list) + Supplier &alternate_glyphs_list) { TRACE_SERIALIZE (); if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false); if (unlikely (!alternateSet.serialize (c, num_glyphs))) return TRACE_RETURN (false); - for (unsigned int i = 0; i < num_glyphs; i++) { - if (unlikely (!alternateSet[i].serialize (c, this).serialize (c, alternate_glyphs_list, alternate_len_list[i]))) return TRACE_RETURN (false); - alternate_glyphs_list += alternate_len_list[i]; - } + for (unsigned int i = 0; i < num_glyphs; i++) + if (unlikely (!alternateSet[i].serialize (c, this).serialize (c, + alternate_glyphs_list, + alternate_len_list[i]))) return TRACE_RETURN (false); + alternate_len_list.advance (num_glyphs); return TRACE_RETURN (true); } @@ -552,10 +554,10 @@ struct AlternateSubst } inline bool serialize (hb_serialize_context_t *c, - const USHORT *glyphs, - unsigned int *alternate_len_list, + Supplier &glyphs, + Supplier &alternate_len_list, unsigned int num_glyphs, - const USHORT *alternate_glyphs_list) + Supplier &alternate_glyphs_list) { TRACE_SERIALIZE (); if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); @@ -646,6 +648,18 @@ struct Ligature return TRACE_RETURN (true); } + inline bool serialize (hb_serialize_context_t *c, + GlyphID ligature, + Supplier &components, /* Starting from second */ + unsigned int num_components /* Including first component */) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + ligGlyph.set (ligature); + if (unlikely (!component.serialize (c, components, num_components))) return TRACE_RETURN (false); + return TRACE_RETURN (true); + } + public: inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); @@ -701,6 +715,24 @@ struct LigatureSet return TRACE_RETURN (false); } + inline bool serialize (hb_serialize_context_t *c, + Supplier &ligatures, + Supplier &component_count_list, + unsigned int num_ligatures, + Supplier &component_list /* Starting from second for each ligature */) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!ligature.serialize (c, num_ligatures))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < num_ligatures; i++) + if (unlikely (!ligature[i].serialize (c, this).serialize (c, + ligatures[i], + component_list, + component_count_list[i]))) return TRACE_RETURN (false); + component_count_list.advance (num_ligatures); + return TRACE_RETURN (true); + } + public: inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); @@ -753,6 +785,28 @@ struct LigatureSubstFormat1 return TRACE_RETURN (lig_set.apply (c)); } + inline bool serialize (hb_serialize_context_t *c, + Supplier &first_glyphs, + Supplier &ligature_per_first_glyph_count_list, + unsigned int num_first_glyphs, + Supplier &ligatures_list, + Supplier &component_count_list, + Supplier &component_list /* Starting from second for each ligature */) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return TRACE_RETURN (false); + if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return TRACE_RETURN (false); + for (unsigned int i = 0; i < num_first_glyphs; i++) + if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c, + ligatures_list, + component_count_list, + ligature_per_first_glyph_count_list[i], + component_list))) return TRACE_RETURN (false); + ligature_per_first_glyph_count_list.advance (num_first_glyphs); + return TRACE_RETURN (true); + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this)); @@ -810,6 +864,25 @@ struct LigatureSubst } } + inline bool serialize (hb_serialize_context_t *c, + Supplier &first_glyphs, + Supplier &ligature_per_first_glyph_count_list, + unsigned int num_first_glyphs, + Supplier &ligatures_list, + Supplier &component_count_list, + Supplier &component_list /* Starting from second for each ligature */) + { + TRACE_SERIALIZE (); + if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false); + unsigned int format = 1; + u.format.set (format); + switch (u.format) { + case 1: return TRACE_RETURN (u.format1.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, num_first_glyphs, + ligatures_list, component_count_list, component_list)); + default:return TRACE_RETURN (false); + } + } + inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (); if (!u.format.sanitize (c)) return TRACE_RETURN (false);