instancer_test: add test for instancing GPOS with kern and mark features

This commit is contained in:
Cosimo Lupo 2019-04-18 17:37:08 +01:00
parent 7209862e89
commit 544f6aae43
No known key found for this signature in database
GPG Key ID: 20D4A261E4A0E642

View File

@ -521,32 +521,79 @@ def makeVariableFont(masters, baseIndex, axes, masterLocations):
return vf return vf
def makeParametrizedVF(glyphOrder, features, values, increments):
# Create a test VF with given glyphs and parametrized OTL features.
# The VF is built from 9 masters (3 x 3 along wght and wdth), with
# locations hard-coded and base master at wght=400 and wdth=100.
# 'values' is a list of initial values that are interpolated in the
# 'features' string, and incremented for each subsequent master by the
# given 'increments' (list of 2-tuple) along the two axes.
assert values and len(values) == len(increments)
assert all(len(i) == 2 for i in increments)
masterLocations = [
{"wght": 100, "wdth": 50},
{"wght": 100, "wdth": 100},
{"wght": 100, "wdth": 150},
{"wght": 400, "wdth": 50},
{"wght": 400, "wdth": 100}, # base master
{"wght": 400, "wdth": 150},
{"wght": 700, "wdth": 50},
{"wght": 700, "wdth": 100},
{"wght": 700, "wdth": 150},
]
n = len(values)
values = list(values)
masters = []
for _ in range(3):
for _ in range(3):
master = makeTTFont(glyphOrder, features=features % tuple(values))
masters.append(master)
for i in range(n):
values[i] += increments[i][1]
for i in range(n):
values[i] += increments[i][0]
baseIndex = 4
axes = [("wght", (100, 400, 700)), ("wdth", (50, 100, 150))]
vf = makeVariableFont(masters, baseIndex, axes, masterLocations)
return vf
@pytest.fixture @pytest.fixture
def varfontGDEF(): def varfontGDEF():
glyphOrder = [".notdef", "f", "i", "f_i"] glyphOrder = [".notdef", "f", "i", "f_i"]
masters = [] features = (
masterLocations = [] "feature liga { sub f i by f_i;} liga;"
weight = v = 100 "table GDEF { LigatureCaretByPos f_i %d; } GDEF;"
for _ in range(3): )
width = 50 values = [100]
for _ in range(3): increments = [(+30, +10)]
master = makeTTFont( return makeParametrizedVF(glyphOrder, features, values, increments)
glyphOrder,
features=(
"feature liga { sub f i by f_i;} liga;" @pytest.fixture
"table GDEF { LigatureCaretByPos f_i %d; } GDEF;" % v def varfontGPOS():
), glyphOrder = [".notdef", "V", "A"]
) features = "feature kern { pos V A %d; } kern;"
masters.append(master) values = [-80]
masterLocations.append({"wght": weight, "wdth": width}) increments = [(-10, -5)]
width += 50 return makeParametrizedVF(glyphOrder, features, values, increments)
v += 10
weight += 300
v += 30 @pytest.fixture
axes = [("wght", (100, 400, 700)), ("wdth", (50, 100, 150))] def varfontGPOS2():
baseIndex = 4 # index of base master (wght=400, wdth=100) glyphOrder = [".notdef", "V", "A", "acutecomb"]
vf = makeVariableFont(masters, baseIndex, axes, masterLocations) features = (
return vf "markClass [acutecomb] <anchor 150 -10> @TOP_MARKS;"
"feature mark {"
" pos base A <anchor %d 450> mark @TOP_MARKS;"
"} mark;"
"feature kern {"
" pos V A %d;"
"} kern;"
)
values = [200, -80]
increments = [(+30, +10), (-10, -5)]
return makeParametrizedVF(glyphOrder, features, values, increments)
class InstantiateOTLTest(object): class InstantiateOTLTest(object):
@ -609,3 +656,152 @@ class InstantiateOTLTest(object):
assert caretValue.Format == 1 assert caretValue.Format == 1
assert not hasattr(caretValue, "DeviceTable") assert not hasattr(caretValue, "DeviceTable")
assert caretValue.Coordinate == expected assert caretValue.Coordinate == expected
@pytest.mark.parametrize(
"location, expected",
[
({"wght": -1.0}, -85), # +25
({"wght": 0}, -110),
({"wght": 1.0}, -135), # -25
({"wdth": -1.0}, -105), # +5
({"wdth": 0}, -110),
({"wdth": 1.0}, -115), # -5
],
)
def test_pin_and_drop_axis_GPOS_kern(self, varfontGPOS, location, expected):
vf = varfontGPOS
assert "GDEF" in vf
assert "GPOS" in vf
instancer.instantiateOTL(vf, location)
gdef = vf["GDEF"].table
gpos = vf["GPOS"].table
assert gdef.Version == 0x00010003
assert gdef.VarStore
assert gpos.LookupList.Lookup[0].LookupType == 2 # PairPos
pairPos = gpos.LookupList.Lookup[0].SubTable[0]
valueRec1 = pairPos.PairSet[0].PairValueRecord[0].Value1
assert valueRec1.XAdvDevice
assert valueRec1.XAdvDevice.DeltaFormat == 0x8000
assert valueRec1.XAdvance == expected
@pytest.mark.parametrize(
"location, expected",
[
({"wght": -1.0, "wdth": -1.0}, -80), # +25 + 5
({"wght": -1.0, "wdth": 0.0}, -85), # +25
({"wght": -1.0, "wdth": 1.0}, -90), # +25 - 5
({"wght": 0.0, "wdth": -1.0}, -105), # +5
({"wght": 0.0, "wdth": 0.0}, -110),
({"wght": 0.0, "wdth": 1.0}, -115), # -5
({"wght": 1.0, "wdth": -1.0}, -130), # -25 + 5
({"wght": 1.0, "wdth": 0.0}, -135), # -25
({"wght": 1.0, "wdth": 1.0}, -140), # -25 - 5
],
)
def test_full_instance_GPOS_kern(self, varfontGPOS, location, expected):
vf = varfontGPOS
assert "GDEF" in vf
assert "GPOS" in vf
instancer.instantiateOTL(vf, location)
assert "GDEF" not in vf
gpos = vf["GPOS"].table
assert gpos.LookupList.Lookup[0].LookupType == 2 # PairPos
pairPos = gpos.LookupList.Lookup[0].SubTable[0]
valueRec1 = pairPos.PairSet[0].PairValueRecord[0].Value1
assert not hasattr(valueRec1, "XAdvDevice")
assert valueRec1.XAdvance == expected
@pytest.mark.parametrize(
"location, expected",
[
({"wght": -1.0}, (210, -85)), # -60, +25
({"wght": 0}, (270, -110)),
({"wght": 0.5}, (300, -122)), # +30, -12
({"wght": 1.0}, (330, -135)), # +60, -25
({"wdth": -1.0}, (260, -105)), # -10, +5
({"wdth": -0.3}, (267, -108)), # -3, +2
({"wdth": 0}, (270, -110)),
({"wdth": 1.0}, (280, -115)), # +10, -5
],
)
def test_pin_and_drop_axis_GPOS_mark_and_kern(
self, varfontGPOS2, location, expected
):
vf = varfontGPOS2
assert "GDEF" in vf
assert "GPOS" in vf
instancer.instantiateOTL(vf, location)
v1, v2 = expected
gdef = vf["GDEF"].table
gpos = vf["GPOS"].table
assert gdef.Version == 0x00010003
assert gdef.VarStore
assert gdef.GlyphClassDef
assert gpos.LookupList.Lookup[0].LookupType == 4 # MarkBasePos
markBasePos = gpos.LookupList.Lookup[0].SubTable[0]
baseAnchor = markBasePos.BaseArray.BaseRecord[0].BaseAnchor[0]
assert baseAnchor.Format == 3
assert baseAnchor.XDeviceTable
assert baseAnchor.XDeviceTable.DeltaFormat == 0x8000
assert not baseAnchor.YDeviceTable
assert baseAnchor.XCoordinate == v1
assert baseAnchor.YCoordinate == 450
assert gpos.LookupList.Lookup[1].LookupType == 2 # PairPos
pairPos = gpos.LookupList.Lookup[1].SubTable[0]
valueRec1 = pairPos.PairSet[0].PairValueRecord[0].Value1
assert valueRec1.XAdvDevice
assert valueRec1.XAdvDevice.DeltaFormat == 0x8000
assert valueRec1.XAdvance == v2
@pytest.mark.parametrize(
"location, expected",
[
({"wght": -1.0, "wdth": -1.0}, (200, -80)), # -60 - 10, +25 + 5
({"wght": -1.0, "wdth": 0.0}, (210, -85)), # -60, +25
({"wght": -1.0, "wdth": 1.0}, (220, -90)), # -60 + 10, +25 - 5
({"wght": 0.0, "wdth": -1.0}, (260, -105)), # -10, +5
({"wght": 0.0, "wdth": 0.0}, (270, -110)),
({"wght": 0.0, "wdth": 1.0}, (280, -115)), # +10, -5
({"wght": 1.0, "wdth": -1.0}, (320, -130)), # +60 - 10, -25 + 5
({"wght": 1.0, "wdth": 0.0}, (330, -135)), # +60, -25
({"wght": 1.0, "wdth": 1.0}, (340, -140)), # +60 + 10, -25 - 5
],
)
def test_full_instance_GPOS_mark_and_kern(self, varfontGPOS2, location, expected):
vf = varfontGPOS2
assert "GDEF" in vf
assert "GPOS" in vf
instancer.instantiateOTL(vf, location)
v1, v2 = expected
gdef = vf["GDEF"].table
gpos = vf["GPOS"].table
assert gdef.Version == 0x00010000
assert not hasattr(gdef, "VarStore")
assert gdef.GlyphClassDef
assert gpos.LookupList.Lookup[0].LookupType == 4 # MarkBasePos
markBasePos = gpos.LookupList.Lookup[0].SubTable[0]
baseAnchor = markBasePos.BaseArray.BaseRecord[0].BaseAnchor[0]
assert baseAnchor.Format == 1
assert not hasattr(baseAnchor, "XDeviceTable")
assert not hasattr(baseAnchor, "YDeviceTable")
assert baseAnchor.XCoordinate == v1
assert baseAnchor.YCoordinate == 450
assert gpos.LookupList.Lookup[1].LookupType == 2 # PairPos
pairPos = gpos.LookupList.Lookup[1].SubTable[0]
valueRec1 = pairPos.PairSet[0].PairValueRecord[0].Value1
assert not hasattr(valueRec1, "XAdvDevice")
assert valueRec1.XAdvance == v2