Skip to content

Commit

Permalink
Test hb-ot-math API
Browse files Browse the repository at this point in the history
  • Loading branch information
khaledhosny committed Dec 27, 2023
1 parent a0be16d commit 7a3b0fa
Show file tree
Hide file tree
Showing 2 changed files with 259 additions and 0 deletions.
Binary file added tests/data/STIXTwoMath-Regular.ttf
Binary file not shown.
259 changes: 259 additions & 0 deletions tests/test_uharfbuzz.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
OPEN_SANS_TTF_PATH = TESTDATA / "OpenSans.subset.ttf"
MUTATOR_SANS_TTF_PATH = TESTDATA / "MutatorSans-VF.subset.ttf"
SPARSE_FONT_TTF_PATH = TESTDATA / "SparseFont.ttf"
MATH_FONT_TTF_PATH = TESTDATA / "STIXTwoMath-Regular.ttf"


@pytest.fixture
Expand Down Expand Up @@ -64,6 +65,14 @@ def sparsefont():
return font


@pytest.fixture
def mathfont():
"""Return a subset of STIX Two Math font with only MATH, post, head, and maxp tables"""
face = hb.Face(MATH_FONT_TTF_PATH.read_bytes())
font = hb.Font(face)
return font


class TestBuffer:
def test_init(self):
buf = hb.Buffer()
Expand Down Expand Up @@ -845,6 +854,256 @@ def test_ot_layout_script_get_language_tags(self, blankfont):
assert tags == []


class TestOTMath:
def test_ot_math_has_data(self, mathfont):
assert hb.ot_math_has_data(mathfont.face)

def test_ot_math_has_no_data(self, blankfont):
assert hb.ot_math_has_data(blankfont.face) == False

@pytest.mark.parametrize(
"constant, expected",
[
(hb.OTMathConstant.SCRIPT_PERCENT_SCALE_DOWN, 70),
(hb.OTMathConstant.SCRIPT_SCRIPT_PERCENT_SCALE_DOWN, 55),
(hb.OTMathConstant.RADICAL_KERN_BEFORE_DEGREE, 65),
(hb.OTMathConstant.RADICAL_KERN_AFTER_DEGREE, -335),
(hb.OTMathConstant.RADICAL_DEGREE_BOTTOM_RAISE_PERCENT, 55),
],
)
def test_ot_math_get_constant(self, mathfont, constant, expected):
assert hb.ot_math_get_constant(mathfont, constant) == expected

def test_ot_math_get_constant_invalid(self, mathfont):
with pytest.raises(ValueError):
hb.ot_math_get_constant(mathfont, 1000)

@pytest.mark.parametrize(
"glyph, expected",
[
("uni222B", 230),
("uni210B", 40),
("uni222B.dsp", 540),
("u1D435", 30),
("A", 0),
],
)
def test_ot_math_get_glyph_italics_correction(self, mathfont, glyph, expected):
gid = mathfont.get_glyph_from_name(glyph)
assert hb.ot_math_get_glyph_italics_correction(mathfont, gid) == expected

@pytest.mark.parametrize(
"glyph, expected",
[
("u1D435", 380),
("A", 360),
("parenleft", 250),
],
)
def test_ot_math_get_glyph_top_accent_attachment(self, mathfont, glyph, expected):
gid = mathfont.get_glyph_from_name(glyph)
assert hb.ot_math_get_glyph_top_accent_attachment(mathfont, gid) == expected

@pytest.mark.parametrize(
"glyph, expected",
[
("A", False),
("parenleft", True),
("parenright", True),
("bar", True),
("uni221A", True),
],
)
def test_ot_math_is_glyph_extended_shape(self, mathfont, glyph, expected):
gid = mathfont.get_glyph_from_name(glyph)
assert hb.ot_math_is_glyph_extended_shape(mathfont.face, gid) == expected

@pytest.mark.parametrize(
"direction, expected",
[
("LTR", 100),
("RTL", 100),
("TTB", 100),
("BTT", 100),
],
)
def test_ot_math_get_min_connector_overlap(self, mathfont, direction, expected):
assert hb.ot_math_get_min_connector_overlap(mathfont, direction) == expected

@pytest.mark.parametrize(
"glyph, kern, height, expected",
[
("A", hb.OTMathKern.TOP_RIGHT, 250, 0),
("A", hb.OTMathKern.TOP_RIGHT, 300, -18),
("A", hb.OTMathKern.TOP_RIGHT, 400, -66),
("F", hb.OTMathKern.BOTTOM_RIGHT, 0, -200),
("F", hb.OTMathKern.BOTTOM_RIGHT, 150, -44),
("F", hb.OTMathKern.BOTTOM_RIGHT, 300, 44),
("J", hb.OTMathKern.TOP_LEFT, 250, 64),
("J", hb.OTMathKern.TOP_LEFT, 300, -28),
("J", hb.OTMathKern.TOP_LEFT, 400, -28),
("M", hb.OTMathKern.BOTTOM_LEFT, 0, 40),
("M", hb.OTMathKern.BOTTOM_LEFT, 150, 40),
("M", hb.OTMathKern.BOTTOM_LEFT, 300, 40),
],
)
def test_ot_math_get_glyph_kerning(self, mathfont, glyph, kern, height, expected):
gid = mathfont.get_glyph_from_name(glyph)
assert hb.ot_math_get_glyph_kerning(mathfont, gid, kern, height) == expected

