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

336 lines
11 KiB
Python
Raw Normal View History

from fontTools.ttLib.tables import otTables
from fontTools.otlLib.builder import buildStatTable
from fontTools.varLib import instancer
import pytest
def test_pruningUnusedNames(varfont):
varNameIDs = instancer.names.getVariationNameIDs(varfont)
assert varNameIDs == set(range(256, 297 + 1))
fvar = varfont["fvar"]
stat = varfont["STAT"].table
with instancer.names.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.names.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
def _test_name_records(varfont, expected, isNonRIBBI, platforms=[0x409]):
nametable = varfont["name"]
font_names = {
(r.nameID, r.platformID, r.platEncID, r.langID): r.toUnicode()
for r in nametable.names
}
for k in expected:
if k[-1] not in platforms:
continue
assert font_names[k] == expected[k]
font_nameids = set(i[0] for i in font_names)
if isNonRIBBI:
assert 16 in font_nameids
assert 17 in font_nameids
if "fvar" not in varfont:
assert 25 not in font_nameids
@pytest.mark.parametrize(
"limits, expected, isNonRIBBI",
[
# Regular
(
{"wght": 400},
{
(1, 3, 1, 0x409): "Test Variable Font",
(2, 3, 1, 0x409): "Regular",
(3, 3, 1, 0x409): "2.001;GOOG;TestVariableFont-Regular",
(6, 3, 1, 0x409): "TestVariableFont-Regular",
},
False,
),
# Regular Normal (width axis Normal isn't included since it is elided)
(
{"wght": 400, "wdth": 100},
{
(1, 3, 1, 0x409): "Test Variable Font",
(2, 3, 1, 0x409): "Regular",
(3, 3, 1, 0x409): "2.001;GOOG;TestVariableFont-Regular",
(6, 3, 1, 0x409): "TestVariableFont-Regular",
},
False,
),
# Black
(
{"wght": 900},
{
(1, 3, 1, 0x409): "Test Variable Font Black",
(2, 3, 1, 0x409): "Regular",
(3, 3, 1, 0x409): "2.001;GOOG;TestVariableFont-Black",
(6, 3, 1, 0x409): "TestVariableFont-Black",
(16, 3, 1, 0x409): "Test Variable Font",
(17, 3, 1, 0x409): "Black",
},
True,
),
# Thin
(
{"wght": 100},
{
(1, 3, 1, 0x409): "Test Variable Font Thin",
(2, 3, 1, 0x409): "Regular",
(3, 3, 1, 0x409): "2.001;GOOG;TestVariableFont-Thin",
(6, 3, 1, 0x409): "TestVariableFont-Thin",
(16, 3, 1, 0x409): "Test Variable Font",
(17, 3, 1, 0x409): "Thin",
},
True,
),
# Thin Condensed
(
{"wght": 100, "wdth": 79},
{
(1, 3, 1, 0x409): "Test Variable Font Thin Condensed",
(2, 3, 1, 0x409): "Regular",
(3, 3, 1, 0x409): "2.001;GOOG;TestVariableFont-ThinCondensed",
(6, 3, 1, 0x409): "TestVariableFont-ThinCondensed",
(16, 3, 1, 0x409): "Test Variable Font",
(17, 3, 1, 0x409): "Thin Condensed",
},
True,
),
# Condensed with unpinned weights
(
{"wdth": 79, "wght": (400, 900)},
{
(1, 3, 1, 0x409): "Test Variable Font Condensed",
(2, 3, 1, 0x409): "Regular",
(3, 3, 1, 0x409): "2.001;GOOG;TestVariableFont-Condensed",
(6, 3, 1, 0x409): "TestVariableFont-Condensed",
(16, 3, 1, 0x409): "Test Variable Font",
(17, 3, 1, 0x409): "Condensed",
},
True,
),
# Restrict weight and move default, new minimum (500) > old default (400)
(
{"wght": (500, 900)},
{
(1, 3, 1, 0x409): "Test Variable Font Medium",
(2, 3, 1, 0x409): "Regular",
(3, 3, 1, 0x409): "2.001;GOOG;TestVariableFont-Medium",
(6, 3, 1, 0x409): "TestVariableFont-Medium",
(16, 3, 1, 0x409): "Test Variable Font",
(17, 3, 1, 0x409): "Medium",
},
True,
),
],
)
def test_updateNameTable_with_registered_axes_ribbi(
varfont, limits, expected, isNonRIBBI
):
instancer.names.updateNameTable(varfont, limits)
_test_name_records(varfont, expected, isNonRIBBI)
def test_updatetNameTable_axis_order(varfont):
axes = [
dict(
tag="wght",
name="Weight",
values=[
dict(value=400, name="Regular"),
],
),
dict(
tag="wdth",
name="Width",
values=[
dict(value=75, name="Condensed"),
],
),
]
nametable = varfont["name"]
buildStatTable(varfont, axes)
instancer.names.updateNameTable(varfont, {"wdth": 75, "wght": 400})
assert nametable.getName(17, 3, 1, 0x409).toUnicode() == "Regular Condensed"
# Swap the axes so the names get swapped
axes[0], axes[1] = axes[1], axes[0]
buildStatTable(varfont, axes)
instancer.names.updateNameTable(varfont, {"wdth": 75, "wght": 400})
assert nametable.getName(17, 3, 1, 0x409).toUnicode() == "Condensed Regular"
@pytest.mark.parametrize(
"limits, expected, isNonRIBBI",
[
# Regular | Normal
(
{"wght": 400},
{
(1, 3, 1, 0x409): "Test Variable Font",
(2, 3, 1, 0x409): "Normal",
},
False,
),
# Black | Negreta
(
{"wght": 900},
{
(1, 3, 1, 0x409): "Test Variable Font Negreta",
(2, 3, 1, 0x409): "Normal",
(16, 3, 1, 0x409): "Test Variable Font",
(17, 3, 1, 0x409): "Negreta",
},
True,
),
# Black Condensed | Negreta Zhuštěné
(
{"wght": 900, "wdth": 79},
{
(1, 3, 1, 0x409): "Test Variable Font Negreta Zhuštěné",
(2, 3, 1, 0x409): "Normal",
(16, 3, 1, 0x409): "Test Variable Font",
(17, 3, 1, 0x409): "Negreta Zhuštěné",
},
True,
),
],
)
def test_updateNameTable_with_multilingual_names(varfont, limits, expected, isNonRIBBI):
name = varfont["name"]
# langID 0x405 is the Czech Windows langID
name.setName("Test Variable Font", 1, 3, 1, 0x405)
name.setName("Normal", 2, 3, 1, 0x405)
name.setName("Normal", 261, 3, 1, 0x405) # nameID 261=Regular STAT entry
name.setName("Negreta", 266, 3, 1, 0x405) # nameID 266=Black STAT entry
name.setName("Zhuštěné", 279, 3, 1, 0x405) # nameID 279=Condensed STAT entry
instancer.names.updateNameTable(varfont, limits)
_test_name_records(varfont, expected, isNonRIBBI, platforms=[0x405])
def test_updateNameTable_missing_axisValues(varfont):
with pytest.raises(ValueError, match="Cannot find Axis Values {'wght': 200}"):
instancer.names.updateNameTable(varfont, {"wght": 200})
def test_updateNameTable_missing_stat(varfont):
del varfont["STAT"]
with pytest.raises(
ValueError, match="Cannot update name table since there is no STAT table."
):
instancer.names.updateNameTable(varfont, {"wght": 400})
@pytest.mark.parametrize(
"limits, expected, isNonRIBBI",
[
# Regular | Normal
(
{"wght": 400},
{
(1, 3, 1, 0x409): "Test Variable Font",
(2, 3, 1, 0x409): "Italic",
(6, 3, 1, 0x409): "TestVariableFont-Italic",
},
False,
),
# Black Condensed Italic
(
{"wght": 900, "wdth": 79},
{
(1, 3, 1, 0x409): "Test Variable Font Black Condensed",
(2, 3, 1, 0x409): "Italic",
(6, 3, 1, 0x409): "TestVariableFont-BlackCondensedItalic",
(16, 3, 1, 0x409): "Test Variable Font",
(17, 3, 1, 0x409): "Black Condensed Italic",
},
True,
),
],
)
def test_updateNameTable_vf_with_italic_attribute(
varfont, limits, expected, isNonRIBBI
):
font_link_axisValue = varfont["STAT"].table.AxisValueArray.AxisValue[5]
# Unset ELIDABLE_AXIS_VALUE_NAME flag
font_link_axisValue.Flags &= ~instancer.names.ELIDABLE_AXIS_VALUE_NAME
font_link_axisValue.ValueNameID = 294 # Roman --> Italic
instancer.names.updateNameTable(varfont, limits)
_test_name_records(varfont, expected, isNonRIBBI)
def test_updateNameTable_format4_axisValues(varfont):
# format 4 axisValues should dominate the other axisValues
stat = varfont["STAT"].table
axisValue = otTables.AxisValue()
axisValue.Format = 4
axisValue.Flags = 0
varfont["name"].setName("Dominant Value", 297, 3, 1, 0x409)
axisValue.ValueNameID = 297
axisValue.AxisValueRecord = []
for tag, value in (("wght", 900), ("wdth", 79)):
rec = otTables.AxisValueRecord()
rec.AxisIndex = next(
i for i, a in enumerate(stat.DesignAxisRecord.Axis) if a.AxisTag == tag
)
rec.Value = value
axisValue.AxisValueRecord.append(rec)
stat.AxisValueArray.AxisValue.append(axisValue)
instancer.names.updateNameTable(varfont, {"wdth": 79, "wght": 900})
expected = {
(1, 3, 1, 0x409): "Test Variable Font Dominant Value",
(2, 3, 1, 0x409): "Regular",
(16, 3, 1, 0x409): "Test Variable Font",
(17, 3, 1, 0x409): "Dominant Value",
}
_test_name_records(varfont, expected, isNonRIBBI=True)
def test_updateNameTable_elided_axisValues(varfont):
stat = varfont["STAT"].table
# set ELIDABLE_AXIS_VALUE_NAME flag for all axisValues
for axisValue in stat.AxisValueArray.AxisValue:
axisValue.Flags |= instancer.names.ELIDABLE_AXIS_VALUE_NAME
stat.ElidedFallbackNameID = 266 # Regular --> Black
instancer.names.updateNameTable(varfont, {"wght": 400})
# Since all axis values are elided, the elided fallback name
# must be used to construct the style names. Since we
# changed it to Black, we need both a typoSubFamilyName and
# the subFamilyName set so it conforms to the RIBBI model.
expected = {(2, 3, 1, 0x409): "Regular", (17, 3, 1, 0x409): "Black"}
_test_name_records(varfont, expected, isNonRIBBI=True)
2021-02-22 11:31:48 +00:00
def test_updateNameTable_existing_subfamily_name_is_not_regular(varfont):
# Check the subFamily name will be set to Regular when we update a name
# table to a non-RIBBI style and the current subFamily name is a RIBBI
# style which isn't Regular.
varfont["name"].setName("Bold", 2, 3, 1, 0x409) # subFamily Regular --> Bold
instancer.names.updateNameTable(varfont, {"wght": 100})
expected = {(2, 3, 1, 0x409): "Regular", (17, 3, 1, 0x409): "Thin"}
_test_name_records(varfont, expected, isNonRIBBI=True)