[subset/cff1] Collect glyph-to-sid map to avoid an O(n^2) algorithm

Saves 13 for largest benchmark:

BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/10000                    -0.1313         -0.1308            75            65            75            65

BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/4096                 -0.1009         -0.1004            54            48            54            48
BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/10000                -0.1067         -0.1066            70            62            69            62
This commit is contained in:
Behdad Esfahbod 2022-05-16 17:02:40 -06:00
parent b87f48e948
commit a4d98b63ea
2 changed files with 53 additions and 2 deletions

View File

@ -327,6 +327,12 @@ struct Charset0 {
return sids[glyph - 1];
}
void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
{
for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++)
mapping->set (gid, sids[gid - 1]);
}
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{
if (sid == 0)
@ -390,13 +396,28 @@ struct Charset1_2 {
for (unsigned int i = 0;; i++)
{
if (glyph <= ranges[i].nLeft)
return (hb_codepoint_t)ranges[i].first + glyph;
return (hb_codepoint_t) ranges[i].first + glyph;
glyph -= (ranges[i].nLeft + 1);
}
return 0;
}
void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
{
hb_codepoint_t gid = 1;
for (unsigned i = 0;; i++)
{
hb_codepoint_t sid = ranges[i].first;
unsigned count = ranges[i].nLeft + 1;
for (unsigned j = 0; j < count; j++)
mapping->set (gid++, sid++);
if (gid >= num_glyphs)
break;
}
}
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{
if (sid == 0) return 0;
@ -532,6 +553,17 @@ struct Charset
}
}
void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
{
switch (format)
{
case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
default:return;
}
}
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{
switch (format)
@ -1196,6 +1228,19 @@ struct cff1
}
}
hb_map_t *create_glyph_to_sid_map () const
{
if (charset != &Null (Charset))
{
hb_map_t *mapping = hb_map_create ();
mapping->set (0, 0);
charset->collect_glyph_to_sid_map (mapping, num_glyphs);
return mapping;
}
else
return nullptr;
}
hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
{
if (charset != &Null (Charset))

View File

@ -442,6 +442,9 @@ struct cff_subset_plan {
return;
}
bool use_glyph_to_sid_map = plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.;
hb_map_t *glyph_to_sid_map = use_glyph_to_sid_map ? acc.create_glyph_to_sid_map () : nullptr;
unsigned int glyph;
for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++)
{
@ -451,7 +454,7 @@ struct cff_subset_plan {
/* Retain the SID for the old missing glyph ID */
old_glyph = glyph;
}
sid = acc.glyph_to_sid (old_glyph);
sid = glyph_to_sid_map ? glyph_to_sid_map->get (old_glyph) : acc.glyph_to_sid (old_glyph);
if (!acc.is_CID ())
sid = sidmap.add (sid);
@ -464,6 +467,9 @@ struct cff_subset_plan {
last_sid = sid;
}
if (glyph_to_sid_map)
hb_map_destroy (glyph_to_sid_map);
bool two_byte = subset_charset_ranges.complete (glyph);
size0 = Charset0::min_size + HBUINT16::static_size * (plan->num_output_glyphs () - 1);