[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
This commit is contained in:
Behdad Esfahbod 2022-05-16 15:41:11 -06:00
parent b58bfd9818
commit 3fbac0942d
1 changed files with 53 additions and 21 deletions

View File

@ -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<gname_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<gname_t> *names = glyph_names.get ();
if (unlikely (!names))
{
names = (hb_sorted_vector_t<gname_t> *) calloc (sizeof (hb_sorted_vector_t<gname_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<gname_t> glyph_names;
mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names;
typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
};