instancer: prune unused name records after instancing

This commit is contained in:
Cosimo Lupo 2019-05-07 17:55:50 +01:00
parent 0010a3cd9a
commit 5a530880c0
No known key found for this signature in database
GPG Key ID: 20D4A261E4A0E642
3 changed files with 92 additions and 6 deletions

View File

@ -21,6 +21,7 @@ from fontTools import varLib
from fontTools.varLib import builder from fontTools.varLib import builder
from fontTools.varLib.mvar import MVAR_ENTRIES from fontTools.varLib.mvar import MVAR_ENTRIES
from fontTools.varLib.merger import MutatorMerger from fontTools.varLib.merger import MutatorMerger
from contextlib import contextmanager
import collections import collections
from copy import deepcopy from copy import deepcopy
import logging import logging
@ -540,6 +541,50 @@ def instantiateSTAT(varfont, location):
stat.DesignAxisCount = len(stat.DesignAxisRecord.Axis) stat.DesignAxisCount = len(stat.DesignAxisRecord.Axis)
def getVariationNameIDs(varfont):
used = []
if "fvar" in varfont:
fvar = varfont["fvar"]
for axis in fvar.axes:
used.append(axis.axisNameID)
for instance in fvar.instances:
used.append(instance.subfamilyNameID)
if instance.postscriptNameID != 0xFFFF:
used.append(instance.postscriptNameID)
if "STAT" in varfont:
stat = varfont["STAT"].table
for axis in stat.DesignAxisRecord.Axis if stat.DesignAxisRecord else ():
used.append(axis.AxisNameID)
for value in stat.AxisValueArray.AxisValue if stat.AxisValueArray else ():
used.append(value.ValueNameID)
# nameIDs <= 255 are reserved by OT spec so we don't touch them
return {nameID for nameID in used if nameID > 255}
@contextmanager
def pruningUnusedNames(varfont):
origNameIDs = getVariationNameIDs(varfont)
yield
log.info("Pruning name table")
exclude = origNameIDs - getVariationNameIDs(varfont)
varfont["name"].names[:] = [
record for record in varfont["name"].names if record.nameID not in exclude
]
if "ltag" in varfont:
# Drop the whole 'ltag' table if all the language-dependent Unicode name
# records that reference it have been dropped.
# TODO: Only prune unused ltag tags, renumerating langIDs accordingly.
# Note ltag can also be used by feat or morx tables, so check those too.
if not any(
record
for record in varfont["name"].names
if record.platformID == 0 and record.langID != 0xFFFF
):
del varfont["ltag"]
def normalize(value, triple, avar_mapping): def normalize(value, triple, avar_mapping):
value = normalizeValue(value, triple) value = normalizeValue(value, triple)
if avar_mapping: if avar_mapping:
@ -622,10 +667,11 @@ def instantiateVariableFont(varfont, axis_limits, inplace=False, optimize=True):
if "avar" in varfont: if "avar" in varfont:
instantiateAvar(varfont, normalized_limits) instantiateAvar(varfont, normalized_limits)
if "STAT" in varfont: with pruningUnusedNames(varfont):
instantiateSTAT(varfont, axis_limits) if "STAT" in varfont:
instantiateSTAT(varfont, axis_limits)
instantiateFvar(varfont, axis_limits) instantiateFvar(varfont, axis_limits)
return varfont return varfont

View File

