From 59387dbe43806d37e094bea15ee3b017a3fbaa8c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 5 Jun 2023 14:47:27 -0600 Subject: [PATCH] [subset/cff] Speed up sid mapping --- src/hb-ot-cff1-table.hh | 47 +++++++++++++++++++++++++++++------------ src/hb-subset-cff1.cc | 14 ++++++------ 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh index 20e6ad8bc..0cbf014be 100644 --- a/src/hb-ot-cff1-table.hh +++ b/src/hb-ot-cff1-table.hh @@ -391,16 +391,31 @@ struct Charset1_2 { return_trace (true); } - hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const + hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs, + code_pair_t *cache = nullptr) const { if (unlikely (glyph >= num_glyphs)) return 0; if (unlikely (glyph == 0)) return 0; - glyph--; - for (unsigned int i = 0;; i++) + hb_codepoint_t start_glyph = 1; + unsigned i = 0; + if (cache && likely (cache->glyph <= glyph)) { - if (glyph <= ranges[i].nLeft) - return (hb_codepoint_t) ranges[i].first + glyph; - glyph -= (ranges[i].nLeft + 1); + i = cache->code; + start_glyph = cache->glyph; + } + glyph -= start_glyph; + for (;; i++) + { + unsigned count = ranges[i].nLeft; + if (glyph <= count) + { + if (cache) + *cache = {i, start_glyph}; + return ranges[i].first + glyph; + } + count++; + start_glyph += count; + glyph -= count; } return 0; @@ -553,13 +568,14 @@ struct Charset } } - hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const + hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs, + code_pair_t *cache = nullptr) const { switch (format) { case 0: return u.format0.get_sid (glyph, num_glyphs); - case 1: return u.format1.get_sid (glyph, num_glyphs); - case 2: return u.format2.get_sid (glyph, num_glyphs); + case 1: return u.format1.get_sid (glyph, num_glyphs, cache); + case 2: return u.format2.get_sid (glyph, num_glyphs, cache); default:return 0; } } @@ -1211,13 +1227,14 @@ struct cff1 bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; } - hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const + hb_codepoint_t glyph_to_code (hb_codepoint_t glyph, + code_pair_t *glyph_to_sid_cache = nullptr) const { if (encoding != &Null (Encoding)) return encoding->get_code (glyph); else { - hb_codepoint_t sid = glyph_to_sid (glyph); + hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache); if (sid == 0) return 0; hb_codepoint_t code = 0; switch (topDict.EncodingOffset) @@ -1250,10 +1267,11 @@ struct cff1 return nullptr; } - hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const + hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph, + code_pair_t *cache = nullptr) const { if (charset != &Null (Charset)) - return charset->get_sid (glyph, num_glyphs); + return charset->get_sid (glyph, num_glyphs, cache); else { hb_codepoint_t sid = 0; @@ -1396,9 +1414,10 @@ struct cff1 /* TODO */ /* fill glyph names */ + code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) { - hb_codepoint_t sid = glyph_to_sid (gid); + hb_codepoint_t sid = glyph_to_sid (gid, &glyph_to_sid_cache); gname_t gname; gname.sid = sid; if (sid < cff1_std_strings_length) diff --git a/src/hb-subset-cff1.cc b/src/hb-subset-cff1.cc index f8b7591eb..0a6078379 100644 --- a/src/hb-subset-cff1.cc +++ b/src/hb-subset-cff1.cc @@ -413,6 +413,7 @@ struct cff_subset_plan { supp_codes.init (); + code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; subset_enc_num_codes = plan->num_output_glyphs () - 1; unsigned int glyph; auto it = hb_iter (plan->new_to_old_gid_list); @@ -431,7 +432,7 @@ struct cff_subset_plan { /* Retain the SID for the old missing glyph ID */ old_glyph = glyph; } - code = acc.glyph_to_code (old_glyph); + code = acc.glyph_to_code (old_glyph, &glyph_to_sid_cache); if (code == CFF_UNDEF_CODE) { subset_enc_num_codes = glyph - 1; @@ -447,7 +448,7 @@ struct cff_subset_plan { if (encoding != &Null (Encoding)) { - hb_codepoint_t sid = acc.glyph_to_sid (old_glyph); + hb_codepoint_t sid = acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache); encoding->get_supplement_codes (sid, supp_codes); for (unsigned int i = 0; i < supp_codes.length; i++) { @@ -473,7 +474,7 @@ struct cff_subset_plan { void plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan) { unsigned int size0, size_ranges; - unsigned sid, last_sid = CFF_UNDEF_CODE - 1; + unsigned last_sid = CFF_UNDEF_CODE - 1; if (unlikely (!subset_charset_ranges.resize (0))) { @@ -486,13 +487,14 @@ struct cff_subset_plan { nullptr; bool created_map = false; if (!glyph_to_sid_map && - ((plan->accelerator && plan->accelerator->cff_accelerator) || - plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.)) + ((plan->accelerator && plan->accelerator->cff_accelerator))) { created_map = true; glyph_to_sid_map = acc.create_glyph_to_sid_map (); } + code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; + unsigned int glyph; unsigned num_glyphs = plan->num_output_glyphs (); auto it = hb_iter (plan->new_to_old_gid_list); @@ -512,7 +514,7 @@ struct cff_subset_plan { /* Retain the SID for the old missing glyph ID */ old_glyph = glyph; } - sid = glyph_to_sid_map ? glyph_to_sid_map->arrayZ[old_glyph] : acc.glyph_to_sid (old_glyph); + unsigned sid = glyph_to_sid_map ? glyph_to_sid_map->arrayZ[old_glyph] : acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache); if (not_is_cid) sid = sidmap.add (sid);