[varLib] Rename fields in fvar, to accommodate for postscriptNameID
This commit is contained in:
parent
8e675db59b
commit
ae93928275
@ -2368,8 +2368,10 @@ def prune_pre_subset(self, font, options):
|
||||
nameIDs = set(options.name_IDs)
|
||||
fvar = font.get('fvar')
|
||||
if fvar:
|
||||
nameIDs.update([inst.nameID for inst in fvar.instances])
|
||||
nameIDs.update([axis.nameID for axis in fvar.axes])
|
||||
nameIDs.update([axis.axisNameID for axis in fvar.axes])
|
||||
nameIDs.update([inst.subfamilyNameID for inst in fvar.instances])
|
||||
nameIDs.update([inst.postscriptNameID for inst in fvar.instances
|
||||
if inst.postscriptNameID != 0xFFFF])
|
||||
if '*' not in options.name_IDs:
|
||||
self.names = [n for n in self.names if n.nameID in nameIDs]
|
||||
if not options.name_legacy:
|
||||
|
12
Lib/fontTools/subset/testdata/TestGVAR.ttx
vendored
12
Lib/fontTools/subset/testdata/TestGVAR.ttx
vendored
@ -394,31 +394,31 @@
|
||||
<MinValue>100.0</MinValue>
|
||||
<DefaultValue>400.0</DefaultValue>
|
||||
<MaxValue>900.0</MaxValue>
|
||||
<NameID>257</NameID>
|
||||
<AxisNameID>257</AxisNameID>
|
||||
</Axis>
|
||||
|
||||
<!-- Thin -->
|
||||
<NamedInstance nameID="258">
|
||||
<NamedInstance subfamilyNameID="258">
|
||||
<coord axis="wght" value="100.0"/>
|
||||
</NamedInstance>
|
||||
|
||||
<!-- Light -->
|
||||
<NamedInstance nameID="259">
|
||||
<NamedInstance subfamilyNameID="259">
|
||||
<coord axis="wght" value="300.0"/>
|
||||
</NamedInstance>
|
||||
|
||||
<!-- Regular -->
|
||||
<NamedInstance nameID="260">
|
||||
<NamedInstance subfamilyNameID="260">
|
||||
<coord axis="wght" value="400.0"/>
|
||||
</NamedInstance>
|
||||
|
||||
<!-- Bold -->
|
||||
<NamedInstance nameID="261">
|
||||
<NamedInstance subfamilyNameID="261">
|
||||
<coord axis="wght" value="700.0"/>
|
||||
</NamedInstance>
|
||||
|
||||
<!-- Black -->
|
||||
<NamedInstance nameID="262">
|
||||
<NamedInstance subfamilyNameID="262">
|
||||
<coord axis="wght" value="900.0"/>
|
||||
</NamedInstance>
|
||||
</fvar>
|
||||
|
@ -25,31 +25,31 @@
|
||||
<MinValue>100.0</MinValue>
|
||||
<DefaultValue>400.0</DefaultValue>
|
||||
<MaxValue>900.0</MaxValue>
|
||||
<NameID>257</NameID>
|
||||
<AxisNameID>257</AxisNameID>
|
||||
</Axis>
|
||||
|
||||
<!-- Thin -->
|
||||
<NamedInstance nameID="258">
|
||||
<NamedInstance subfamilyNameID="258">
|
||||
<coord axis="wght" value="100.0"/>
|
||||
</NamedInstance>
|
||||
|
||||
<!-- Light -->
|
||||
<NamedInstance nameID="259">
|
||||
<NamedInstance subfamilyNameID="259">
|
||||
<coord axis="wght" value="300.0"/>
|
||||
</NamedInstance>
|
||||
|
||||
<!-- Regular -->
|
||||
<NamedInstance nameID="260">
|
||||
<NamedInstance subfamilyNameID="260">
|
||||
<coord axis="wght" value="400.0"/>
|
||||
</NamedInstance>
|
||||
|
||||
<!-- Bold -->
|
||||
<NamedInstance nameID="261">
|
||||
<NamedInstance subfamilyNameID="261">
|
||||
<coord axis="wght" value="700.0"/>
|
||||
</NamedInstance>
|
||||
|
||||
<!-- Black -->
|
||||
<NamedInstance nameID="262">
|
||||
<NamedInstance subfamilyNameID="262">
|
||||
<coord axis="wght" value="900.0"/>
|
||||
</NamedInstance>
|
||||
</fvar>
|
||||
|
@ -24,31 +24,31 @@
|
||||
<MinValue>100.0</MinValue>
|
||||
<DefaultValue>400.0</DefaultValue>
|
||||
<MaxValue>900.0</MaxValue>
|
||||
<NameID>257</NameID>
|
||||
<AxisNameID>257</AxisNameID>
|
||||
</Axis>
|
||||
|
||||
<!-- Thin -->
|
||||
<NamedInstance nameID="258">
|
||||
<NamedInstance subfamilyNameID="258">
|
||||
<coord axis="wght" value="100.0"/>
|
||||
</NamedInstance>
|
||||
|
||||
<!-- Light -->
|
||||
<NamedInstance nameID="259">
|
||||
<NamedInstance subfamilyNameID="259">
|
||||
<coord axis="wght" value="300.0"/>
|
||||
</NamedInstance>
|
||||
|
||||
<!-- Regular -->
|
||||
<NamedInstance nameID="260">
|
||||
<NamedInstance subfamilyNameID="260">
|
||||
<coord axis="wght" value="400.0"/>
|
||||
</NamedInstance>
|
||||
|
||||
<!-- Bold -->
|
||||
<NamedInstance nameID="261">
|
||||
<NamedInstance subfamilyNameID="261">
|
||||
<coord axis="wght" value="700.0"/>
|
||||
</NamedInstance>
|
||||
|
||||
<!-- Black -->
|
||||
<NamedInstance nameID="262">
|
||||
<NamedInstance subfamilyNameID="262">
|
||||
<coord axis="wght" value="900.0"/>
|
||||
</NamedInstance>
|
||||
</fvar>
|
||||
|
@ -29,12 +29,12 @@ FVAR_AXIS_FORMAT = """
|
||||
defaultValue: 16.16F
|
||||
maxValue: 16.16F
|
||||
flags: H
|
||||
nameID: H
|
||||
axisNameID: H
|
||||
"""
|
||||
|
||||
FVAR_INSTANCE_FORMAT = """
|
||||
> # big endian
|
||||
nameID: H
|
||||
subfamilyNameID: H
|
||||
flags: H
|
||||
"""
|
||||
|
||||
@ -47,6 +47,9 @@ class table__f_v_a_r(DefaultTable.DefaultTable):
|
||||
self.instances = []
|
||||
|
||||
def compile(self, ttFont):
|
||||
instanceSize = sstruct.calcsize(FVAR_INSTANCE_FORMAT) + (len(self.axes) * 4)
|
||||
if any(instance.postscriptNameID != 0xFFFF for instance in self.instances):
|
||||
instanceSize += 2
|
||||
header = {
|
||||
"version": 0x00010000,
|
||||
"offsetToData": sstruct.calcsize(FVAR_HEADER_FORMAT),
|
||||
@ -54,12 +57,12 @@ class table__f_v_a_r(DefaultTable.DefaultTable):
|
||||
"axisCount": len(self.axes),
|
||||
"axisSize": sstruct.calcsize(FVAR_AXIS_FORMAT),
|
||||
"instanceCount": len(self.instances),
|
||||
"instanceSize": sstruct.calcsize(FVAR_INSTANCE_FORMAT) + len(self.axes) * 4
|
||||
"instanceSize": instanceSize,
|
||||
}
|
||||
result = [sstruct.pack(FVAR_HEADER_FORMAT, header)]
|
||||
result.extend([axis.compile() for axis in self.axes])
|
||||
axisTags = [axis.axisTag for axis in self.axes]
|
||||
result.extend([instance.compile(axisTags) for instance in self.instances])
|
||||
result.extend([instance.compile(axisTags)[:instanceSize] for instance in self.instances])
|
||||
return bytesjoin(result)
|
||||
|
||||
def decompile(self, data, ttFont):
|
||||
@ -102,7 +105,7 @@ class table__f_v_a_r(DefaultTable.DefaultTable):
|
||||
class Axis(object):
|
||||
def __init__(self):
|
||||
self.axisTag = None
|
||||
self.nameID = 0
|
||||
self.axisNameID = 0
|
||||
self.flags = 0 # not exposed in XML because spec defines no values
|
||||
self.minValue = -1.0
|
||||
self.defaultValue = 0.0
|
||||
@ -115,7 +118,7 @@ class Axis(object):
|
||||
sstruct.unpack2(FVAR_AXIS_FORMAT, data, self)
|
||||
|
||||
def toXML(self, writer, ttFont):
|
||||
name = ttFont["name"].getDebugName(self.nameID)
|
||||
name = ttFont["name"].getDebugName(self.axisNameID)
|
||||
if name is not None:
|
||||
writer.newline()
|
||||
writer.comment(name)
|
||||
@ -126,7 +129,7 @@ class Axis(object):
|
||||
("MinValue", str(self.minValue)),
|
||||
("DefaultValue", str(self.defaultValue)),
|
||||
("MaxValue", str(self.maxValue)),
|
||||
("NameID", str(self.nameID))]:
|
||||
("AxisNameID", str(self.axisNameID))]:
|
||||
writer.begintag(tag)
|
||||
writer.write(value)
|
||||
writer.endtag(tag)
|
||||
@ -140,12 +143,13 @@ class Axis(object):
|
||||
value = ''.join(value)
|
||||
if tag == "AxisTag":
|
||||
self.axisTag = Tag(value)
|
||||
elif tag in ["MinValue", "DefaultValue", "MaxValue", "NameID"]:
|
||||
elif tag in ["MinValue", "DefaultValue", "MaxValue", "AxisNameID"]:
|
||||
setattr(self, tag[0].lower() + tag[1:], safeEval(value))
|
||||
|
||||
class NamedInstance(object):
|
||||
def __init__(self):
|
||||
self.nameID = 0
|
||||
self.subfamilyNameID = 0
|
||||
self.postscriptNameID = 0xFFFF
|
||||
self.flags = 0 # not exposed in XML because spec defines no values
|
||||
self.coordinates = {}
|
||||
|
||||
@ -154,6 +158,7 @@ class NamedInstance(object):
|
||||
for axis in axisTags:
|
||||
fixedCoord = floatToFixed(self.coordinates[axis], 16)
|
||||
result.append(struct.pack(">l", fixedCoord))
|
||||
result.append(struct.pack(">H", self.postscriptNameID))
|
||||
return bytesjoin(result)
|
||||
|
||||
def decompile(self, data, axisTags):
|
||||
@ -163,14 +168,22 @@ class NamedInstance(object):
|
||||
value = struct.unpack(">l", data[pos : pos + 4])[0]
|
||||
self.coordinates[axis] = fixedToFloat(value, 16)
|
||||
pos += 4
|
||||
if pos + 2 <= len(data):
|
||||
self.postscriptNameID = struct.unpack(">H", data[pos : pos + 2])[0]
|
||||
else:
|
||||
self.postscriptNameID = 0xFFFF
|
||||
|
||||
def toXML(self, writer, ttFont):
|
||||
name = ttFont["name"].getDebugName(self.nameID)
|
||||
name = ttFont["name"].getDebugName(self.subfamilyNameID)
|
||||
if name is not None:
|
||||
writer.newline()
|
||||
writer.comment(name)
|
||||
writer.newline()
|
||||
writer.begintag("NamedInstance", nameID=self.nameID)
|
||||
if self.postscriptNameID == 0xFFFF:
|
||||
writer.begintag("NamedInstance", subfamilyNameID=self.subfamilyNameID)
|
||||
else:
|
||||
writer.begintag("NamedInstance", subfamilyNameID=self.subfamilyNameID,
|
||||
postscriptNameID=self.postscriptNameID, )
|
||||
writer.newline()
|
||||
for axis in ttFont["fvar"].axes:
|
||||
writer.simpletag("coord", axis=axis.axisTag,
|
||||
@ -181,7 +194,12 @@ class NamedInstance(object):
|
||||
|
||||
def fromXML(self, name, attrs, content, ttFont):
|
||||
assert(name == "NamedInstance")
|
||||
self.nameID = safeEval(attrs["nameID"])
|
||||
self.subfamilyNameID = safeEval(attrs["subfamilyNameID"])
|
||||
if "postscriptNameID" in attrs:
|
||||
self.postscriptNameID = safeEval(attrs["postscriptNameID"])
|
||||
else:
|
||||
self.postscriptNameID = 0xFFFF
|
||||
|
||||
for tag, elementAttrs, _ in filter(lambda t: type(t) is tuple, content):
|
||||
if tag == "coord":
|
||||
self.coordinates[elementAttrs["axis"]] = safeEval(elementAttrs["value"])
|
||||
|
@ -20,7 +20,7 @@ FVAR_DATA = deHexStr(
|
||||
FVAR_AXIS_DATA = deHexStr(
|
||||
"6F 70 73 7a ff ff 80 00 00 01 4c cd 00 01 80 00 00 00 01 59")
|
||||
|
||||
FVAR_INSTANCE_DATA = deHexStr("01 59 00 00 00 00 b3 33 00 00 80 00")
|
||||
FVAR_INSTANCE_DATA = deHexStr("01 59 00 00 00 00 b3 33 00 00 80 00 ff ff")
|
||||
|
||||
|
||||
def xml_lines(writer):
|
||||
@ -51,11 +51,11 @@ def MakeFont():
|
||||
axis.axisTag = tag
|
||||
axis.defaultValue = defaultValue
|
||||
axis.minValue, axis.maxValue = minValue, maxValue
|
||||
axis.nameID = AddName(font, name).nameID
|
||||
axis.axisNameID = AddName(font, name).nameID
|
||||
fvarTable.axes.append(axis)
|
||||
for name, weight, width in instances:
|
||||
inst = NamedInstance()
|
||||
inst.nameID = AddName(font, name).nameID
|
||||
inst.subfamilyNameID = AddName(font, name).nameID
|
||||
inst.coordinates = {"wght": weight, "wdth": width}
|
||||
fvarTable.instances.append(inst)
|
||||
return font
|
||||
@ -71,7 +71,7 @@ class FontVariationTableTest(unittest.TestCase):
|
||||
fvar = table__f_v_a_r()
|
||||
fvar.decompile(FVAR_DATA, ttFont={"fvar": fvar})
|
||||
self.assertEqual(["wght", "wdth"], [a.axisTag for a in fvar.axes])
|
||||
self.assertEqual([259, 260], [i.nameID for i in fvar.instances])
|
||||
self.assertEqual([259, 260], [i.subfamilyNameID for i in fvar.instances])
|
||||
|
||||
def test_toXML(self):
|
||||
font = MakeFont()
|
||||
@ -94,17 +94,17 @@ class FontVariationTableTest(unittest.TestCase):
|
||||
'<Axis>'
|
||||
' <AxisTag>slnt</AxisTag>'
|
||||
'</Axis>'
|
||||
'<NamedInstance nameID="765"/>'
|
||||
'<NamedInstance nameID="234"/>'):
|
||||
'<NamedInstance subfamilyNameID="765"/>'
|
||||
'<NamedInstance subfamilyNameID="234"/>'):
|
||||
fvar.fromXML(name, attrs, content, ttFont=None)
|
||||
self.assertEqual(["opsz", "slnt"], [a.axisTag for a in fvar.axes])
|
||||
self.assertEqual([765, 234], [i.nameID for i in fvar.instances])
|
||||
self.assertEqual([765, 234], [i.subfamilyNameID for i in fvar.instances])
|
||||
|
||||
|
||||
class AxisTest(unittest.TestCase):
|
||||
def test_compile(self):
|
||||
axis = Axis()
|
||||
axis.axisTag, axis.nameID = ('opsz', 345)
|
||||
axis.axisTag, axis.axisNameID = ('opsz', 345)
|
||||
axis.minValue, axis.defaultValue, axis.maxValue = (-0.5, 1.3, 1.5)
|
||||
self.assertEqual(FVAR_AXIS_DATA, axis.compile())
|
||||
|
||||
@ -112,7 +112,7 @@ class AxisTest(unittest.TestCase):
|
||||
axis = Axis()
|
||||
axis.decompile(FVAR_AXIS_DATA)
|
||||
self.assertEqual("opsz", axis.axisTag)
|
||||
self.assertEqual(345, axis.nameID)
|
||||
self.assertEqual(345, axis.axisNameID)
|
||||
self.assertEqual(-0.5, axis.minValue)
|
||||
self.assertEqual(1.3, axis.defaultValue)
|
||||
self.assertEqual(1.5, axis.maxValue)
|
||||
@ -122,7 +122,7 @@ class AxisTest(unittest.TestCase):
|
||||
axis = Axis()
|
||||
axis.decompile(FVAR_AXIS_DATA)
|
||||
AddName(font, "Optical Size").nameID = 256
|
||||
axis.nameID = 256
|
||||
axis.axisNameID = 256
|
||||
writer = XMLWriter(BytesIO())
|
||||
axis.toXML(writer, font)
|
||||
self.assertEqual([
|
||||
@ -133,7 +133,7 @@ class AxisTest(unittest.TestCase):
|
||||
'<MinValue>-0.5</MinValue>',
|
||||
'<DefaultValue>1.3</DefaultValue>',
|
||||
'<MaxValue>1.5</MaxValue>',
|
||||
'<NameID>256</NameID>',
|
||||
'<AxisNameID>256</AxisNameID>',
|
||||
'</Axis>'
|
||||
], xml_lines(writer))
|
||||
|
||||
@ -145,40 +145,40 @@ class AxisTest(unittest.TestCase):
|
||||
' <MinValue>100</MinValue>'
|
||||
' <DefaultValue>400</DefaultValue>'
|
||||
' <MaxValue>900</MaxValue>'
|
||||
' <NameID>256</NameID>'
|
||||
' <AxisNameID>256</AxisNameID>'
|
||||
'</Axis>'):
|
||||
axis.fromXML(name, attrs, content, ttFont=None)
|
||||
self.assertEqual("wght", axis.axisTag)
|
||||
self.assertEqual(100, axis.minValue)
|
||||
self.assertEqual(400, axis.defaultValue)
|
||||
self.assertEqual(900, axis.maxValue)
|
||||
self.assertEqual(256, axis.nameID)
|
||||
self.assertEqual(256, axis.axisNameID)
|
||||
|
||||
|
||||
class NamedInstanceTest(unittest.TestCase):
|
||||
def test_compile(self):
|
||||
inst = NamedInstance()
|
||||
inst.nameID = 345
|
||||
inst.subfamilyNameID = 345
|
||||
inst.coordinates = {"wght": 0.7, "wdth": 0.5}
|
||||
self.assertEqual(FVAR_INSTANCE_DATA, inst.compile(["wght", "wdth"]))
|
||||
|
||||
def test_decompile(self):
|
||||
inst = NamedInstance()
|
||||
inst.decompile(FVAR_INSTANCE_DATA, ["wght", "wdth"])
|
||||
self.assertEqual(345, inst.nameID)
|
||||
self.assertEqual(345, inst.subfamilyNameID)
|
||||
self.assertEqual({"wght": 0.7, "wdth": 0.5}, inst.coordinates)
|
||||
|
||||
def test_toXML(self):
|
||||
font = MakeFont()
|
||||
inst = NamedInstance()
|
||||
inst.nameID = AddName(font, "Light Condensed").nameID
|
||||
inst.subfamilyNameID = AddName(font, "Light Condensed").nameID
|
||||
inst.coordinates = {"wght": 0.7, "wdth": 0.5}
|
||||
writer = XMLWriter(BytesIO())
|
||||
inst.toXML(writer, font)
|
||||
self.assertEqual([
|
||||
'',
|
||||
'<!-- Light Condensed -->',
|
||||
'<NamedInstance nameID="%s">' % inst.nameID,
|
||||
'<NamedInstance subfamilyNameID="%s">' % inst.subfamilyNameID,
|
||||
'<coord axis="wght" value="0.7"/>',
|
||||
'<coord axis="wdth" value="0.5"/>',
|
||||
'</NamedInstance>'
|
||||
@ -187,12 +187,12 @@ class NamedInstanceTest(unittest.TestCase):
|
||||
def test_fromXML(self):
|
||||
inst = NamedInstance()
|
||||
for name, attrs, content in parseXML(
|
||||
'<NamedInstance nameID="345">'
|
||||
'<NamedInstance subfamilyNameID="345">'
|
||||
' <coord axis="wght" value="0.7"/>'
|
||||
' <coord axis="wdth" value="0.5"/>'
|
||||
'</NamedInstance>'):
|
||||
inst.fromXML(name, attrs, content, ttFont=MakeFont())
|
||||
self.assertEqual(345, inst.nameID)
|
||||
self.assertEqual(345, inst.subfamilyNameID)
|
||||
self.assertEqual({"wght": 0.7, "wdth": 0.5}, inst.coordinates)
|
||||
|
||||
|
||||
|
@ -68,15 +68,18 @@ def _add_fvar(font, axes, instances, axis_map):
|
||||
axis = Axis()
|
||||
axis.axisTag = Tag(axis_map[iden][0])
|
||||
axis.minValue, axis.defaultValue, axis.maxValue = axes[iden]
|
||||
axis.nameID = _AddName(font, axis_map[iden][1]).nameID
|
||||
axis.axisNameID = _AddName(font, axis_map[iden][1]).nameID
|
||||
fvar.axes.append(axis)
|
||||
|
||||
for instance in instances:
|
||||
coordinates = instance['location']
|
||||
name = instance['stylename']
|
||||
psname = instance.get('postscriptfontname')
|
||||
|
||||
inst = NamedInstance()
|
||||
inst.nameID = _AddName(font, name).nameID
|
||||
inst.subfamilyNameID = _AddName(font, name).nameID
|
||||
if psname:
|
||||
inst.postscriptNamedID = _AddName(font, psname).nameID
|
||||
inst.coordinates = {axis_map[k][0]:v for k,v in coordinates.items()}
|
||||
fvar.instances.append(inst)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user