@ -12,12 +12,12 @@
<!-- Most of this table will be recalculated by the compiler --> <!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/> <tableVersion value="1.0"/>
<fontRevision value="2.001"/> <fontRevision value="2.001"/>
<checkSumAdjustment value="0x710b1826"/> <checkSumAdjustment value="0x7815682b"/>
<magicNumber value="0x5f0f3cf5"/> <magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/> <flags value="00000000 00000011"/>
<unitsPerEm value="1000"/> <unitsPerEm value="1000"/>
<created value="Tue Mar 5 00:05:14 2019"/> <created value="Tue Mar 5 00:05:14 2019"/>
<modified value="Fri May 3 10:34:01 2019"/> <modified value="Wed May 8 10:35:06 2019"/>
<xMin value="40"/> <xMin value="40"/>
<yMin value="-200"/> <yMin value="-200"/>
<xMax value="450"/> <xMax value="450"/>
@ -186,6 +186,9 @@
</glyf> </glyf>
<name> <name>
<namerecord nameID="257" platformID="0" platEncID="4" langID="0x0">
Bräiti
</namerecord>
<namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True"> <namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
Weight Weight
</namerecord> </namerecord>
@ -306,6 +309,9 @@
<namerecord nameID="295" platformID="1" platEncID="0" langID="0x0" unicode="True"> <namerecord nameID="295" platformID="1" platEncID="0" langID="0x0" unicode="True">
Upright Upright
</namerecord> </namerecord>
<namerecord nameID="296" platformID="1" platEncID="0" langID="0x0" unicode="True">
TestVariableFont-XCdBd
</namerecord>
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x409"> <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
Copyright 2015 Google Inc. All Rights Reserved. Copyright 2015 Google Inc. All Rights Reserved.
</namerecord> </namerecord>
@ -462,6 +468,9 @@
<namerecord nameID="295" platformID="3" platEncID="1" langID="0x409"> <namerecord nameID="295" platformID="3" platEncID="1" langID="0x409">
Upright Upright
</namerecord> </namerecord>
<namerecord nameID="296" platformID="3" platEncID="1" langID="0x409">
TestVariableFont-XCdBd
</namerecord>
</name> </name>
<post> <post>
@ -1008,7 +1017,8 @@
</NamedInstance> </NamedInstance>
<!-- ExtraCondensed ExtraBold --> <!-- ExtraCondensed ExtraBold -->
<NamedInstance flags="0x0" subfamilyNameID="292"> <!-- PostScript: TestVariableFont-XCdBd -->
<NamedInstance flags="0x0" postscriptNameID="296" subfamilyNameID="292">
<coord axis="wght" value="800.0"/> <coord axis="wght" value="800.0"/>
<coord axis="wdth" value="70.0"/> <coord axis="wdth" value="70.0"/>
</NamedInstance> </NamedInstance>
@ -1076,6 +1086,12 @@
</glyphVariations> </glyphVariations>
</gvar> </gvar>
<ltag>
<version value="1"/>
<flags value="0"/>
<LanguageTag tag="gsw-LI"/>
</ltag>
<vmtx> <vmtx>
<mtx name=".notdef" height="1000" tsb="100"/> <mtx name=".notdef" height="1000" tsb="100"/>
<mtx name="hyphen" height="536" tsb="229"/> <mtx name="hyphen" height="536" tsb="229"/>

View File

@ -966,3 +966,27 @@ class InstantiateSTATTest(object):
instancer.instantiateSTAT(varfont, {"wght": 100}) instancer.instantiateSTAT(varfont, {"wght": 100})
assert "STAT" not in varfont assert "STAT" not in varfont
def test_pruningUnusedNames(varfont):
varNameIDs = instancer.getVariationNameIDs(varfont)
assert varNameIDs == set(range(256, 296 + 1))
fvar = varfont["fvar"]
stat = varfont["STAT"].table
with instancer.pruningUnusedNames(varfont):
del fvar.axes[0] # Weight (nameID=256)
del fvar.instances[0] # Thin (nameID=258)
del stat.DesignAxisRecord.Axis[0] # Weight (nameID=256)
del stat.AxisValueArray.AxisValue[0] # Thin (nameID=258)
assert not any(n for n in varfont["name"].names if n.nameID in {256, 258})
with instancer.pruningUnusedNames(varfont):
del varfont["fvar"]
del varfont["STAT"]
assert not any(n for n in varfont["name"].names if n.nameID in varNameIDs)
assert "ltag" not in varfont