From 3fbac0942da80457f8c226105f5a4a1bdfe502f5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 16 May 2022 15:41:11 -0600 Subject: [PATCH] [cff1] Lazy-load & sort glyph names Improves subset benchmarks by up to 70% for small CFF1 subset of non-CID fonts! BM_subset/subset_glyphs/SourceSansPro-Regular.otf/10 -0.7067 -0.7071 1 0 1 0 BM_subset/subset_glyphs/SourceSansPro-Regular.otf/64 -0.4817 -0.4824 1 0 1 0 BM_subset/subset_glyphs/SourceSansPro-Regular.otf/512 -0.1948 -0.1956 2 2 2 2 BM_subset/subset_glyphs/SourceSansPro-Regular.otf/2000 -0.0767 -0.0761 6 6 6 6 --- src/hb-ot-cff1-table.hh | 74 +++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh index 2f2a27888..3026d6881 100644 --- a/src/hb-ot-cff1-table.hh +++ b/src/hb-ot-cff1-table.hh @@ -1275,30 +1275,20 @@ struct cff1 { SUPER::init (face); + glyph_names.set_relaxed (nullptr); + if (!is_valid ()) return; if (is_CID ()) return; - /* fill glyph_names */ - for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) - { - hb_codepoint_t sid = glyph_to_sid (gid); - gname_t gname; - gname.sid = sid; - if (sid < cff1_std_strings_length) - gname.name = cff1_std_strings (sid); - else - { - hb_ubytes_t ustr = (*stringIndex)[sid - cff1_std_strings_length]; - gname.name = hb_bytes_t ((const char*)ustr.arrayZ, ustr.length); - } - if (unlikely (!gname.name.length)) { fini (); return; } - glyph_names.push (gname); - } - glyph_names.qsort (); } ~accelerator_t () { - glyph_names.fini (); + hb_sorted_vector_t *names = glyph_names.get_relaxed (); + if (names) + { + names->fini (); + free (names); + } SUPER::fini (); } @@ -1306,9 +1296,9 @@ struct cff1 bool get_glyph_name (hb_codepoint_t glyph, char *buf, unsigned int buf_len) const { - if (!buf_len) return true; if (unlikely (!is_valid ())) return false; if (is_CID()) return false; + if (unlikely (!buf_len)) return true; hb_codepoint_t sid = glyph_to_sid (glyph); const char *str; size_t str_len; @@ -1334,11 +1324,53 @@ struct cff1 bool get_glyph_from_name (const char *name, int len, hb_codepoint_t *glyph) const { + if (unlikely (!is_valid ())) return false; + if (is_CID()) return false; if (len < 0) len = strlen (name); if (unlikely (!len)) return false; + retry: + hb_sorted_vector_t *names = glyph_names.get (); + if (unlikely (!names)) + { + names = (hb_sorted_vector_t *) calloc (sizeof (hb_sorted_vector_t), 1); + if (likely (names)) + { + names->init (); + /* TODO */ + + /* fill glyph names */ + for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) + { + hb_codepoint_t sid = glyph_to_sid (gid); + gname_t gname; + gname.sid = sid; + if (sid < cff1_std_strings_length) + gname.name = cff1_std_strings (sid); + else + { + hb_ubytes_t ustr = (*stringIndex)[sid - cff1_std_strings_length]; + gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length); + } + if (unlikely (!gname.name.arrayZ)) + gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */ + names->push (gname); + } + names->qsort (); + } + if (unlikely (!glyph_names.cmpexch (nullptr, names))) + { + if (names) + { + names->fini (); + free (names); + } + goto retry; + } + } + gname_t key = { hb_bytes_t (name, len), 0 }; - const gname_t *gname = glyph_names.bsearch (key); + const gname_t *gname = glyph_names->bsearch (key); if (!gname) return false; hb_codepoint_t gid = sid_to_glyph (gname->sid); if (!gid && gname->sid) return false; @@ -1369,7 +1401,7 @@ struct cff1 int cmp (const gname_t &a) const { return cmp (&a, this); } }; - hb_sorted_vector_t glyph_names; + mutable hb_atomic_ptr_t> glyph_names; typedef accelerator_templ_t SUPER; };