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.mvar import MVAR_ENTRIES
from fontTools.varLib.merger import MutatorMerger
from contextlib import contextmanager
import collections
from copy import deepcopy
import logging
@ -540,6 +541,50 @@ def instantiateSTAT(varfont, location):
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):
value = normalizeValue(value, triple)
if avar_mapping:
@ -622,10 +667,11 @@ def instantiateVariableFont(varfont, axis_limits, inplace=False, optimize=True):
if "avar" in varfont:
instantiateAvar(varfont, normalized_limits)
if "STAT" in varfont:
instantiateSTAT(varfont, axis_limits)
with pruningUnusedNames(varfont):
if "STAT" in varfont:
instantiateSTAT(varfont, axis_limits)
instantiateFvar(varfont, axis_limits)
instantiateFvar(varfont, axis_limits)
return varfont

View File

@ -12,12 +12,12 @@
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="2.001"/>
<checkSumAdjustment value="0x710b1826"/>
<checkSumAdjustment value="0x7815682b"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<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"/>
<yMin value="-200"/>
<xMax value="450"/>
@ -186,6 +186,9 @@
</glyf>
<name>
<namerecord nameID="257" platformID="0" platEncID="4" langID="0x0">
Bräiti
</namerecord>
<namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
Weight
</namerecord>
@ -306,6 +309,9 @@
<namerecord nameID="295" platformID="1" platEncID="0" langID="0x0" unicode="True">
Upright
</namerecord>
<namerecord nameID="296" platformID="1" platEncID="0" langID="0x0" unicode="True">
TestVariableFont-XCdBd
</namerecord>
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
Copyright 2015 Google Inc. All Rights Reserved.
</namerecord>
@ -462,6 +468,9 @@
<namerecord nameID="295" platformID="3" platEncID="1" langID="0x409">
Upright
</namerecord>
<namerecord nameID="296" platformID="3" platEncID="1" langID="0x409">
TestVariableFont-XCdBd
</namerecord>
</name>
<post>
@ -1008,7 +1017,8 @@
</NamedInstance>
<!-- 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="wdth" value="70.0"/>
</NamedInstance>
@ -1076,6 +1086,12 @@
</glyphVariations>
</gvar>
<ltag>
<version value="1"/>
<flags value="0"/>
<LanguageTag tag="gsw-LI"/>
</ltag>
<vmtx>
<mtx name=".notdef" height="1000" tsb="100"/>
<mtx name="hyphen" height="536" tsb="229"/>

View File

@ -966,3 +966,27 @@ class InstantiateSTATTest(object):
instancer.instantiateSTAT(varfont, {"wght": 100})
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