diff options
Diffstat (limited to 'thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh')
-rw-r--r-- | thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh | 622 |
1 files changed, 393 insertions, 229 deletions
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh index f523e35c00..1e305518f5 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh @@ -89,20 +89,22 @@ struct ValueFormat : HBUINT16 HBINT16 yAdvance; /* Vertical adjustment for advance--in * design units (only used for vertical * writing) */ - OffsetTo<Device> xPlaDevice; /* Offset to Device table for + Offset16To<Device> xPlaDevice; /* Offset to Device table for * horizontal placement--measured from * beginning of PosTable (may be NULL) */ - OffsetTo<Device> yPlaDevice; /* Offset to Device table for vertical + Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical * placement--measured from beginning * of PosTable (may be NULL) */ - OffsetTo<Device> xAdvDevice; /* Offset to Device table for + Offset16To<Device> xAdvDevice; /* Offset to Device table for * horizontal advance--measured from * beginning of PosTable (may be NULL) */ - OffsetTo<Device> yAdvDevice; /* Offset to Device table for vertical + Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical * advance--measured from beginning of * PosTable (may be NULL) */ #endif + IntType& operator = (uint16_t i) { v = i; return *this; } + unsigned int get_len () const { return hb_popcount ((unsigned int) *this); } unsigned int get_size () const { return get_len () * Value::static_size; } @@ -160,16 +162,40 @@ struct ValueFormat : HBUINT16 return ret; } - void serialize_copy (hb_serialize_context_t *c, const void *base, - const Value *values, const hb_map_t *layout_variation_idx_map) const + unsigned int get_effective_format (const Value *values) const + { + unsigned int format = *this; + for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) { + if (format & flag) should_drop (*values++, (Flags) flag, &format); + } + + return format; + } + + template<typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + unsigned int get_effective_format (Iterator it) const { + unsigned int new_format = 0; + + for (const hb_array_t<const Value>& values : it) + new_format = new_format | get_effective_format (&values); + + return new_format; + } + + void copy_values (hb_serialize_context_t *c, + unsigned int new_format, + const void *base, + const Value *values, + const hb_map_t *layout_variation_idx_map) const { unsigned int format = *this; if (!format) return; - if (format & xPlacement) c->copy (*values++); - if (format & yPlacement) c->copy (*values++); - if (format & xAdvance) c->copy (*values++); - if (format & yAdvance) c->copy (*values++); + if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++); + if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++); + if (format & xAdvance) copy_value (c, new_format, xAdvance, *values++); + if (format & yAdvance) copy_value (c, new_format, yAdvance, *values++); if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map); if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map); @@ -177,6 +203,16 @@ struct ValueFormat : HBUINT16 if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map); } + void copy_value (hb_serialize_context_t *c, + unsigned int new_format, + Flags flag, + Value value) const + { + // Filter by new format. + if (!(new_format & flag)) return; + c->copy (value); + } + void collect_variation_indices (hb_collect_variation_indices_context_t *c, const void *base, const hb_array_t<const Value>& values) const @@ -232,14 +268,14 @@ struct ValueFormat : HBUINT16 return true; } - static inline OffsetTo<Device>& get_device (Value* value) + static inline Offset16To<Device>& get_device (Value* value) { - return *static_cast<OffsetTo<Device> *> (value); + return *static_cast<Offset16To<Device> *> (value); } - static inline const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr) + static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr) { if (worked) *worked |= bool (*value); - return *static_cast<const OffsetTo<Device> *> (value); + return *static_cast<const Offset16To<Device> *> (value); } bool copy_device (hb_serialize_context_t *c, const void *base, @@ -317,13 +353,21 @@ struct ValueFormat : HBUINT16 return_trace (true); } + + private: + + void should_drop (Value value, Flags flag, unsigned int* format) const + { + if (value) return; + *format = *format & ~flag; + } + }; -template<typename Iterator> +template<typename Iterator, typename SrcLookup> static void SinglePos_serialize (hb_serialize_context_t *c, - const void *src, + const SrcLookup *src, Iterator it, - ValueFormat valFormat, const hb_map_t *layout_variation_idx_map); @@ -346,7 +390,10 @@ struct AnchorFormat1 AnchorFormat1* copy (hb_serialize_context_t *c) const { TRACE_SERIALIZE (this); - return_trace (c->embed<AnchorFormat1> (this)); + AnchorFormat1* out = c->embed<AnchorFormat1> (this); + if (!out) return_trace (out); + out->format = 1; + return_trace (out); } protected: @@ -447,11 +494,11 @@ struct AnchorFormat3 HBUINT16 format; /* Format identifier--format = 3 */ FWORD xCoordinate; /* Horizontal value--in design units */ FWORD yCoordinate; /* Vertical value--in design units */ - OffsetTo<Device> + Offset16To<Device> xDeviceTable; /* Offset to Device table for X * coordinate-- from beginning of * Anchor table (may be NULL) */ - OffsetTo<Device> + Offset16To<Device> yDeviceTable; /* Offset to Device table for Y * coordinate-- from beginning of * Anchor table (may be NULL) */ @@ -485,14 +532,22 @@ struct Anchor } } - Anchor* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const + bool subset (hb_subset_context_t *c) const { - TRACE_SERIALIZE (this); + TRACE_SUBSET (this); switch (u.format) { - case 1: return_trace (reinterpret_cast<Anchor *> (u.format1.copy (c))); - case 2: return_trace (reinterpret_cast<Anchor *> (u.format2.copy (c))); - case 3: return_trace (reinterpret_cast<Anchor *> (u.format3.copy (c, layout_variation_idx_map))); - default:return_trace (nullptr); + case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer)))); + case 2: + if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING) + { + // AnchorFormat 2 just containins extra hinting information, so + // if hints are being dropped convert to format 1. + return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer)))); + } + return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer)))); + case 3: return_trace (bool (reinterpret_cast<Anchor *> (u.format3.copy (c->serializer, + c->plan->layout_variation_idx_map)))); + default:return_trace (false); } } @@ -541,51 +596,29 @@ struct AnchorMatrix } template <typename Iterator, - hb_requires (hb_is_iterator (Iterator))> - bool serialize (hb_serialize_context_t *c, - unsigned num_rows, - AnchorMatrix const *offset_matrix, - const hb_map_t *layout_variation_idx_map, - Iterator index_iter) + hb_requires (hb_is_iterator (Iterator))> + bool subset (hb_subset_context_t *c, + unsigned num_rows, + Iterator index_iter) const { - TRACE_SERIALIZE (this); + TRACE_SUBSET (this); + + auto *out = c->serializer->start_embed (this); + if (!index_iter) return_trace (false); - if (unlikely (!c->extend_min ((*this)))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - this->rows = num_rows; + out->rows = num_rows; for (const unsigned i : index_iter) { - auto *offset = c->embed (offset_matrix->matrixZ[i]); + auto *offset = c->serializer->embed (matrixZ[i]); if (!offset) return_trace (false); - offset->serialize_copy (c, offset_matrix->matrixZ[i], - offset_matrix, c->to_bias (this), - hb_serialize_context_t::Head, - layout_variation_idx_map); + offset->serialize_subset (c, matrixZ[i], this); } return_trace (true); } - bool subset (hb_subset_context_t *c, - unsigned cols, - const hb_map_t *klass_mapping) const - { - TRACE_SUBSET (this); - auto *out = c->serializer->start_embed (*this); - - auto indexes = - + hb_range (rows * cols) - | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % cols); }) - ; - - out->serialize (c->serializer, - (unsigned) rows, - this, - c->plan->layout_variation_idx_map, - indexes); - return_trace (true); - } - bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const { TRACE_SANITIZE (this); @@ -599,7 +632,7 @@ struct AnchorMatrix } HBUINT16 rows; /* Number of rows */ - UnsizedArrayOf<OffsetTo<Anchor>> + UnsizedArrayOf<Offset16To<Anchor>> matrixZ; /* Matrix of offsets to Anchor tables-- * from beginning of AnchorMatrix table */ public: @@ -618,18 +651,16 @@ struct MarkRecord return_trace (c->check_struct (this) && markAnchor.sanitize (c, base)); } - MarkRecord *copy (hb_serialize_context_t *c, - const void *src_base, - unsigned dst_bias, - const hb_map_t *klass_mapping, - const hb_map_t *layout_variation_idx_map) const + MarkRecord *subset (hb_subset_context_t *c, + const void *src_base, + const hb_map_t *klass_mapping) const { - TRACE_SERIALIZE (this); - auto *out = c->embed (this); + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); if (unlikely (!out)) return_trace (nullptr); out->klass = klass_mapping->get (klass); - out->markAnchor.serialize_copy (c, markAnchor, src_base, dst_bias, hb_serialize_context_t::Head, layout_variation_idx_map); + out->markAnchor.serialize_subset (c, markAnchor, src_base); return_trace (out); } @@ -641,14 +672,14 @@ struct MarkRecord protected: HBUINT16 klass; /* Class defined for this mark */ - OffsetTo<Anchor> + Offset16To<Anchor> markAnchor; /* Offset to Anchor table--from * beginning of MarkArray table */ public: DEFINE_SIZE_STATIC (4); }; -struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage order */ +struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */ { bool apply (hb_ot_apply_context_t *c, unsigned int mark_index, unsigned int glyph_index, @@ -657,7 +688,7 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; - const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index); + const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index); unsigned int mark_class = record.klass; const Anchor& mark_anchor = this + record.markAnchor; @@ -684,25 +715,42 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde return_trace (true); } - template<typename Iterator, - hb_requires (hb_is_source_of (Iterator, MarkRecord))> - bool serialize (hb_serialize_context_t *c, - const hb_map_t *klass_mapping, - const hb_map_t *layout_variation_idx_map, - const void *base, - Iterator it) + template <typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + bool subset (hb_subset_context_t *c, + Iterator coverage, + const hb_map_t *klass_mapping) const { - TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (*this))) return_trace (false); - if (unlikely (!c->check_assign (len, it.len ()))) return_trace (false); - c->copy_all (it, base, c->to_bias (this), klass_mapping, layout_variation_idx_map); + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + + auto* out = c->serializer->start_embed (this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + auto mark_iter = + + hb_zip (coverage, this->iter ()) + | hb_filter (glyphset, hb_first) + | hb_map (hb_second) + ; + + unsigned new_length = 0; + for (const auto& mark_record : mark_iter) { + if (unlikely (!mark_record.subset (c, this, klass_mapping))) + return_trace (false); + new_length++; + } + + if (unlikely (!c->serializer->check_assign (out->len, new_length, + HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) + return_trace (false); + return_trace (true); } bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (ArrayOf<MarkRecord>::sanitize (c, this)); + return_trace (Array16Of<MarkRecord>::sanitize (c, this)); } }; @@ -733,6 +781,8 @@ struct SinglePosFormat1 const Coverage &get_coverage () const { return this+coverage; } + ValueFormat get_value_format () const { return valueFormat; } + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); @@ -747,29 +797,33 @@ struct SinglePosFormat1 } template<typename Iterator, - hb_requires (hb_is_iterator (Iterator))> + typename SrcLookup, + hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, - const void *src, + const SrcLookup *src, Iterator it, - ValueFormat valFormat, + ValueFormat newFormat, const hb_map_t *layout_variation_idx_map) { - auto out = c->extend_min (*this); - if (unlikely (!out)) return; - if (unlikely (!c->check_assign (valueFormat, valFormat))) return; + if (unlikely (!c->extend_min (this))) return; + if (unlikely (!c->check_assign (valueFormat, + newFormat, + HB_SERIALIZE_ERROR_INT_OVERFLOW))) return; - + it - | hb_map (hb_second) - | hb_apply ([&] (hb_array_t<const Value> _) - { valFormat.serialize_copy (c, src, &_, layout_variation_idx_map); }) - ; + for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second)) + { + src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); + // Only serialize the first entry in the iterator, the rest are assumed to + // be the same. + break; + } auto glyphs = + it | hb_map_retains_sorting (hb_first) ; - coverage.serialize (c, this).serialize (c, glyphs); + coverage.serialize_serialize (c, glyphs); } bool subset (hb_subset_context_t *c) const @@ -786,7 +840,7 @@ struct SinglePosFormat1 ; bool ret = bool (it); - SinglePos_serialize (c->serializer, this, it, valueFormat, c->plan->layout_variation_idx_map); + SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map); return_trace (ret); } @@ -800,7 +854,7 @@ struct SinglePosFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ ValueFormat valueFormat; /* Defines the types of data in the @@ -843,6 +897,8 @@ struct SinglePosFormat2 const Coverage &get_coverage () const { return this+coverage; } + ValueFormat get_value_format () const { return valueFormat; } + bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); @@ -861,22 +917,23 @@ struct SinglePosFormat2 } template<typename Iterator, - hb_requires (hb_is_iterator (Iterator))> + typename SrcLookup, + hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, - const void *src, + const SrcLookup *src, Iterator it, - ValueFormat valFormat, + ValueFormat newFormat, const hb_map_t *layout_variation_idx_map) { - auto out = c->extend_min (*this); + auto out = c->extend_min (this); if (unlikely (!out)) return; - if (unlikely (!c->check_assign (valueFormat, valFormat))) return; - if (unlikely (!c->check_assign (valueCount, it.len ()))) return; + if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return; + if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return; + it | hb_map (hb_second) | hb_apply ([&] (hb_array_t<const Value> _) - { valFormat.serialize_copy (c, src, &_, layout_variation_idx_map); }) + { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); }) ; auto glyphs = @@ -884,7 +941,7 @@ struct SinglePosFormat2 | hb_map_retains_sorting (hb_first) ; - coverage.serialize (c, this).serialize (c, glyphs); + coverage.serialize_serialize (c, glyphs); } bool subset (hb_subset_context_t *c) const @@ -908,7 +965,7 @@ struct SinglePosFormat2 ; bool ret = bool (it); - SinglePos_serialize (c->serializer, this, it, valueFormat, c->plan->layout_variation_idx_map); + SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map); return_trace (ret); } @@ -922,7 +979,7 @@ struct SinglePosFormat2 protected: HBUINT16 format; /* Format identifier--format = 2 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ ValueFormat valueFormat; /* Defines the types of data in the @@ -952,24 +1009,37 @@ struct SinglePos template<typename Iterator, - hb_requires (hb_is_iterator (Iterator))> + typename SrcLookup, + hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, - const void *src, + const SrcLookup* src, Iterator glyph_val_iter_pairs, - ValueFormat valFormat, const hb_map_t *layout_variation_idx_map) { if (unlikely (!c->extend_min (u.format))) return; unsigned format = 2; + ValueFormat new_format = src->get_value_format (); - if (glyph_val_iter_pairs) format = get_format (glyph_val_iter_pairs); + if (glyph_val_iter_pairs) + { + format = get_format (glyph_val_iter_pairs); + new_format = src->get_value_format ().get_effective_format (+ glyph_val_iter_pairs | hb_map (hb_second)); + } u.format = format; switch (u.format) { - case 1: u.format1.serialize (c, src, glyph_val_iter_pairs, valFormat, layout_variation_idx_map); - return; - case 2: u.format2.serialize (c, src, glyph_val_iter_pairs, valFormat, layout_variation_idx_map); - return; + case 1: u.format1.serialize (c, + src, + glyph_val_iter_pairs, + new_format, + layout_variation_idx_map); + return; + case 2: u.format2.serialize (c, + src, + glyph_val_iter_pairs, + new_format, + layout_variation_idx_map); + return; default:return; } } @@ -994,14 +1064,13 @@ struct SinglePos } u; }; -template<typename Iterator> +template<typename Iterator, typename SrcLookup> static void SinglePos_serialize (hb_serialize_context_t *c, - const void *src, + const SrcLookup *src, Iterator it, - ValueFormat valFormat, const hb_map_t *layout_variation_idx_map) -{ c->start_embed<SinglePos> ()->serialize (c, src, it, valFormat, layout_variation_idx_map); } +{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_map); } struct PairValueRecord @@ -1011,26 +1080,35 @@ struct PairValueRecord int cmp (hb_codepoint_t k) const { return secondGlyph.cmp (k); } - struct serialize_closure_t + struct context_t { const void *base; const ValueFormat *valueFormats; + const ValueFormat *newFormats; unsigned len1; /* valueFormats[0].get_len() */ const hb_map_t *glyph_map; const hb_map_t *layout_variation_idx_map; }; - bool serialize (hb_serialize_context_t *c, - serialize_closure_t *closure) const + bool subset (hb_subset_context_t *c, + context_t *closure) const { TRACE_SERIALIZE (this); - auto *out = c->start_embed (*this); - if (unlikely (!c->extend_min (out))) return_trace (false); + auto *s = c->serializer; + auto *out = s->start_embed (*this); + if (unlikely (!s->extend_min (out))) return_trace (false); out->secondGlyph = (*closure->glyph_map)[secondGlyph]; - closure->valueFormats[0].serialize_copy (c, closure->base, &values[0], closure->layout_variation_idx_map); - closure->valueFormats[1].serialize_copy (c, closure->base, &values[closure->len1], closure->layout_variation_idx_map); + closure->valueFormats[0].copy_values (s, + closure->newFormats[0], + closure->base, &values[0], + closure->layout_variation_idx_map); + closure->valueFormats[1].copy_values (s, + closure->newFormats[1], + closure->base, + &values[closure->len1], + closure->layout_variation_idx_map); return_trace (true); } @@ -1050,6 +1128,21 @@ struct PairValueRecord valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len)); } + bool intersects (const hb_set_t& glyphset) const + { + return glyphset.has(secondGlyph); + } + + const Value* get_values_1 () const + { + return &values[0]; + } + + const Value* get_values_2 (ValueFormat format1) const + { + return &values[format1.get_len ()]; + } + protected: HBGlyphID secondGlyph; /* GlyphID of second glyph in the * pair--first glyph is listed in the @@ -1140,7 +1233,8 @@ struct PairSet } bool subset (hb_subset_context_t *c, - const ValueFormat valueFormats[2]) const + const ValueFormat valueFormats[2], + const ValueFormat newFormats[2]) const { TRACE_SUBSET (this); auto snap = c->serializer->snapshot (); @@ -1156,10 +1250,11 @@ struct PairSet unsigned len2 = valueFormats[1].get_len (); unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2); - PairValueRecord::serialize_closure_t closure = + PairValueRecord::context_t context = { this, valueFormats, + newFormats, len1, &glyph_map, c->plan->layout_variation_idx_map @@ -1170,7 +1265,7 @@ struct PairSet for (unsigned i = 0; i < count; i++) { if (glyphset.has (record->secondGlyph) - && record->serialize (c->serializer, &closure)) num++; + && record->subset (c, &context)) num++; record = &StructAtOffset<const PairValueRecord> (record, record_size); } @@ -1218,7 +1313,7 @@ struct PairPosFormat1 + hb_zip (this+coverage, pairSet) | hb_filter (*glyphs, hb_first) | hb_map (hb_second) - | hb_map ([glyphs, this] (const OffsetTo<PairSet> &_) + | hb_map ([glyphs, this] (const Offset16To<PairSet> &_) { return (this+_).intersects (glyphs, valueFormat); }) | hb_any ; @@ -1278,17 +1373,23 @@ struct PairPosFormat1 out->format = format; out->valueFormat[0] = valueFormat[0]; out->valueFormat[1] = valueFormat[1]; + if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING) + { + hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset); + out->valueFormat[0] = newFormats.first; + out->valueFormat[1] = newFormats.second; + } hb_sorted_vector_t<hb_codepoint_t> new_coverage; + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) - | hb_filter ([this, c, out] (const OffsetTo<PairSet>& _) + | hb_filter ([this, c, out] (const Offset16To<PairSet>& _) { auto *o = out->pairSet.serialize_append (c->serializer); if (unlikely (!o)) return false; auto snap = c->serializer->snapshot (); - bool ret = o->serialize_subset (c, _, this, valueFormat); + bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat); if (!ret) { out->pairSet.pop (); @@ -1302,12 +1403,41 @@ struct PairPosFormat1 | hb_sink (new_coverage) ; - out->coverage.serialize (c->serializer, out) - .serialize (c->serializer, new_coverage.iter ()); + out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); return_trace (bool (new_coverage)); } + + hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const + { + unsigned len1 = valueFormat[0].get_len (); + unsigned len2 = valueFormat[1].get_len (); + unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2); + + unsigned format1 = 0; + unsigned format2 = 0; + for (const Offset16To<PairSet>& _ : + + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second)) + { + const PairSet& set = (this + _); + const PairValueRecord *record = &set.firstPairValueRecord; + + for (unsigned i = 0; i < set.len; i++) + { + if (record->intersects (glyphset)) + { + format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ()); + format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0])); + } + record = &StructAtOffset<const PairValueRecord> (record, record_size); + } + } + + return hb_pair (format1, format2); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -1328,7 +1458,7 @@ struct PairPosFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ ValueFormat valueFormat[2]; /* [0] Defines the types of data in @@ -1337,7 +1467,7 @@ struct PairPosFormat1 /* [1] Defines the types of data in * ValueRecord2--for the second glyph * in the pair--may be zero (0) */ - OffsetArrayOf<PairSet> + Array16OfOffset16To<PairSet> pairSet; /* Array of PairSet tables * ordered by Coverage Index */ public: @@ -1355,18 +1485,35 @@ struct PairPosFormat2 void closure_lookups (hb_closure_lookups_context_t *c) const {} void collect_variation_indices (hb_collect_variation_indices_context_t *c) const { + if (!intersects (c->glyph_set)) return; if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return; + hb_set_t klass1_glyphs, klass2_glyphs; + if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return; + if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return; + hb_set_t class1_set, class2_set; - for (const unsigned cp : c->glyph_set->iter ()) + for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage)) + { + if (!klass1_glyphs.has (cp)) class1_set.add (0); + else + { + unsigned klass1 = (this+classDef1).get (cp); + class1_set.add (klass1); + } + } + + class2_set.add (0); + for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs)) { - unsigned klass1 = (this+classDef1).get (cp); unsigned klass2 = (this+classDef2).get (cp); - class1_set.add (klass1); class2_set.add (klass2); } - if (class1_set.is_empty () || class2_set.is_empty ()) return; + if (class1_set.is_empty () + || class2_set.is_empty () + || (class2_set.get_population() == 1 && class2_set.has(0))) + return; unsigned len1 = valueFormat1.get_len (); unsigned len2 = valueFormat2.get_len (); @@ -1431,35 +1578,34 @@ struct PairPosFormat2 auto *out = c->serializer->start_embed (*this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); out->format = format; - out->valueFormat1 = valueFormat1; - out->valueFormat2 = valueFormat2; hb_map_t klass1_map; - out->classDef1.serialize_subset (c, classDef1, this, &klass1_map); + out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage)); out->class1Count = klass1_map.get_population (); hb_map_t klass2_map; - out->classDef2.serialize_subset (c, classDef2, this, &klass2_map); + out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false); out->class2Count = klass2_map.get_population (); unsigned len1 = valueFormat1.get_len (); unsigned len2 = valueFormat2.get_len (); - + hb_range ((unsigned) class1Count) - | hb_filter (klass1_map) - | hb_apply ([&] (const unsigned class1_idx) - { - + hb_range ((unsigned) class2Count) - | hb_filter (klass2_map) - | hb_apply ([&] (const unsigned class2_idx) - { - unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); - valueFormat1.serialize_copy (c->serializer, this, &values[idx], c->plan->layout_variation_idx_map); - valueFormat2.serialize_copy (c->serializer, this, &values[idx + len1], c->plan->layout_variation_idx_map); - }) - ; - }) - ; + hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2); + if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING) + newFormats = compute_effective_value_formats (klass1_map, klass2_map); + + out->valueFormat1 = newFormats.first; + out->valueFormat2 = newFormats.second; + + for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map)) + { + for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map)) + { + unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); + valueFormat1.copy_values (c->serializer, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map); + valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map); + } + } const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; @@ -1470,10 +1616,34 @@ struct PairPosFormat2 | hb_map_retains_sorting (glyph_map) ; - out->coverage.serialize (c->serializer, out).serialize (c->serializer, it); + out->coverage.serialize_serialize (c->serializer, it); return_trace (out->class1Count && out->class2Count && bool (it)); } + + hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map, + const hb_map_t& klass2_map) const + { + unsigned len1 = valueFormat1.get_len (); + unsigned len2 = valueFormat2.get_len (); + + unsigned format1 = 0; + unsigned format2 = 0; + + for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map)) + { + for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map)) + { + unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); + format1 = format1 | valueFormat1.get_effective_format (&values[idx]); + format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]); + } + } + + return hb_pair (format1, format2); + } + + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -1496,7 +1666,7 @@ struct PairPosFormat2 protected: HBUINT16 format; /* Format identifier--format = 2 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ ValueFormat valueFormat1; /* ValueRecord definition--for the @@ -1505,11 +1675,11 @@ struct PairPosFormat2 ValueFormat valueFormat2; /* ValueRecord definition--for the * second glyph of the pair--may be * zero (0) */ - OffsetTo<ClassDef> + Offset16To<ClassDef> classDef1; /* Offset to ClassDef table--from * beginning of PairPos subtable--for * the first glyph of the pair */ - OffsetTo<ClassDef> + Offset16To<ClassDef> classDef2; /* Offset to ClassDef table--from * beginning of PairPos subtable--for * the second glyph of the pair */ @@ -1564,26 +1734,24 @@ struct EntryExitRecord (src_base+exitAnchor).collect_variation_indices (c); } - EntryExitRecord* copy (hb_serialize_context_t *c, - const void *src_base, - const void *dst_base, - const hb_map_t *layout_variation_idx_map) const + EntryExitRecord* subset (hb_subset_context_t *c, + const void *src_base) const { TRACE_SERIALIZE (this); - auto *out = c->embed (this); + auto *out = c->serializer->embed (this); if (unlikely (!out)) return_trace (nullptr); - out->entryAnchor.serialize_copy (c, entryAnchor, src_base, c->to_bias (dst_base), hb_serialize_context_t::Head, layout_variation_idx_map); - out->exitAnchor.serialize_copy (c, exitAnchor, src_base, c->to_bias (dst_base), hb_serialize_context_t::Head, layout_variation_idx_map); + out->entryAnchor.serialize_subset (c, entryAnchor, src_base); + out->exitAnchor.serialize_subset (c, exitAnchor, src_base); return_trace (out); } protected: - OffsetTo<Anchor> + Offset16To<Anchor> entryAnchor; /* Offset to EntryAnchor table--from * beginning of CursivePos * subtable--may be NULL */ - OffsetTo<Anchor> + Offset16To<Anchor> exitAnchor; /* Offset to ExitAnchor table--from * beginning of CursivePos * subtable--may be NULL */ @@ -1712,7 +1880,7 @@ struct CursivePosFormat1 else pos[child].x_offset = x_offset; - /* If parent was attached to child, break them free. + /* If parent was attached to child, separate them. * https://github.com/harfbuzz/harfbuzz/issues/2469 */ if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain())) @@ -1724,25 +1892,24 @@ struct CursivePosFormat1 template <typename Iterator, hb_requires (hb_is_iterator (Iterator))> - void serialize (hb_serialize_context_t *c, + void serialize (hb_subset_context_t *c, Iterator it, - const void *src_base, - const hb_map_t *layout_variation_idx_map) + const void *src_base) { - if (unlikely (!c->extend_min ((*this)))) return; + if (unlikely (!c->serializer->extend_min ((*this)))) return; this->format = 1; this->entryExitRecord.len = it.len (); for (const EntryExitRecord& entry_record : + it | hb_map (hb_second)) - c->copy (entry_record, src_base, this, layout_variation_idx_map); + entry_record.subset (c, src_base); auto glyphs = + it | hb_map_retains_sorting (hb_first) ; - coverage.serialize (c, this).serialize (c, glyphs); + coverage.serialize_serialize (c->serializer, glyphs); } bool subset (hb_subset_context_t *c) const @@ -1762,7 +1929,7 @@ struct CursivePosFormat1 ; bool ret = bool (it); - out->serialize (c->serializer, it, this, c->plan->layout_variation_idx_map); + out->serialize (c, it, this); return_trace (ret); } @@ -1774,10 +1941,10 @@ struct CursivePosFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ - ArrayOf<EntryExitRecord> + Array16Of<EntryExitRecord> entryExitRecord; /* Array of EntryExit records--in * Coverage Index order */ public: @@ -1949,13 +2116,12 @@ struct MarkBasePosFormat1 | hb_sink (new_coverage) ; - if (!out->markCoverage.serialize (c->serializer, out) - .serialize (c->serializer, new_coverage.iter ())) + if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ())) return_trace (false); - out->markArray.serialize (c->serializer, out) - .serialize (c->serializer, &klass_mapping, c->plan->layout_variation_idx_map, &(this+markArray), + mark_iter - | hb_map (hb_second)); + out->markArray.serialize_subset (c, markArray, this, + (this+markCoverage).iter (), + &klass_mapping); unsigned basecount = (this+baseArray).rows; auto base_iter = @@ -1970,8 +2136,7 @@ struct MarkBasePosFormat1 | hb_sink (new_coverage) ; - if (!out->baseCoverage.serialize (c->serializer, out) - .serialize (c->serializer, new_coverage.iter ())) + if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ())) return_trace (false); hb_sorted_vector_t<unsigned> base_indexes; @@ -1984,8 +2149,10 @@ struct MarkBasePosFormat1 | hb_sink (base_indexes) ; } - out->baseArray.serialize (c->serializer, out) - .serialize (c->serializer, base_iter.len (), &(this+baseArray), c->plan->layout_variation_idx_map, base_indexes.iter ()); + + out->baseArray.serialize_subset (c, baseArray, this, + base_iter.len (), + base_indexes.iter ()); return_trace (true); } @@ -2002,17 +2169,17 @@ struct MarkBasePosFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> markCoverage; /* Offset to MarkCoverage table--from * beginning of MarkBasePos subtable */ - OffsetTo<Coverage> + Offset16To<Coverage> baseCoverage; /* Offset to BaseCoverage table--from * beginning of MarkBasePos subtable */ HBUINT16 classCount; /* Number of classes defined for marks */ - OffsetTo<MarkArray> + Offset16To<MarkArray> markArray; /* Offset to MarkArray table--from * beginning of MarkBasePos subtable */ - OffsetTo<BaseArray> + Offset16To<BaseArray> baseArray; /* Offset to BaseArray table--from * beginning of MarkBasePos subtable */ public: @@ -2046,12 +2213,12 @@ typedef AnchorMatrix LigatureAttach; /* component-major-- * ordered by class--zero-based. */ /* Array of LigatureAttach tables ordered by LigatureCoverage Index */ -struct LigatureArray : OffsetListOf<LigatureAttach> +struct LigatureArray : List16OfOffset16To<LigatureAttach> { template <typename Iterator, hb_requires (hb_is_iterator (Iterator))> bool subset (hb_subset_context_t *c, - Iterator coverage, + Iterator coverage, unsigned class_count, const hb_map_t *klass_mapping) const { @@ -2067,11 +2234,16 @@ struct LigatureArray : OffsetListOf<LigatureAttach> auto *matrix = out->serialize_append (c->serializer); if (unlikely (!matrix)) return_trace (false); + const LigatureAttach& src = (this + _.second); + auto indexes = + + hb_range (src.rows * class_count) + | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); }) + ; matrix->serialize_subset (c, _.second, this, - class_count, - klass_mapping); + src.rows, + indexes); } return_trace (this->len); } @@ -2201,17 +2373,12 @@ struct MarkLigPosFormat1 | hb_map_retains_sorting (glyph_map) ; - if (!out->markCoverage.serialize (c->serializer, out) - .serialize (c->serializer, new_mark_coverage)) + if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage)) return_trace (false); - out->markArray.serialize (c->serializer, out) - .serialize (c->serializer, - &klass_mapping, - c->plan->layout_variation_idx_map, - &(this+markArray), - + mark_iter - | hb_map (hb_second)); + out->markArray.serialize_subset (c, markArray, this, + (this+markCoverage).iter (), + &klass_mapping); auto new_ligature_coverage = + hb_iter (this + ligatureCoverage) @@ -2219,8 +2386,7 @@ struct MarkLigPosFormat1 | hb_map_retains_sorting (glyph_map) ; - if (!out->ligatureCoverage.serialize (c->serializer, out) - .serialize (c->serializer, new_ligature_coverage)) + if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage)) return_trace (false); out->ligatureArray.serialize_subset (c, ligatureArray, this, @@ -2241,18 +2407,18 @@ struct MarkLigPosFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> markCoverage; /* Offset to Mark Coverage table--from * beginning of MarkLigPos subtable */ - OffsetTo<Coverage> + Offset16To<Coverage> ligatureCoverage; /* Offset to Ligature Coverage * table--from beginning of MarkLigPos * subtable */ HBUINT16 classCount; /* Number of defined mark classes */ - OffsetTo<MarkArray> + Offset16To<MarkArray> markArray; /* Offset to MarkArray table--from * beginning of MarkLigPos subtable */ - OffsetTo<LigatureArray> + Offset16To<LigatureArray> ligatureArray; /* Offset to LigatureArray table--from * beginning of MarkLigPos subtable */ public: @@ -2409,13 +2575,12 @@ struct MarkMarkPosFormat1 | hb_sink (new_coverage) ; - if (!out->mark1Coverage.serialize (c->serializer, out) - .serialize (c->serializer, new_coverage.iter ())) + if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) return_trace (false); - out->mark1Array.serialize (c->serializer, out) - .serialize (c->serializer, &klass_mapping, c->plan->layout_variation_idx_map, &(this+mark1Array), + mark1_iter - | hb_map (hb_second)); + out->mark1Array.serialize_subset (c, mark1Array, this, + (this+mark1Coverage).iter (), + &klass_mapping); unsigned mark2count = (this+mark2Array).rows; auto mark2_iter = @@ -2430,8 +2595,7 @@ struct MarkMarkPosFormat1 | hb_sink (new_coverage) ; - if (!out->mark2Coverage.serialize (c->serializer, out) - .serialize (c->serializer, new_coverage.iter ())) + if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) return_trace (false); hb_sorted_vector_t<unsigned> mark2_indexes; @@ -2444,8 +2608,8 @@ struct MarkMarkPosFormat1 | hb_sink (mark2_indexes) ; } - out->mark2Array.serialize (c->serializer, out) - .serialize (c->serializer, mark2_iter.len (), &(this+mark2Array), c->plan->layout_variation_idx_map, mark2_indexes.iter ()); + + out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ()); return_trace (true); } @@ -2462,19 +2626,19 @@ struct MarkMarkPosFormat1 protected: HBUINT16 format; /* Format identifier--format = 1 */ - OffsetTo<Coverage> + Offset16To<Coverage> mark1Coverage; /* Offset to Combining Mark1 Coverage * table--from beginning of MarkMarkPos * subtable */ - OffsetTo<Coverage> + Offset16To<Coverage> mark2Coverage; /* Offset to Combining Mark2 Coverage * table--from beginning of MarkMarkPos * subtable */ HBUINT16 classCount; /* Number of defined mark classes */ - OffsetTo<MarkArray> + Offset16To<MarkArray> mark1Array; /* Offset to Mark1Array table--from * beginning of MarkMarkPos subtable */ - OffsetTo<Mark2Array> + Offset16To<Mark2Array> mark2Array; /* Offset to Mark2Array table--from * beginning of MarkMarkPos subtable */ public: @@ -2663,7 +2827,7 @@ struct GPOS : GSUBGPOS bool subset (hb_subset_context_t *c) const { - hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_features); + hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features); return GSUBGPOS::subset<PosLookup> (&l); } |