xref: /aosp_15_r20/external/fonttools/Tests/pens/hashPointPen_test.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1from fontTools.misc.transform import Identity
2from fontTools.pens.hashPointPen import HashPointPen
3import pytest
4
5
6class _TestGlyph(object):
7    width = 500
8
9    def drawPoints(self, pen):
10        pen.beginPath(identifier="abc")
11        pen.addPoint((0.0, 0.0), "line", False, "start", identifier="0000")
12        pen.addPoint((10, 110), "line", False, None, identifier="0001")
13        pen.addPoint((50.0, 75.0), None, False, None, identifier="0002")
14        pen.addPoint((60.0, 50.0), None, False, None, identifier="0003")
15        pen.addPoint((50.0, 0.0), "curve", True, "last", identifier="0004")
16        pen.endPath()
17
18
19class _TestGlyph2(_TestGlyph):
20    def drawPoints(self, pen):
21        pen.beginPath(identifier="abc")
22        pen.addPoint((0.0, 0.0), "line", False, "start", identifier="0000")
23        # Minor difference to _TestGlyph() is in the next line:
24        pen.addPoint((101, 10), "line", False, None, identifier="0001")
25        pen.addPoint((50.0, 75.0), None, False, None, identifier="0002")
26        pen.addPoint((60.0, 50.0), None, False, None, identifier="0003")
27        pen.addPoint((50.0, 0.0), "curve", True, "last", identifier="0004")
28        pen.endPath()
29
30
31class _TestGlyph3(_TestGlyph):
32    def drawPoints(self, pen):
33        pen.beginPath(identifier="abc")
34        pen.addPoint((0.0, 0.0), "line", False, "start", identifier="0000")
35        pen.addPoint((10, 110), "line", False, None, identifier="0001")
36        pen.endPath()
37        # Same segment, but in a different path:
38        pen.beginPath(identifier="pth2")
39        pen.addPoint((50.0, 75.0), None, False, None, identifier="0002")
40        pen.addPoint((60.0, 50.0), None, False, None, identifier="0003")
41        pen.addPoint((50.0, 0.0), "curve", True, "last", identifier="0004")
42        pen.endPath()
43
44
45class _TestGlyph4(_TestGlyph):
46    def drawPoints(self, pen):
47        pen.beginPath(identifier="abc")
48        pen.addPoint((0.0, 0.0), "move", False, "start", identifier="0000")
49        pen.addPoint((10, 110), "line", False, None, identifier="0001")
50        pen.addPoint((50.0, 75.0), None, False, None, identifier="0002")
51        pen.addPoint((60.0, 50.0), None, False, None, identifier="0003")
52        pen.addPoint((50.0, 0.0), "curve", True, "last", identifier="0004")
53        pen.endPath()
54
55
56class _TestGlyph5(_TestGlyph):
57    def drawPoints(self, pen):
58        pen.addComponent("b", Identity)
59
60
61class HashPointPenTest(object):
62    def test_addComponent(self):
63        pen = HashPointPen(_TestGlyph().width, {"a": _TestGlyph()})
64        pen.addComponent("a", (2, 0, 0, 3, -10, 5))
65        assert pen.hash == "w500[l0+0l10+110o50+75o60+50c50+0|(+2+0+0+3-10+5)]"
66
67    def test_NestedComponents(self):
68        pen = HashPointPen(
69            _TestGlyph().width, {"a": _TestGlyph5(), "b": _TestGlyph()}
70        )  # "a" contains "b" as a component
71        pen.addComponent("a", (2, 0, 0, 3, -10, 5))
72
73        assert (
74            pen.hash
75            == "w500[[l0+0l10+110o50+75o60+50c50+0|(+1+0+0+1+0+0)](+2+0+0+3-10+5)]"
76        )
77
78    def test_outlineAndComponent(self):
79        pen = HashPointPen(_TestGlyph().width, {"a": _TestGlyph()})
80        glyph = _TestGlyph()
81        glyph.drawPoints(pen)
82        pen.addComponent("a", (2, 0, 0, 2, -10, 5))
83
84        assert (
85            pen.hash
86            == "w500l0+0l10+110o50+75o60+50c50+0|[l0+0l10+110o50+75o60+50c50+0|(+2+0+0+2-10+5)]"
87        )
88
89    def test_addComponent_missing_raises(self):
90        pen = HashPointPen(_TestGlyph().width, dict())
91        with pytest.raises(KeyError) as excinfo:
92            pen.addComponent("a", Identity)
93        assert excinfo.value.args[0] == "a"
94
95    def test_similarGlyphs(self):
96        pen = HashPointPen(_TestGlyph().width)
97        glyph = _TestGlyph()
98        glyph.drawPoints(pen)
99
100        pen2 = HashPointPen(_TestGlyph2().width)
101        glyph = _TestGlyph2()
102        glyph.drawPoints(pen2)
103
104        assert pen.hash != pen2.hash
105
106    def test_similarGlyphs2(self):
107        pen = HashPointPen(_TestGlyph().width)
108        glyph = _TestGlyph()
109        glyph.drawPoints(pen)
110
111        pen2 = HashPointPen(_TestGlyph3().width)
112        glyph = _TestGlyph3()
113        glyph.drawPoints(pen2)
114
115        assert pen.hash != pen2.hash
116
117    def test_similarGlyphs3(self):
118        pen = HashPointPen(_TestGlyph().width)
119        glyph = _TestGlyph()
120        glyph.drawPoints(pen)
121
122        pen2 = HashPointPen(_TestGlyph4().width)
123        glyph = _TestGlyph4()
124        glyph.drawPoints(pen2)
125
126        assert pen.hash != pen2.hash
127
128    def test_glyphVsComposite(self):
129        # If a glyph contains a component, the decomposed glyph should still
130        # compare false
131        pen = HashPointPen(_TestGlyph().width, {"a": _TestGlyph()})
132        pen.addComponent("a", Identity)
133
134        pen2 = HashPointPen(_TestGlyph().width)
135        glyph = _TestGlyph()
136        glyph.drawPoints(pen2)
137
138        assert pen.hash != pen2.hash
139