aboutsummaryrefslogtreecommitdiff
path: root/Tests/varLib/instancer/names_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tests/varLib/instancer/names_test.py')
-rw-r--r--Tests/varLib/instancer/names_test.py322
1 files changed, 322 insertions, 0 deletions
diff --git a/Tests/varLib/instancer/names_test.py b/Tests/varLib/instancer/names_test.py
new file mode 100644
index 00000000..9774458a
--- /dev/null
+++ b/Tests/varLib/instancer/names_test.py
@@ -0,0 +1,322 @@
+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": instancer.AxisRange(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,
+ ),
+ ],
+)
+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[4]
+ # 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)
+
+
+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)