fix GSUB table reading
Note: Hello! I'm new to the project, so apologies if I'm missing something.
Inkscape freezes if you click on the "Font features" tab with the Iosevka font selected.
I initially believed this to be an infinite loop in readOpenTypeGsubTable, but no, it just needs ~6 minutes to do its work.
This is because get_glyphs() needs to lookup the Unicode codepoint for a glyph.
It does so by bruteforcing the full 2^16 codepoint lookups, and stopping early when there's a matching glyph.
Iosevka has ~80 tables with about ~200k mapped glyphs, and many of these glyphs aren't mapped to any BMP codepoint, so the 2^16 lookups are performed for each and every one of them.
This MR does two things:
- makes the code efficient by performing all those lookups only once, and saving the results in an
std::unordered_map.- The map is populated lazily to avoid hurting performance on simple fonts.
- in addition, it also fixes the results by using
hb_face_collect_unicodes()to iterate over all the mappings of the font. This is more efficient than a bruteforce and supports non-BMP characters like emojis.- It still falls back to the bruteforce if
hb_face_collect_unicodesis not available.
- It still falls back to the bruteforce if
It now takes ~150ms and displays more glyphs than before.
Pending improvements
We're still dropping glyphs that aren't mapped to anything, or mapped to Variation Selectors.
But the thing is that we should work with glyph IDs directly, not codepoints. We don't want text, we want the user to compare the glyphs. The design of the "feature settings" UI could also be improved a bit, rendering each pair of glyphs side by side, and adding some spacing.