[subset] set emptied CFF charstrings to 'endchar' with --retain-gids

Part of #1446
This commit is contained in:
Cosimo Lupo 2019-01-15 14:07:54 +00:00
parent 71dbe2daea
commit af1a0d1fe5
No known key found for this signature in database
GPG Key ID: 59D54DB0C9976482
2 changed files with 73 additions and 31 deletions

View File

@ -104,37 +104,44 @@ def subset_glyphs(self, s):
font = cff[fontname]
cs = font.CharStrings
# Load all glyphs
for g in font.charset:
if g not in s.glyphs: continue
c, _ = cs.getItemAndSelector(g)
if cs.charStringsAreIndexed:
indices = [i for i,g in enumerate(font.charset) if g in s.glyphs]
csi = cs.charStringsIndex
csi.items = [csi.items[i] for i in indices]
del csi.file, csi.offsets
if hasattr(font, "FDSelect"):
sel = font.FDSelect
# XXX We want to set sel.format to None, such that the
# most compact format is selected. However, OTS was
# broken and couldn't parse a FDSelect format 0 that
# happened before CharStrings. As such, always force
# format 3 until we fix cffLib to always generate
# FDSelect after CharStrings.
# https://github.com/khaledhosny/ots/pull/31
#sel.format = None
sel.format = 3
sel.gidArray = [sel.gidArray[i] for i in indices]
cs.charStrings = {g:indices.index(v)
for g,v in cs.charStrings.items()
if g in s.glyphs}
if s.options.retain_gids:
for g in cs.keys():
if g in s.glyphs_emptied:
c = cs[g]
c.decompile()
c.program = ["endchar"]
else:
cs.charStrings = {g:v
for g,v in cs.charStrings.items()
if g in s.glyphs}
font.charset = [g for g in font.charset if g in s.glyphs]
font.numGlyphs = len(font.charset)
# Load all glyphs
for g in font.charset:
if g not in s.glyphs: continue
c, _ = cs.getItemAndSelector(g)
if cs.charStringsAreIndexed:
indices = [i for i,g in enumerate(font.charset) if g in s.glyphs]
csi = cs.charStringsIndex
csi.items = [csi.items[i] for i in indices]
del csi.file, csi.offsets
if hasattr(font, "FDSelect"):
sel = font.FDSelect
# XXX We want to set sel.format to None, such that the
# most compact format is selected. However, OTS was
# broken and couldn't parse a FDSelect format 0 that
# happened before CharStrings. As such, always force
# format 3 until we fix cffLib to always generate
# FDSelect after CharStrings.
# https://github.com/khaledhosny/ots/pull/31
#sel.format = None
sel.format = 3
sel.gidArray = [sel.gidArray[i] for i in indices]
cs.charStrings = {g:indices.index(v)
for g,v in cs.charStrings.items()
if g in s.glyphs}
else:
cs.charStrings = {g:v
for g,v in cs.charStrings.items()
if g in s.glyphs}
font.charset = [g for g in font.charset if g in s.glyphs]
font.numGlyphs = len(font.charset)
return True # any(cff[fontname].numGlyphs for fontname in cff.keys())

View File

@ -475,7 +475,7 @@ class SubsetTest(unittest.TestCase):
subset.main([fontpath, "--recalc-timestamp", "--output-file=%s" % subsetpath, "*"])
self.assertLess(modified, TTFont(subsetpath)['head'].modified)
def test_retain_gids(self):
def test_retain_gids_ttf(self):
_, fontpath = self.compile_font(self.getpath("TestTTF-Regular.ttx"), ".ttf")
font = TTFont(fontpath)
@ -507,6 +507,41 @@ class SubsetTest(unittest.TestCase):
self.assertGreater(glyf["A"].numberOfContours, 0)
self.assertEqual(glyf["B"].numberOfContours, 0)
def test_retain_gids_otf(self):
_, fontpath = self.compile_font(self.getpath("TestOTF-Regular.ttx"), ".otf")
font = TTFont(fontpath)
self.assertEqual(font["hmtx"]["A"], (500, 132))
self.assertEqual(font["hmtx"]["B"], (400, 132))
font["CFF "].cff[0].decompileAllCharStrings()
cs = font["CFF "].cff[0].CharStrings
self.assertGreater(len(cs["A"].program), 0)
self.assertGreater(len(cs["B"].program), 0)
subsetpath = self.temp_path(".ttf")
subset.main(
[
fontpath,
"--retain-gids",
"--output-file=%s" % subsetpath,
"--glyph-names",
"A",
]
)
subsetfont = TTFont(subsetpath)
self.assertEqual(subsetfont.getGlyphOrder(), font.getGlyphOrder())
hmtx = subsetfont["hmtx"]
self.assertEqual(hmtx["A"], (500, 132))
self.assertEqual(hmtx["B"], (0, 0))
subsetfont["CFF "].cff[0].decompileAllCharStrings()
cs = subsetfont["CFF "].cff[0].CharStrings
self.assertGreater(len(cs["A"].program), 0)
self.assertEqual(cs["B"].program, ["endchar"])
if __name__ == "__main__":
sys.exit(unittest.main())