[subset] speedup cmap4 subsetting for large codepoint counts. (#3178)

glyphIdArray generation implementation was O(n^2). Refactored to use a hashmap to reduce complexity. After the change subset time for a 22k codepoint subset went from 7s to 0.7s.
This commit is contained in:
Garret Rieger 2021-08-29 10:33:12 -06:00 committed by GitHub
parent fdce294120
commit b9a176e268
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 14 additions and 19 deletions

View File

@ -218,29 +218,24 @@ struct CmapSubtableFormat4
HBINT16 *idDelta,
unsigned segcount)
{
hb_hashmap_t<hb_codepoint_t, hb_codepoint_t> cp_to_gid;
+ it | hb_sink (cp_to_gid);
HBUINT16 *idRangeOffset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
if (unlikely (!c->check_success (idRangeOffset))) return nullptr;
if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr;
+ hb_range (segcount)
| hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; })
| hb_apply ([&] (const unsigned i)
{
idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
+ it
| hb_filter ([&] (const hb_item_type<Iterator> _) { return _.first >= startCode[i] && _.first <= endCode[i]; })
| hb_apply ([&] (const hb_item_type<Iterator> _)
{
HBUINT16 glyID;
glyID = _.second;
c->copy<HBUINT16> (glyID);
})
;
})
;
for (unsigned i : + hb_range (segcount)
| hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }))
{
idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
for (hb_codepoint_t cp = startCode[i]; cp <= endCode[i]; cp++)
{
HBUINT16 gid;
gid = cp_to_gid[cp];
c->copy<HBUINT16> (gid);
}
}
return idRangeOffset;
}