subset: speed up subsetting of large fonts

Two small changes that significantly speed up subsetting of large fonts
such as Noto Sans CJK:

1. When emptying a charstring, simply empty its program rather than
attempting to decompile it first. (Only relevant when retaining GIDs.)

2. When reindexing charstrings, swap an accidentally-quadratic
implementation for one that is linear in the number of retained glyphs.
This commit is contained in:
aschmitz 2021-12-09 23:44:57 -06:00
parent fa0eae6658
commit d9f9466d63

View File

@ -53,8 +53,7 @@ def _empty_charstring(font, glyphName, isCFF2, ignoreWidth=False):
c, fdSelectIndex = font.CharStrings.getItemAndSelector(glyphName) c, fdSelectIndex = font.CharStrings.getItemAndSelector(glyphName)
if isCFF2 or ignoreWidth: if isCFF2 or ignoreWidth:
# CFF2 charstrings have no widths nor 'endchar' operators # CFF2 charstrings have no widths nor 'endchar' operators
c.decompile() c.setProgram([] if isCFF2 else ['endchar'])
c.program = [] if isCFF2 else ['endchar']
else: else:
if hasattr(font, 'FDArray') and font.FDArray is not None: if hasattr(font, 'FDArray') and font.FDArray is not None:
private = font.FDArray[fdSelectIndex].Private private = font.FDArray[fdSelectIndex].Private
@ -120,9 +119,12 @@ def subset_glyphs(self, s):
#sel.format = None #sel.format = None
sel.format = 3 sel.format = 3
sel.gidArray = [sel.gidArray[i] for i in indices] sel.gidArray = [sel.gidArray[i] for i in indices]
cs.charStrings = {g:indices.index(v) newCharStrings = {}
for g,v in cs.charStrings.items() for indicesIdx, charsetIdx in enumerate(indices):
if g in glyphs} g = font.charset[charsetIdx]
if g in cs.charStrings:
newCharStrings[g] = indicesIdx
cs.charStrings = newCharStrings
else: else:
cs.charStrings = {g:v cs.charStrings = {g:v
for g,v in cs.charStrings.items() for g,v in cs.charStrings.items()