Skip to content

Commit b7a19ed

Browse files
authored
Merge pull request #820 from googlefonts/math-fixes
Handle MATH input more carefully
2 parents 6656977 + e132a81 commit b7a19ed

File tree

2 files changed

+61
-14
lines changed

2 files changed

+61
-14
lines changed

Lib/ufo2ft/outlineCompiler.py

+10-12
Original file line numberDiff line numberDiff line change
@@ -1186,24 +1186,22 @@ def setupTable_MATH(self):
11861186
for name, glyph in self.allGlyphs.items():
11871187
if GLYPHS_MATH_VARIANTS_KEY in glyph.lib:
11881188
variants = glyph.lib[GLYPHS_MATH_VARIANTS_KEY]
1189-
if "hVariants" in variants:
1190-
h_variants[name] = [
1191-
(n, self._bboxWidth(n)) for n in variants["hVariants"]
1192-
]
1193-
if "vVariants" in variants:
1194-
v_variants[name] = [
1195-
(n, self._bboxHeight(n)) for n in variants["vVariants"]
1196-
]
1197-
if "hAssembly" in variants:
1198-
parts = variants["hAssembly"]
1189+
if names := variants.get("hVariants"):
1190+
h_variants[name] = [(n, self._bboxWidth(n)) for n in names]
1191+
if names := variants.get("vVariants"):
1192+
v_variants[name] = [(n, self._bboxHeight(n)) for n in names]
1193+
if parts := variants.get("hAssembly"):
1194+
if not all(len(part) == 4 for part in parts):
1195+
raise InvalidFontData("Invalid assembly")
11991196
h_assemblies[name] = (
12001197
[(*part, self._bboxWidth(part[0])) for part in parts],
12011198
# If the last part has italic correction, we use it as
12021199
# the assembly's.
12031200
italics_correction.pop(parts[-1][0], 0),
12041201
)
1205-
if "vAssembly" in variants:
1206-
parts = variants["vAssembly"]
1202+
if parts := variants.get("vAssembly"):
1203+
if not all(len(part) == 4 for part in parts):
1204+
raise InvalidFontData("Invalid assembly")
12071205
v_assemblies[name] = (
12081206
[(*part, self._bboxHeight(part[0])) for part in parts],
12091207
# If the last part has italic correction, we use it as

tests/outlineCompiler_test.py

+51-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
SPARSE_TTF_MASTER_TABLES,
2727
USE_PRODUCTION_NAMES,
2828
)
29+
from ufo2ft.errors import InvalidFontData
2930
from ufo2ft.fontInfoData import intListToNum
3031
from ufo2ft.outlineCompiler import OutlineOTFCompiler, OutlineTTFCompiler
3132

@@ -1406,9 +1407,10 @@ def test_achVendId_space_padded_if_less_than_4_chars(
14061407
assert font["OS/2"].achVendID == expected
14071408

14081409

1409-
def test_MATH_table(FontClass):
1410+
@pytest.mark.parametrize("compile", [compileTTF, compileOTF])
1411+
def test_MATH_table(FontClass, compile):
14101412
ufo = FontClass(getpath("TestMathFont-Regular.ufo"))
1411-
result = compileTTF(ufo)
1413+
result = compile(ufo)
14121414
assert "MATH" in result
14131415

14141416
math = result["MATH"].table
@@ -1427,6 +1429,53 @@ def test_MATH_table(FontClass):
14271429

14281430
assert set(math.MathGlyphInfo.ExtendedShapeCoverage.glyphs) == extendedShapes
14291431

1432+
assert set(math.MathVariants.VertGlyphCoverage.glyphs) == {
1433+
"parenright",
1434+
"parenleft",
1435+
}
1436+
assert math.MathVariants.VertGlyphConstruction
1437+
assert len(math.MathVariants.VertGlyphConstruction) == 2
1438+
assert (
1439+
math.MathVariants.VertGlyphConstruction[0].GlyphAssembly.ItalicsCorrection.Value
1440+
== 0
1441+
)
1442+
assert (
1443+
len(math.MathVariants.VertGlyphConstruction[0].GlyphAssembly.PartRecords) == 3
1444+
)
1445+
1446+
assert not math.MathVariants.HorizGlyphCoverage
1447+
assert not math.MathVariants.HorizGlyphConstruction
1448+
1449+
1450+
@pytest.mark.parametrize("compile", [compileTTF, compileOTF])
1451+
@pytest.mark.parametrize(
1452+
"attribute",
1453+
[
1454+
"vAssembly",
1455+
"hAssembly",
1456+
"vVariants",
1457+
"hVariants",
1458+
],
1459+
)
1460+
def test_MATH_table_ignore_empty(FontClass, compile, attribute):
1461+
# Should not raise becaise of empty assembly/variants
1462+
ufo = FontClass(getpath("TestMathFont-Regular.ufo"))
1463+
ufo["parenright"].lib[GLYPHS_MATH_VARIANTS_KEY][attribute] = []
1464+
compile(ufo)
1465+
1466+
1467+
@pytest.mark.parametrize("compile", [compileTTF, compileOTF])
1468+
@pytest.mark.parametrize("attribute", ["vAssembly", "hAssembly"])
1469+
def test_MATH_table_invalid(FontClass, compile, attribute):
1470+
ufo = FontClass(getpath("TestMathFont-Regular.ufo"))
1471+
ufo["parenright"].lib[GLYPHS_MATH_VARIANTS_KEY][attribute] = [
1472+
["parenright.top", 0, 0],
1473+
["parenright.ext", 1, 100, 100],
1474+
["parenright.bot", 0, 100, 0],
1475+
]
1476+
with pytest.raises(InvalidFontData, match="Invalid assembly"):
1477+
compile(ufo)
1478+
14301479

14311480
if __name__ == "__main__":
14321481
import sys

0 commit comments

Comments
 (0)