fonttools/Tests/ttLib/tables/_a_v_a_r_test.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

207 lines
6.9 KiB
Python
Raw Permalink Normal View History

from fontTools.misc.testTools import parseXML
2015-06-20 00:13:01 +02:00
from fontTools.misc.textTools import deHexStr
from fontTools.misc.xmlWriter import XMLWriter
2023-03-15 11:40:24 -06:00
from fontTools.misc.fixedTools import floatToFixed as fl2fi
2024-04-02 11:42:42 -06:00
from fontTools.pens.statisticsPen import StatisticsPen
from fontTools.ttLib import TTFont, TTLibError
2023-03-14 13:46:39 -06:00
import fontTools.ttLib.tables.otTables as otTables
2015-06-20 00:13:01 +02:00
from fontTools.ttLib.tables._a_v_a_r import table__a_v_a_r
from fontTools.ttLib.tables._f_v_a_r import table__f_v_a_r, Axis
2023-03-14 13:46:39 -06:00
import fontTools.varLib.models as models
import fontTools.varLib.varStore as varStore
from io import BytesIO
2024-04-02 11:42:42 -06:00
import os
2015-06-20 00:13:01 +02:00
import unittest
2024-04-02 11:42:42 -06:00
DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "data")
2015-06-20 00:13:01 +02:00
TEST_DATA = deHexStr(
"00 01 00 00 00 00 00 02 "
"00 04 C0 00 C0 00 00 00 00 00 13 33 33 33 40 00 40 00 "
"00 03 C0 00 C0 00 00 00 00 00 40 00 40 00"
)
class AxisVariationTableTest(unittest.TestCase):
def assertAvarAlmostEqual(self, segments1, segments2):
self.assertSetEqual(set(segments1.keys()), set(segments2.keys()))
for axisTag, mapping1 in segments1.items():
mapping2 = segments2[axisTag]
self.assertEqual(len(mapping1), len(mapping2))
for (k1, v1), (k2, v2) in zip(
sorted(mapping1.items()), sorted(mapping2.items())
):
self.assertAlmostEqual(k1, k2)
self.assertAlmostEqual(v1, v2)
2015-06-20 00:13:01 +02:00
def test_compile(self):
avar = table__a_v_a_r()
avar.segments["wdth"] = {-1.0: -1.0, 0.0: 0.0, 0.3: 0.8, 1.0: 1.0}
avar.segments["wght"] = {-1.0: -1.0, 0.0: 0.0, 1.0: 1.0}
self.assertEqual(TEST_DATA, avar.compile(self.makeFont(["wdth", "wght"])))
def test_decompile(self):
avar = table__a_v_a_r()
avar.decompile(TEST_DATA, self.makeFont(["wdth", "wght"]))
self.assertAvarAlmostEqual(
{
"wdth": {-1.0: -1.0, 0.0: 0.0, 0.2999878: 0.7999878, 1.0: 1.0},
2015-06-20 00:13:01 +02:00
"wght": {-1.0: -1.0, 0.0: 0.0, 1.0: 1.0},
},
avar.segments,
)
def test_toXML(self):
avar = table__a_v_a_r()
avar.segments["opsz"] = {-1.0: -1.0, 0.0: 0.0, 0.2999878: 0.7999878, 1.0: 1.0}
2015-08-07 16:16:49 +01:00
writer = XMLWriter(BytesIO())
2015-06-20 00:13:01 +02:00
avar.toXML(writer, self.makeFont(["opsz"]))
self.assertEqual(
[
2023-03-08 11:07:06 -07:00
'<version major="1" minor="0"/>',
2015-06-20 00:13:01 +02:00
'<segment axis="opsz">',
'<mapping from="-1.0" to="-1.0"/>',
'<mapping from="0.0" to="0.0"/>',
'<mapping from="0.3" to="0.8"/>',
'<mapping from="1.0" to="1.0"/>',
"</segment>",
],
self.xml_lines(writer),
)
def test_fromXML(self):
avar = table__a_v_a_r()
for name, attrs, content in parseXML(
'<segment axis="wdth">'
' <mapping from="-1.0" to="-1.0"/>'
' <mapping from="0.0" to="0.0"/>'
' <mapping from="0.7" to="0.2"/>'
' <mapping from="1.0" to="1.0"/>'
"</segment>"
):
avar.fromXML(name, attrs, content, ttFont=None)
self.assertAvarAlmostEqual(
{"wdth": {-1: -1, 0: 0, 0.7000122: 0.2000122, 1.0: 1.0}}, avar.segments
)
2015-06-20 00:13:01 +02:00
@staticmethod
def makeFont(axisTags):
"""['opsz', 'wdth'] --> ttFont"""
fvar = table__f_v_a_r()
for tag in axisTags:
axis = Axis()
axis.axisTag = tag
fvar.axes.append(axis)
font = TTFont()
font["fvar"] = fvar
return font
2015-06-20 00:13:01 +02:00
@staticmethod
def xml_lines(writer):
content = writer.file.getvalue().decode("utf-8")
return [line.strip() for line in content.splitlines()][1:]
2023-03-14 13:46:39 -06:00
class Avar2Test(unittest.TestCase):
2024-04-02 11:42:42 -06:00
def test_roundtrip(self):
2023-03-14 13:46:39 -06:00
axisTags = ["wght", "wdth"]
fvar = table__f_v_a_r()
for tag in axisTags:
axis = Axis()
axis.axisTag = tag
fvar.axes.append(axis)
master_locations_normalized = [
{},
{"wght": 1, "wdth": -1},
]
data = [
{},
{"wdth": -0.8},
]
model = models.VariationModel(master_locations_normalized, axisTags)
store_builder = varStore.OnlineVarStoreBuilder(axisTags)
store_builder.setModel(model)
varIdxes = {}
for axis in axisTags:
2023-03-15 11:40:24 -06:00
masters = [fl2fi(m.get(axis, 0), 14) for m in data]
2023-03-14 13:46:39 -06:00
varIdxes[axis] = store_builder.storeMasters(masters)[1]
store = store_builder.finish()
mapping = store.optimize()
varIdxes = {axis: mapping[value] for axis, value in varIdxes.items()}
del model, store_builder, mapping
varIdxMap = otTables.DeltaSetIndexMap()
2023-03-15 11:46:57 -06:00
varIdxMap.Format = 1
2023-03-14 13:46:39 -06:00
varIdxMap.mapping = []
for tag in axisTags:
varIdxMap.mapping.append(varIdxes[tag])
avar = table__a_v_a_r()
avar.segments["wght"] = {}
avar.segments["wdth"] = {-1.0: -1.0, 0.0: 0.0, 0.4: 0.5, 1.0: 1.0}
avar.majorVersion = 2
avar.table = otTables.avar()
avar.table.VarIdxMap = varIdxMap
avar.table.VarStore = store
font = TTFont()
font["fvar"] = fvar
font["avar"] = avar
b = BytesIO()
font.save(b)
b.seek(0)
font2 = TTFont(b)
assert font2["avar"].table.VarStore.VarRegionList.RegionAxisCount == 2
assert font2["avar"].table.VarStore.VarRegionList.RegionCount == 1
xml1 = BytesIO()
writer = XMLWriter(xml1)
font["avar"].toXML(writer, font)
xml2 = BytesIO()
writer = XMLWriter(xml2)
font2["avar"].toXML(writer, font2)
2023-03-15 11:46:57 -06:00
assert xml1.getvalue() == xml2.getvalue(), (xml1.getvalue(), xml2.getvalue())
2023-03-14 13:46:39 -06:00
avar = table__a_v_a_r()
xml = b"".join(xml2.getvalue().splitlines()[1:])
for name, attrs, content in parseXML(xml):
avar.fromXML(name, attrs, content, ttFont=TTFont())
assert avar.table.VarStore.VarRegionList.RegionAxisCount == 2
assert avar.table.VarStore.VarRegionList.RegionCount == 1
2024-04-02 11:42:42 -06:00
def test_ttGlyphSet(self):
ttf = os.path.join(DATA_DIR, "Amstelvar-avar2.subset.ttf")
font = TTFont(ttf)
regular = font.getGlyphSet()
black = font.getGlyphSet(location={"wght": 900})
expanded = font.getGlyphSet(location={"wdth": 125})
regularStats = StatisticsPen()
blackStats = StatisticsPen()
expandedStats = StatisticsPen()
for glyph in "Test":
regular[glyph].draw(regularStats)
black[glyph].draw(blackStats)
expanded[glyph].draw(expandedStats)
assert abs(regularStats.area) < abs(blackStats.area)
assert abs(expandedStats.area) < abs(blackStats.area)
assert regularStats.meanX < expandedStats.meanX
2023-03-14 13:46:39 -06:00
2015-06-20 00:13:01 +02:00
if __name__ == "__main__":
import sys
2022-12-13 11:26:36 +00:00
sys.exit(unittest.main())