xref: /aosp_15_r20/external/fonttools/Tests/pens/basePen_test.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1*e1fe3e4aSElliott Hughesfrom fontTools.pens.basePen import (
2*e1fe3e4aSElliott Hughes    AbstractPen,
3*e1fe3e4aSElliott Hughes    BasePen,
4*e1fe3e4aSElliott Hughes    decomposeSuperBezierSegment,
5*e1fe3e4aSElliott Hughes    decomposeQuadraticSegment,
6*e1fe3e4aSElliott Hughes)
7*e1fe3e4aSElliott Hughesfrom fontTools.pens.pointPen import AbstractPointPen
8*e1fe3e4aSElliott Hughesfrom fontTools.misc.loggingTools import CapturingLogHandler
9*e1fe3e4aSElliott Hughesimport unittest
10*e1fe3e4aSElliott Hughes
11*e1fe3e4aSElliott Hughes
12*e1fe3e4aSElliott Hughesclass _TestPen(BasePen):
13*e1fe3e4aSElliott Hughes    def __init__(self):
14*e1fe3e4aSElliott Hughes        BasePen.__init__(self, glyphSet={})
15*e1fe3e4aSElliott Hughes        self._commands = []
16*e1fe3e4aSElliott Hughes
17*e1fe3e4aSElliott Hughes    def __repr__(self):
18*e1fe3e4aSElliott Hughes        return " ".join(self._commands)
19*e1fe3e4aSElliott Hughes
20*e1fe3e4aSElliott Hughes    def getCurrentPoint(self):
21*e1fe3e4aSElliott Hughes        return self._getCurrentPoint()
22*e1fe3e4aSElliott Hughes
23*e1fe3e4aSElliott Hughes    def _moveTo(self, pt):
24*e1fe3e4aSElliott Hughes        self._commands.append("%s %s moveto" % (pt[0], pt[1]))
25*e1fe3e4aSElliott Hughes
26*e1fe3e4aSElliott Hughes    def _lineTo(self, pt):
27*e1fe3e4aSElliott Hughes        self._commands.append("%s %s lineto" % (pt[0], pt[1]))
28*e1fe3e4aSElliott Hughes
29*e1fe3e4aSElliott Hughes    def _curveToOne(self, bcp1, bcp2, pt):
30*e1fe3e4aSElliott Hughes        self._commands.append(
31*e1fe3e4aSElliott Hughes            "%s %s %s %s %s %s curveto"
32*e1fe3e4aSElliott Hughes            % (bcp1[0], bcp1[1], bcp2[0], bcp2[1], pt[0], pt[1])
33*e1fe3e4aSElliott Hughes        )
34*e1fe3e4aSElliott Hughes
35*e1fe3e4aSElliott Hughes    def _closePath(self):
36*e1fe3e4aSElliott Hughes        self._commands.append("closepath")
37*e1fe3e4aSElliott Hughes
38*e1fe3e4aSElliott Hughes    def _endPath(self):
39*e1fe3e4aSElliott Hughes        self._commands.append("endpath")
40*e1fe3e4aSElliott Hughes
41*e1fe3e4aSElliott Hughes
42*e1fe3e4aSElliott Hughesclass _TestGlyph:
43*e1fe3e4aSElliott Hughes    def draw(self, pen):
44*e1fe3e4aSElliott Hughes        pen.moveTo((0.0, 0.0))
45*e1fe3e4aSElliott Hughes        pen.lineTo((0.0, 100.0))
46*e1fe3e4aSElliott Hughes        pen.curveTo((50.0, 75.0), (60.0, 50.0), (50.0, 25.0), (0.0, 0.0))
47*e1fe3e4aSElliott Hughes        pen.closePath()
48*e1fe3e4aSElliott Hughes
49*e1fe3e4aSElliott Hughes
50*e1fe3e4aSElliott Hughesclass BasePenTest(unittest.TestCase):
51*e1fe3e4aSElliott Hughes    def test_moveTo(self):
52*e1fe3e4aSElliott Hughes        pen = _TestPen()
53*e1fe3e4aSElliott Hughes        pen.moveTo((0.5, -4.3))
54*e1fe3e4aSElliott Hughes        self.assertEqual("0.5 -4.3 moveto", repr(pen))
55*e1fe3e4aSElliott Hughes        self.assertEqual((0.5, -4.3), pen.getCurrentPoint())
56*e1fe3e4aSElliott Hughes
57*e1fe3e4aSElliott Hughes    def test_lineTo(self):
58*e1fe3e4aSElliott Hughes        pen = _TestPen()
59*e1fe3e4aSElliott Hughes        pen.moveTo((4, 5))
60*e1fe3e4aSElliott Hughes        pen.lineTo((7, 8))
61*e1fe3e4aSElliott Hughes        self.assertEqual("4 5 moveto 7 8 lineto", repr(pen))
62*e1fe3e4aSElliott Hughes        self.assertEqual((7, 8), pen.getCurrentPoint())
63*e1fe3e4aSElliott Hughes
64*e1fe3e4aSElliott Hughes    def test_curveTo_zeroPoints(self):
65*e1fe3e4aSElliott Hughes        pen = _TestPen()
66*e1fe3e4aSElliott Hughes        pen.moveTo((0.0, 0.0))
67*e1fe3e4aSElliott Hughes        self.assertRaises(AssertionError, pen.curveTo)
68*e1fe3e4aSElliott Hughes
69*e1fe3e4aSElliott Hughes    def test_curveTo_onePoint(self):
70*e1fe3e4aSElliott Hughes        pen = _TestPen()
71*e1fe3e4aSElliott Hughes        pen.moveTo((0.0, 0.0))
72*e1fe3e4aSElliott Hughes        pen.curveTo((1.0, 1.1))
73*e1fe3e4aSElliott Hughes        self.assertEqual("0.0 0.0 moveto 1.0 1.1 lineto", repr(pen))
74*e1fe3e4aSElliott Hughes        self.assertEqual((1.0, 1.1), pen.getCurrentPoint())
75*e1fe3e4aSElliott Hughes
76*e1fe3e4aSElliott Hughes    def test_curveTo_twoPoints(self):
77*e1fe3e4aSElliott Hughes        pen = _TestPen()
78*e1fe3e4aSElliott Hughes        pen.moveTo((0.0, 0.0))
79*e1fe3e4aSElliott Hughes        pen.curveTo((6.0, 3.0), (3.0, 6.0))
80*e1fe3e4aSElliott Hughes        self.assertEqual("0.0 0.0 moveto 4.0 2.0 5.0 4.0 3.0 6.0 curveto", repr(pen))
81*e1fe3e4aSElliott Hughes        self.assertEqual((3.0, 6.0), pen.getCurrentPoint())
82*e1fe3e4aSElliott Hughes
83*e1fe3e4aSElliott Hughes    def test_curveTo_manyPoints(self):
84*e1fe3e4aSElliott Hughes        pen = _TestPen()
85*e1fe3e4aSElliott Hughes        pen.moveTo((0.0, 0.0))
86*e1fe3e4aSElliott Hughes        pen.curveTo((1.0, 1.1), (2.0, 2.1), (3.0, 3.1), (4.0, 4.1))
87*e1fe3e4aSElliott Hughes        self.assertEqual(
88*e1fe3e4aSElliott Hughes            "0.0 0.0 moveto "
89*e1fe3e4aSElliott Hughes            "1.0 1.1 1.5 1.6 2.0 2.1 curveto "
90*e1fe3e4aSElliott Hughes            "2.5 2.6 3.0 3.1 4.0 4.1 curveto",
91*e1fe3e4aSElliott Hughes            repr(pen),
92*e1fe3e4aSElliott Hughes        )
93*e1fe3e4aSElliott Hughes        self.assertEqual((4.0, 4.1), pen.getCurrentPoint())
94*e1fe3e4aSElliott Hughes
95*e1fe3e4aSElliott Hughes    def test_qCurveTo_zeroPoints(self):
96*e1fe3e4aSElliott Hughes        pen = _TestPen()
97*e1fe3e4aSElliott Hughes        pen.moveTo((0.0, 0.0))
98*e1fe3e4aSElliott Hughes        self.assertRaises(AssertionError, pen.qCurveTo)
99*e1fe3e4aSElliott Hughes
100*e1fe3e4aSElliott Hughes    def test_qCurveTo_onePoint(self):
101*e1fe3e4aSElliott Hughes        pen = _TestPen()
102*e1fe3e4aSElliott Hughes        pen.moveTo((0.0, 0.0))
103*e1fe3e4aSElliott Hughes        pen.qCurveTo((77.7, 99.9))
104*e1fe3e4aSElliott Hughes        self.assertEqual("0.0 0.0 moveto 77.7 99.9 lineto", repr(pen))
105*e1fe3e4aSElliott Hughes        self.assertEqual((77.7, 99.9), pen.getCurrentPoint())
106*e1fe3e4aSElliott Hughes
107*e1fe3e4aSElliott Hughes    def test_qCurveTo_manyPoints(self):
108*e1fe3e4aSElliott Hughes        pen = _TestPen()
109*e1fe3e4aSElliott Hughes        pen.moveTo((0.0, 0.0))
110*e1fe3e4aSElliott Hughes        pen.qCurveTo((6.0, 3.0), (3.0, 6.0))
111*e1fe3e4aSElliott Hughes        self.assertEqual("0.0 0.0 moveto 4.0 2.0 5.0 4.0 3.0 6.0 curveto", repr(pen))
112*e1fe3e4aSElliott Hughes        self.assertEqual((3.0, 6.0), pen.getCurrentPoint())
113*e1fe3e4aSElliott Hughes
114*e1fe3e4aSElliott Hughes    def test_qCurveTo_onlyOffCurvePoints(self):
115*e1fe3e4aSElliott Hughes        pen = _TestPen()
116*e1fe3e4aSElliott Hughes        pen.moveTo((0.0, 0.0))
117*e1fe3e4aSElliott Hughes        pen.qCurveTo((6.0, -6.0), (12.0, 12.0), (18.0, -18.0), None)
118*e1fe3e4aSElliott Hughes        self.assertEqual(
119*e1fe3e4aSElliott Hughes            "0.0 0.0 moveto "
120*e1fe3e4aSElliott Hughes            "12.0 -12.0 moveto "
121*e1fe3e4aSElliott Hughes            "8.0 -8.0 7.0 -3.0 9.0 3.0 curveto "
122*e1fe3e4aSElliott Hughes            "11.0 9.0 13.0 7.0 15.0 -3.0 curveto "
123*e1fe3e4aSElliott Hughes            "17.0 -13.0 16.0 -16.0 12.0 -12.0 curveto",
124*e1fe3e4aSElliott Hughes            repr(pen),
125*e1fe3e4aSElliott Hughes        )
126*e1fe3e4aSElliott Hughes        self.assertEqual((12.0, -12.0), pen.getCurrentPoint())
127*e1fe3e4aSElliott Hughes
128*e1fe3e4aSElliott Hughes    def test_closePath(self):
129*e1fe3e4aSElliott Hughes        pen = _TestPen()
130*e1fe3e4aSElliott Hughes        pen.lineTo((3, 4))
131*e1fe3e4aSElliott Hughes        pen.closePath()
132*e1fe3e4aSElliott Hughes        self.assertEqual("3 4 lineto closepath", repr(pen))
133*e1fe3e4aSElliott Hughes        self.assertEqual(None, pen.getCurrentPoint())
134*e1fe3e4aSElliott Hughes
135*e1fe3e4aSElliott Hughes    def test_endPath(self):
136*e1fe3e4aSElliott Hughes        pen = _TestPen()
137*e1fe3e4aSElliott Hughes        pen.lineTo((3, 4))
138*e1fe3e4aSElliott Hughes        pen.endPath()
139*e1fe3e4aSElliott Hughes        self.assertEqual("3 4 lineto endpath", repr(pen))
140*e1fe3e4aSElliott Hughes        self.assertEqual(None, pen.getCurrentPoint())
141*e1fe3e4aSElliott Hughes
142*e1fe3e4aSElliott Hughes    def test_addComponent(self):
143*e1fe3e4aSElliott Hughes        pen = _TestPen()
144*e1fe3e4aSElliott Hughes        pen.glyphSet["oslash"] = _TestGlyph()
145*e1fe3e4aSElliott Hughes        pen.addComponent("oslash", (2, 3, 0.5, 2, -10, 0))
146*e1fe3e4aSElliott Hughes        self.assertEqual(
147*e1fe3e4aSElliott Hughes            "-10.0 0.0 moveto "
148*e1fe3e4aSElliott Hughes            "40.0 200.0 lineto "
149*e1fe3e4aSElliott Hughes            "127.5 300.0 131.25 290.0 125.0 265.0 curveto "
150*e1fe3e4aSElliott Hughes            "118.75 240.0 102.5 200.0 -10.0 0.0 curveto "
151*e1fe3e4aSElliott Hughes            "closepath",
152*e1fe3e4aSElliott Hughes            repr(pen),
153*e1fe3e4aSElliott Hughes        )
154*e1fe3e4aSElliott Hughes        self.assertEqual(None, pen.getCurrentPoint())
155*e1fe3e4aSElliott Hughes
156*e1fe3e4aSElliott Hughes    def test_addComponent_skip_missing(self):
157*e1fe3e4aSElliott Hughes        pen = _TestPen()
158*e1fe3e4aSElliott Hughes        with CapturingLogHandler(pen.log, "WARNING") as captor:
159*e1fe3e4aSElliott Hughes            pen.addComponent("nonexistent", (1, 0, 0, 1, 0, 0))
160*e1fe3e4aSElliott Hughes        captor.assertRegex("glyph '.*' is missing from glyphSet; skipped")
161*e1fe3e4aSElliott Hughes
162*e1fe3e4aSElliott Hughes
163*e1fe3e4aSElliott Hughesclass DecomposeSegmentTest(unittest.TestCase):
164*e1fe3e4aSElliott Hughes    def test_decomposeSuperBezierSegment(self):
165*e1fe3e4aSElliott Hughes        decompose = decomposeSuperBezierSegment
166*e1fe3e4aSElliott Hughes        self.assertRaises(AssertionError, decompose, [])
167*e1fe3e4aSElliott Hughes        self.assertRaises(AssertionError, decompose, [(0, 0)])
168*e1fe3e4aSElliott Hughes        self.assertRaises(AssertionError, decompose, [(0, 0), (1, 1)])
169*e1fe3e4aSElliott Hughes        self.assertEqual(
170*e1fe3e4aSElliott Hughes            [((0, 0), (1, 1), (2, 2))], decompose([(0, 0), (1, 1), (2, 2)])
171*e1fe3e4aSElliott Hughes        )
172*e1fe3e4aSElliott Hughes        self.assertEqual(
173*e1fe3e4aSElliott Hughes            [((0, 0), (2, -2), (4, 0)), ((6, 2), (8, 8), (12, -12))],
174*e1fe3e4aSElliott Hughes            decompose([(0, 0), (4, -4), (8, 8), (12, -12)]),
175*e1fe3e4aSElliott Hughes        )
176*e1fe3e4aSElliott Hughes
177*e1fe3e4aSElliott Hughes    def test_decomposeQuadraticSegment(self):
178*e1fe3e4aSElliott Hughes        decompose = decomposeQuadraticSegment
179*e1fe3e4aSElliott Hughes        self.assertRaises(AssertionError, decompose, [])
180*e1fe3e4aSElliott Hughes        self.assertRaises(AssertionError, decompose, [(0, 0)])
181*e1fe3e4aSElliott Hughes        self.assertEqual([((0, 0), (4, 8))], decompose([(0, 0), (4, 8)]))
182*e1fe3e4aSElliott Hughes        self.assertEqual(
183*e1fe3e4aSElliott Hughes            [((0, 0), (2, 4)), ((4, 8), (9, -9))], decompose([(0, 0), (4, 8), (9, -9)])
184*e1fe3e4aSElliott Hughes        )
185*e1fe3e4aSElliott Hughes        self.assertEqual(
186*e1fe3e4aSElliott Hughes            [((0, 0), (2.0, 4.0)), ((4, 8), (6.5, -0.5)), ((9, -9), (10, 10))],
187*e1fe3e4aSElliott Hughes            decompose([(0, 0), (4, 8), (9, -9), (10, 10)]),
188*e1fe3e4aSElliott Hughes        )
189*e1fe3e4aSElliott Hughes
190*e1fe3e4aSElliott Hughes
191*e1fe3e4aSElliott Hughesif __name__ == "__main__":
192*e1fe3e4aSElliott Hughes    import sys
193*e1fe3e4aSElliott Hughes
194*e1fe3e4aSElliott Hughes    sys.exit(unittest.main())
195