def test_ot_math_get_glyph_kerning_invalid(self, mathfont):
gid = mathfont.get_glyph_from_name("A")
with pytest.raises(ValueError):
hb.ot_math_get_glyph_kerning(mathfont, gid, 1000, 100)

@pytest.mark.parametrize(
"glyph, kern, expected",
[
(
"u1D434",
hb.OTMathKern.TOP_RIGHT,
[(213, 58), (350, -58), (0x7FFFFFFF, -70)],
),
(
"u1D435",
hb.OTMathKern.BOTTOM_RIGHT,
[(160, -50), (283, -12), (0x7FFFFFFF, 20)],
),
(
"u1D435",
hb.OTMathKern.TOP_LEFT,
[(176, 81), (0x7FFFFFFF, -50)],
),
(
"U",
hb.OTMathKern.BOTTOM_LEFT,
[(126, -80), (256, -60), (0x7FFFFFFF, 36)],
),
],
)
def test_ot_math_get_glyph_kernings(self, mathfont, glyph, kern, expected):
gid = mathfont.get_glyph_from_name(glyph)
assert hb.ot_math_get_glyph_kernings(mathfont, gid, kern) == expected

def test_ot_math_get_glyph_kernings_invalid(self, mathfont):
gid = mathfont.get_glyph_from_name("A")
with pytest.raises(ValueError):
hb.ot_math_get_glyph_kernings(mathfont, gid, 1000)

@pytest.mark.parametrize(
"glyph, direction, expected",
[
(
"parenleft",
"TTB",
[
("parenleft", 933),
("parenleft.s1", 1187),
("parenleft.s2", 1427),
("parenleft.s3", 1667),
("parenleft.s4", 1907),
("parenleft.s5", 2145),
("parenleft.s6", 2385),
("parenleft.s7", 2625),
("parenleft.s8", 2865),
("parenleft.s9", 3101),
("parenleft.s10", 3341),
("parenleft.s11", 3581),
("parenleft.s12", 3821),
],
),
("parenleft", "LTR", []),
("uni2211", "TTB", [("uni2211", 1031), ("uni2211.s1", 1326)]),
(
"uni0302",
"LTR",
[
("uni0302", 283),
("circumflex.s1", 574),
("circumflex.s2", 1003),
("circumflex.s3", 1496),
("circumflex.s4", 1932),
("circumflex.s5", 2385),
],
),
("uni0302", "TTB", []),
],
)
def test_ot_math_get_glyph_variants(self, mathfont, glyph, direction, expected):
gid = mathfont.get_glyph_from_name(glyph)
variants = hb.ot_math_get_glyph_variants(mathfont, gid, direction)
result = [(mathfont.get_glyph_name(v.glyph), v.advance) for v in variants]
assert result == expected

@pytest.mark.parametrize(
"glyph, direction, expected",
[
(
"parenleft",
"TTB",
(
[
("uni239D", 0, 250, 1273, 0),
("uni239C", 1000, 1000, 1252, hb.OTMathGlyphPartFlags.EXTENDER),
("uni239B", 250, 0, 1273, 0),
],
0,
),
),
("parenleft", "LTR", ([], 0)),
(
"uni222B",
"TTB",
(
[
("uni2321", 0, 800, 1896, 0),
(
"integral.x",
600,
600,
1251,
hb.OTMathGlyphPartFlags.EXTENDER,
),
("uni2320", 800, 0, 1630, 0),
],
80,
),
),
(
"uni23DE",
"LTR",
(
[
("uni23DE.l", 0, 300, 957, 0),
("uni23B4.x", 600, 600, 751, hb.OTMathGlyphPartFlags.EXTENDER),
("uni23DE.m", 300, 300, 943, 0),
("uni23B4.x", 600, 600, 751, hb.OTMathGlyphPartFlags.EXTENDER),
("uni23DE.r", 300, 0, 957, 0),
],
0,
),
),
("uni0302", "TTB", ([], 0)),
],
)
def test_ot_math_get_glyph_assembly(self, mathfont, glyph, direction, expected):
gid = mathfont.get_glyph_from_name(glyph)
assembly, italics_correction = hb.ot_math_get_glyph_assembly(
mathfont, gid, direction
)
result = [
(
mathfont.get_glyph_name(v.glyph),
v.start_connector_length,
v.end_connector_length,
v.full_advance,
v.flags,
)
for v in assembly
]
assert (result, italics_correction) == expected


def test_harfbuzz_version():
v = hb.version_string()
assert isinstance(v, str)
Expand Down

0 comments on commit 7a3b0fa

Please sign in to comment.