From f9fbe4817ebcb0c88865dc19b7a6e616842a7be6 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Fri, 23 Apr 2021 17:06:06 -0700 Subject: [PATCH] [subset] implement value record optimization for PairPosFormat2. --- src/hb-ot-layout-gpos-table.hh | 59 +++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 961ee5826..35286b538 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -1029,7 +1029,6 @@ struct SinglePos u.format = format; switch (u.format) { - // TODO(grieger): pass reference to src lookup instead of separate src + format case 1: u.format1.serialize (c, src, glyph_val_iter_pairs, @@ -1517,9 +1516,6 @@ struct PairPosFormat2 auto *out = c->serializer->start_embed (*this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); out->format = format; - // TODO(grieger): compute new formats - out->valueFormat1 = valueFormat1; - out->valueFormat2 = valueFormat2; hb_map_t klass1_map; out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, &(this + coverage)); @@ -1532,21 +1528,22 @@ struct PairPosFormat2 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.copy_values (c->serializer, valueFormat1, this, &values[idx], c->plan->layout_variation_idx_map); - valueFormat2.copy_values (c->serializer, valueFormat2, this, &values[idx + len1], c->plan->layout_variation_idx_map); - }) - ; - }) - ; + hb_pair_t newFormats = hb_pair (valueFormat1, valueFormat2); + if (c->plan->drop_hints) + 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; @@ -1561,6 +1558,30 @@ struct PairPosFormat2 return_trace (out->class1Count && out->class2Count && bool (it)); } + + hb_pair_t 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);