From c8f6ae1df7d559180c40511a8ad8c2da7b303dff Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 8 Jul 2023 20:21:49 -0600 Subject: [PATCH] [subset/hvar/retaingids] Synthesize a DeltaSetIndexMap if needed Before we were emitting the entire VarStore rows if advMap was Null. Instead, synthesize an advMap. 20% speed up in subset_glyphs/SourceHanSans-VF.otf/retaingids benchmark. --- src/hb-ot-var-hvar-table.hh | 32 +++++------------- .../fonts/AdobeVFPrototype.ac.retaingids.otf | Bin 4584 -> 4584 bytes .../fonts/SourceSansVariable-Roman.abc.ttf | Bin 3196 -> 5160 bytes ...SourceSansVariable-Roman.ac.retaingids.ttf | Bin 2976 -> 4584 bytes .../api/fonts/SourceSansVariable-Roman.ac.ttf | Bin 2964 -> 4580 bytes 5 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/hb-ot-var-hvar-table.hh b/src/hb-ot-var-hvar-table.hh index ea81ee86d..742ba8686 100644 --- a/src/hb-ot-var-hvar-table.hh +++ b/src/hb-ot-var-hvar-table.hh @@ -45,7 +45,8 @@ struct index_map_subset_plan_t void init (const DeltaSetIndexMap &index_map, hb_inc_bimap_t &outer_map, hb_vector_t &inner_sets, - const hb_subset_plan_t *plan) + const hb_subset_plan_t *plan, + bool bypass_empty = true) { map_count = 0; outer_bit_count = 0; @@ -53,11 +54,10 @@ struct index_map_subset_plan_t max_inners.init (); output_map.init (); - if (&index_map == &Null (DeltaSetIndexMap)) return; + if (bypass_empty && !index_map.get_map_count ()) return; unsigned int last_val = (unsigned int)-1; hb_codepoint_t last_gid = HB_CODEPOINT_INVALID; - hb_codepoint_t num_gid = (hb_codepoint_t) hb_min (index_map.get_map_count (), plan->num_output_glyphs ()); outer_bit_count = (index_map.get_width () * 8) - index_map.get_inner_bit_count (); max_inners.resize (inner_sets.length); @@ -68,24 +68,17 @@ struct index_map_subset_plan_t unsigned count = new_to_old_gid_list.length; for (unsigned j = count; j; j--) { - hb_codepoint_t gid = new_to_old_gid_list[j - 1].first; - if (gid >= num_gid) continue; - - hb_codepoint_t old_gid = new_to_old_gid_list[j - 1].second; + hb_codepoint_t gid = new_to_old_gid_list.arrayZ[j - 1].first; + hb_codepoint_t old_gid = new_to_old_gid_list.arrayZ[j - 1].second; unsigned int v = index_map.map (old_gid); if (last_gid == HB_CODEPOINT_INVALID) { - if (gid + 1 != num_gid) - { - last_gid = gid + 1; - break; - } last_val = v; last_gid = gid; continue; } - if (v != last_val || gid + 1 != last_gid) + if (v != last_val) break; last_gid = gid; @@ -120,8 +113,6 @@ struct index_map_subset_plan_t const hb_vector_t &inner_maps, const hb_subset_plan_t *plan) { - if (input_map == &Null (DeltaSetIndexMap)) return; - for (unsigned int i = 0; i < max_inners.length; i++) { if (inner_maps[i].get_population () == 0) continue; @@ -183,7 +174,7 @@ struct hvarvvar_subset_plan_t if (unlikely (!index_map_plans.length || !inner_sets.length || !inner_maps.length)) return; bool retain_adv_map = false; - index_map_plans[0].init (*index_maps[0], outer_map, inner_sets, plan); + index_map_plans[0].init (*index_maps[0], outer_map, inner_sets, plan, false); if (index_maps[0] == &Null (DeltaSetIndexMap)) { retain_adv_map = plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS; @@ -200,15 +191,10 @@ struct hvarvvar_subset_plan_t if (retain_adv_map) { - hb_codepoint_t next_gid = 0; for (const auto &_ : plan->new_to_old_gid_list) { - hb_codepoint_t gid = _.first; - - inner_maps[0].skip (gid - next_gid); - - inner_maps[0].add (gid); - next_gid = gid + 1; + hb_codepoint_t old_gid = _.second; + inner_maps[0].add (old_gid); } } else diff --git a/test/api/fonts/AdobeVFPrototype.ac.retaingids.otf b/test/api/fonts/AdobeVFPrototype.ac.retaingids.otf index 8ff99c625cc4af1b12b24234ec443d3677528f85..50b5be6d3cdc713ac1e64d1d9f34ea3420de70ab 100644 GIT binary patch delta 369 zcmaE%{6cwxSUtA_0|VP}cNbSTriAa&3=B*>3=9nB?g9S6I=)NZF)%Ri0P;KBgF~Hm z{Mqq}fq}6C$k*@)a|~ii{yPDvz5&Qj@CEYMGS5x|s&@eL%lw1&jiT38%mKwP00rFKca!V@Mk{DJ3`6@uZKyG410Ru|_ zkjW?mB-rv2b5mEmy$m#u6{w%pt02F)y7Hx!6dgr!56B#0D2gGOcqrlc9<;`0|Snv|GBXvFlDa}VcsEnQ31RAFO)^ypjiE(@{WD4^*8nDYe# zA-li!4QS~d$G*_UVzb}uk!$3sm566uNc>gFPvn@Ne62c*13Ejo7zjC>(VNmadDxGI z!k%zzymJcZMRHFmDm#-oYZ(>je<*MzvPvF%cmNDm@+!ev0# zl4mm%Xd=Qb*-f@)vW1cq#}zqA9?2@DJj5Vf{0FS+VDkU~ diff --git a/test/api/fonts/SourceSansVariable-Roman.abc.ttf b/test/api/fonts/SourceSansVariable-Roman.abc.ttf index dbbc388f63031a4cc9d024680bc1058b202d1689..01fb89ee3d8cf17a0d76abdb2b4a9ee150416bce 100644 GIT binary patch literal 5160 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 W2WiV!ZkzRhuL)UkMCY(-SN{#$fDiou literal 3196 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 a6BQDSMK8XaC%pu`n!m+ZG8cgVKI3mpAIwPr