xref: /aosp_15_r20/external/fonttools/Tests/pens/cu2quPen_test.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1*e1fe3e4aSElliott Hughes# Copyright 2016 Google Inc. All Rights Reserved.
2*e1fe3e4aSElliott Hughes#
3*e1fe3e4aSElliott Hughes# Licensed under the Apache License, Version 2.0 (the "License");
4*e1fe3e4aSElliott Hughes# you may not use this file except in compliance with the License.
5*e1fe3e4aSElliott Hughes# You may obtain a copy of the License at
6*e1fe3e4aSElliott Hughes#
7*e1fe3e4aSElliott Hughes#     http://www.apache.org/licenses/LICENSE-2.0
8*e1fe3e4aSElliott Hughes#
9*e1fe3e4aSElliott Hughes# Unless required by applicable law or agreed to in writing, software
10*e1fe3e4aSElliott Hughes# distributed under the License is distributed on an "AS IS" BASIS,
11*e1fe3e4aSElliott Hughes# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e1fe3e4aSElliott Hughes# See the License for the specific language governing permissions and
13*e1fe3e4aSElliott Hughes# limitations under the License.
14*e1fe3e4aSElliott Hughes
15*e1fe3e4aSElliott Hughesimport sys
16*e1fe3e4aSElliott Hughesimport unittest
17*e1fe3e4aSElliott Hughes
18*e1fe3e4aSElliott Hughesfrom fontTools.pens.cu2quPen import Cu2QuPen, Cu2QuPointPen, Cu2QuMultiPen
19*e1fe3e4aSElliott Hughesfrom fontTools.pens.recordingPen import RecordingPen, RecordingPointPen
20*e1fe3e4aSElliott Hughesfrom fontTools.misc.loggingTools import CapturingLogHandler
21*e1fe3e4aSElliott Hughesfrom textwrap import dedent
22*e1fe3e4aSElliott Hughesimport logging
23*e1fe3e4aSElliott Hughesimport pytest
24*e1fe3e4aSElliott Hughes
25*e1fe3e4aSElliott Hughestry:
26*e1fe3e4aSElliott Hughes    from .utils import CUBIC_GLYPHS, QUAD_GLYPHS
27*e1fe3e4aSElliott Hughes    from .utils import DummyGlyph, DummyPointGlyph
28*e1fe3e4aSElliott Hughes    from .utils import DummyPen, DummyPointPen
29*e1fe3e4aSElliott Hughesexcept ImportError as e:
30*e1fe3e4aSElliott Hughes    pytest.skip(str(e), allow_module_level=True)
31*e1fe3e4aSElliott Hughes
32*e1fe3e4aSElliott Hughes
33*e1fe3e4aSElliott HughesMAX_ERR = 1.0
34*e1fe3e4aSElliott Hughes
35*e1fe3e4aSElliott Hughes
36*e1fe3e4aSElliott Hughesclass _TestPenMixin(object):
37*e1fe3e4aSElliott Hughes    """Collection of tests that are shared by both the SegmentPen and the
38*e1fe3e4aSElliott Hughes    PointPen test cases, plus some helper methods.
39*e1fe3e4aSElliott Hughes    """
40*e1fe3e4aSElliott Hughes
41*e1fe3e4aSElliott Hughes    maxDiff = None
42*e1fe3e4aSElliott Hughes
43*e1fe3e4aSElliott Hughes    def diff(self, expected, actual):
44*e1fe3e4aSElliott Hughes        import difflib
45*e1fe3e4aSElliott Hughes
46*e1fe3e4aSElliott Hughes        expected = str(self.Glyph(expected)).splitlines(True)
47*e1fe3e4aSElliott Hughes        actual = str(self.Glyph(actual)).splitlines(True)
48*e1fe3e4aSElliott Hughes        diff = difflib.unified_diff(
49*e1fe3e4aSElliott Hughes            expected, actual, fromfile="expected", tofile="actual"
50*e1fe3e4aSElliott Hughes        )
51*e1fe3e4aSElliott Hughes        return "".join(diff)
52*e1fe3e4aSElliott Hughes
53*e1fe3e4aSElliott Hughes    def convert_glyph(self, glyph, **kwargs):
54*e1fe3e4aSElliott Hughes        # draw source glyph onto a new glyph using a Cu2Qu pen and return it
55*e1fe3e4aSElliott Hughes        converted = self.Glyph()
56*e1fe3e4aSElliott Hughes        pen = getattr(converted, self.pen_getter_name)()
57*e1fe3e4aSElliott Hughes        quadpen = self.Cu2QuPen(pen, MAX_ERR, **kwargs)
58*e1fe3e4aSElliott Hughes        getattr(glyph, self.draw_method_name)(quadpen)
59*e1fe3e4aSElliott Hughes        return converted
60*e1fe3e4aSElliott Hughes
61*e1fe3e4aSElliott Hughes    def expect_glyph(self, source, expected):
62*e1fe3e4aSElliott Hughes        converted = self.convert_glyph(source)
63*e1fe3e4aSElliott Hughes        self.assertNotEqual(converted, source)
64*e1fe3e4aSElliott Hughes        if not converted.approx(expected):
65*e1fe3e4aSElliott Hughes            print(self.diff(expected, converted))
66*e1fe3e4aSElliott Hughes            self.fail("converted glyph is different from expected")
67*e1fe3e4aSElliott Hughes
68*e1fe3e4aSElliott Hughes    def test_convert_simple_glyph(self):
69*e1fe3e4aSElliott Hughes        self.expect_glyph(CUBIC_GLYPHS["a"], QUAD_GLYPHS["a"])
70*e1fe3e4aSElliott Hughes        self.expect_glyph(CUBIC_GLYPHS["A"], QUAD_GLYPHS["A"])
71*e1fe3e4aSElliott Hughes
72*e1fe3e4aSElliott Hughes    def test_convert_composite_glyph(self):
73*e1fe3e4aSElliott Hughes        source = CUBIC_GLYPHS["Aacute"]
74*e1fe3e4aSElliott Hughes        converted = self.convert_glyph(source)
75*e1fe3e4aSElliott Hughes        # components don't change after quadratic conversion
76*e1fe3e4aSElliott Hughes        self.assertEqual(converted, source)
77*e1fe3e4aSElliott Hughes
78*e1fe3e4aSElliott Hughes    def test_convert_mixed_glyph(self):
79*e1fe3e4aSElliott Hughes        # this contains a mix of contours and components
80*e1fe3e4aSElliott Hughes        self.expect_glyph(CUBIC_GLYPHS["Eacute"], QUAD_GLYPHS["Eacute"])
81*e1fe3e4aSElliott Hughes
82*e1fe3e4aSElliott Hughes    def test_reverse_direction(self):
83*e1fe3e4aSElliott Hughes        for name in ("a", "A", "Eacute"):
84*e1fe3e4aSElliott Hughes            source = CUBIC_GLYPHS[name]
85*e1fe3e4aSElliott Hughes            normal_glyph = self.convert_glyph(source)
86*e1fe3e4aSElliott Hughes            reversed_glyph = self.convert_glyph(source, reverse_direction=True)
87*e1fe3e4aSElliott Hughes
88*e1fe3e4aSElliott Hughes            # the number of commands is the same, just their order is iverted
89*e1fe3e4aSElliott Hughes            self.assertTrue(len(normal_glyph.outline), len(reversed_glyph.outline))
90*e1fe3e4aSElliott Hughes            self.assertNotEqual(normal_glyph, reversed_glyph)
91*e1fe3e4aSElliott Hughes
92*e1fe3e4aSElliott Hughes    def test_stats(self):
93*e1fe3e4aSElliott Hughes        stats = {}
94*e1fe3e4aSElliott Hughes        for name in CUBIC_GLYPHS.keys():
95*e1fe3e4aSElliott Hughes            source = CUBIC_GLYPHS[name]
96*e1fe3e4aSElliott Hughes            self.convert_glyph(source, stats=stats)
97*e1fe3e4aSElliott Hughes
98*e1fe3e4aSElliott Hughes        self.assertTrue(stats)
99*e1fe3e4aSElliott Hughes        self.assertTrue("1" in stats)
100*e1fe3e4aSElliott Hughes        self.assertEqual(type(stats["1"]), int)
101*e1fe3e4aSElliott Hughes
102*e1fe3e4aSElliott Hughes    def test_addComponent(self):
103*e1fe3e4aSElliott Hughes        pen = self.Pen()
104*e1fe3e4aSElliott Hughes        quadpen = self.Cu2QuPen(pen, MAX_ERR)
105*e1fe3e4aSElliott Hughes        quadpen.addComponent("a", (1, 2, 3, 4, 5.0, 6.0))
106*e1fe3e4aSElliott Hughes
107*e1fe3e4aSElliott Hughes        # components are passed through without changes
108*e1fe3e4aSElliott Hughes        self.assertEqual(
109*e1fe3e4aSElliott Hughes            str(pen).splitlines(),
110*e1fe3e4aSElliott Hughes            [
111*e1fe3e4aSElliott Hughes                "pen.addComponent('a', (1, 2, 3, 4, 5.0, 6.0))",
112*e1fe3e4aSElliott Hughes            ],
113*e1fe3e4aSElliott Hughes        )
114*e1fe3e4aSElliott Hughes
115*e1fe3e4aSElliott Hughes
116*e1fe3e4aSElliott Hughesclass TestCu2QuPen(unittest.TestCase, _TestPenMixin):
117*e1fe3e4aSElliott Hughes    def __init__(self, *args, **kwargs):
118*e1fe3e4aSElliott Hughes        super(TestCu2QuPen, self).__init__(*args, **kwargs)
119*e1fe3e4aSElliott Hughes        self.Glyph = DummyGlyph
120*e1fe3e4aSElliott Hughes        self.Pen = DummyPen
121*e1fe3e4aSElliott Hughes        self.Cu2QuPen = Cu2QuPen
122*e1fe3e4aSElliott Hughes        self.pen_getter_name = "getPen"
123*e1fe3e4aSElliott Hughes        self.draw_method_name = "draw"
124*e1fe3e4aSElliott Hughes
125*e1fe3e4aSElliott Hughes    def test_qCurveTo_1_point(self):
126*e1fe3e4aSElliott Hughes        pen = DummyPen()
127*e1fe3e4aSElliott Hughes        quadpen = Cu2QuPen(pen, MAX_ERR)
128*e1fe3e4aSElliott Hughes        quadpen.moveTo((0, 0))
129*e1fe3e4aSElliott Hughes        quadpen.qCurveTo((1, 1))
130*e1fe3e4aSElliott Hughes
131*e1fe3e4aSElliott Hughes        self.assertEqual(
132*e1fe3e4aSElliott Hughes            str(pen).splitlines(),
133*e1fe3e4aSElliott Hughes            [
134*e1fe3e4aSElliott Hughes                "pen.moveTo((0, 0))",
135*e1fe3e4aSElliott Hughes                "pen.qCurveTo((1, 1))",
136*e1fe3e4aSElliott Hughes            ],
137*e1fe3e4aSElliott Hughes        )
138*e1fe3e4aSElliott Hughes
139*e1fe3e4aSElliott Hughes    def test_qCurveTo_more_than_1_point(self):
140*e1fe3e4aSElliott Hughes        pen = DummyPen()
141*e1fe3e4aSElliott Hughes        quadpen = Cu2QuPen(pen, MAX_ERR)
142*e1fe3e4aSElliott Hughes        quadpen.moveTo((0, 0))
143*e1fe3e4aSElliott Hughes        quadpen.qCurveTo((1, 1), (2, 2))
144*e1fe3e4aSElliott Hughes
145*e1fe3e4aSElliott Hughes        self.assertEqual(
146*e1fe3e4aSElliott Hughes            str(pen).splitlines(),
147*e1fe3e4aSElliott Hughes            [
148*e1fe3e4aSElliott Hughes                "pen.moveTo((0, 0))",
149*e1fe3e4aSElliott Hughes                "pen.qCurveTo((1, 1), (2, 2))",
150*e1fe3e4aSElliott Hughes            ],
151*e1fe3e4aSElliott Hughes        )
152*e1fe3e4aSElliott Hughes
153*e1fe3e4aSElliott Hughes    def test_curveTo_1_point(self):
154*e1fe3e4aSElliott Hughes        pen = DummyPen()
155*e1fe3e4aSElliott Hughes        quadpen = Cu2QuPen(pen, MAX_ERR)
156*e1fe3e4aSElliott Hughes        quadpen.moveTo((0, 0))
157*e1fe3e4aSElliott Hughes        quadpen.curveTo((1, 1))
158*e1fe3e4aSElliott Hughes
159*e1fe3e4aSElliott Hughes        self.assertEqual(
160*e1fe3e4aSElliott Hughes            str(pen).splitlines(),
161*e1fe3e4aSElliott Hughes            [
162*e1fe3e4aSElliott Hughes                "pen.moveTo((0, 0))",
163*e1fe3e4aSElliott Hughes                "pen.qCurveTo((1, 1))",
164*e1fe3e4aSElliott Hughes            ],
165*e1fe3e4aSElliott Hughes        )
166*e1fe3e4aSElliott Hughes
167*e1fe3e4aSElliott Hughes    def test_curveTo_2_points(self):
168*e1fe3e4aSElliott Hughes        pen = DummyPen()
169*e1fe3e4aSElliott Hughes        quadpen = Cu2QuPen(pen, MAX_ERR)
170*e1fe3e4aSElliott Hughes        quadpen.moveTo((0, 0))
171*e1fe3e4aSElliott Hughes        quadpen.curveTo((1, 1), (2, 2))
172*e1fe3e4aSElliott Hughes
173*e1fe3e4aSElliott Hughes        self.assertEqual(
174*e1fe3e4aSElliott Hughes            str(pen).splitlines(),
175*e1fe3e4aSElliott Hughes            [
176*e1fe3e4aSElliott Hughes                "pen.moveTo((0, 0))",
177*e1fe3e4aSElliott Hughes                "pen.qCurveTo((1, 1), (2, 2))",
178*e1fe3e4aSElliott Hughes            ],
179*e1fe3e4aSElliott Hughes        )
180*e1fe3e4aSElliott Hughes
181*e1fe3e4aSElliott Hughes    def test_curveTo_3_points(self):
182*e1fe3e4aSElliott Hughes        pen = DummyPen()
183*e1fe3e4aSElliott Hughes        quadpen = Cu2QuPen(pen, MAX_ERR)
184*e1fe3e4aSElliott Hughes        quadpen.moveTo((0, 0))
185*e1fe3e4aSElliott Hughes        quadpen.curveTo((1, 1), (2, 2), (3, 3))
186*e1fe3e4aSElliott Hughes
187*e1fe3e4aSElliott Hughes        self.assertEqual(
188*e1fe3e4aSElliott Hughes            str(pen).splitlines(),
189*e1fe3e4aSElliott Hughes            [
190*e1fe3e4aSElliott Hughes                "pen.moveTo((0, 0))",
191*e1fe3e4aSElliott Hughes                "pen.qCurveTo((0.75, 0.75), (2.25, 2.25), (3, 3))",
192*e1fe3e4aSElliott Hughes            ],
193*e1fe3e4aSElliott Hughes        )
194*e1fe3e4aSElliott Hughes
195*e1fe3e4aSElliott Hughes    def test_curveTo_more_than_3_points(self):
196*e1fe3e4aSElliott Hughes        # a 'SuperBezier' as described in fontTools.basePen.AbstractPen
197*e1fe3e4aSElliott Hughes        pen = DummyPen()
198*e1fe3e4aSElliott Hughes        quadpen = Cu2QuPen(pen, MAX_ERR)
199*e1fe3e4aSElliott Hughes        quadpen.moveTo((0, 0))
200*e1fe3e4aSElliott Hughes        quadpen.curveTo((1, 1), (2, 2), (3, 3), (4, 4))
201*e1fe3e4aSElliott Hughes
202*e1fe3e4aSElliott Hughes        self.assertEqual(
203*e1fe3e4aSElliott Hughes            str(pen).splitlines(),
204*e1fe3e4aSElliott Hughes            [
205*e1fe3e4aSElliott Hughes                "pen.moveTo((0, 0))",
206*e1fe3e4aSElliott Hughes                "pen.qCurveTo((0.75, 0.75), (1.625, 1.625), (2, 2))",
207*e1fe3e4aSElliott Hughes                "pen.qCurveTo((2.375, 2.375), (3.25, 3.25), (4, 4))",
208*e1fe3e4aSElliott Hughes            ],
209*e1fe3e4aSElliott Hughes        )
210*e1fe3e4aSElliott Hughes
211*e1fe3e4aSElliott Hughes
212*e1fe3e4aSElliott Hughesclass TestCu2QuPointPen(unittest.TestCase, _TestPenMixin):
213*e1fe3e4aSElliott Hughes    def __init__(self, *args, **kwargs):
214*e1fe3e4aSElliott Hughes        super(TestCu2QuPointPen, self).__init__(*args, **kwargs)
215*e1fe3e4aSElliott Hughes        self.Glyph = DummyPointGlyph
216*e1fe3e4aSElliott Hughes        self.Pen = DummyPointPen
217*e1fe3e4aSElliott Hughes        self.Cu2QuPen = Cu2QuPointPen
218*e1fe3e4aSElliott Hughes        self.pen_getter_name = "getPointPen"
219*e1fe3e4aSElliott Hughes        self.draw_method_name = "drawPoints"
220*e1fe3e4aSElliott Hughes
221*e1fe3e4aSElliott Hughes    def test_super_bezier_curve(self):
222*e1fe3e4aSElliott Hughes        pen = DummyPointPen()
223*e1fe3e4aSElliott Hughes        quadpen = Cu2QuPointPen(pen, MAX_ERR)
224*e1fe3e4aSElliott Hughes        quadpen.beginPath()
225*e1fe3e4aSElliott Hughes        quadpen.addPoint((0, 0), segmentType="move")
226*e1fe3e4aSElliott Hughes        quadpen.addPoint((1, 1))
227*e1fe3e4aSElliott Hughes        quadpen.addPoint((2, 2))
228*e1fe3e4aSElliott Hughes        quadpen.addPoint((3, 3))
229*e1fe3e4aSElliott Hughes        quadpen.addPoint(
230*e1fe3e4aSElliott Hughes            (4, 4), segmentType="curve", smooth=False, name="up", selected=1
231*e1fe3e4aSElliott Hughes        )
232*e1fe3e4aSElliott Hughes        quadpen.endPath()
233*e1fe3e4aSElliott Hughes
234*e1fe3e4aSElliott Hughes        self.assertEqual(
235*e1fe3e4aSElliott Hughes            str(pen).splitlines(),
236*e1fe3e4aSElliott Hughes            """\
237*e1fe3e4aSElliott Hughespen.beginPath()
238*e1fe3e4aSElliott Hughespen.addPoint((0, 0), name=None, segmentType='move', smooth=False)
239*e1fe3e4aSElliott Hughespen.addPoint((0.75, 0.75), name=None, segmentType=None, smooth=False)
240*e1fe3e4aSElliott Hughespen.addPoint((1.625, 1.625), name=None, segmentType=None, smooth=False)
241*e1fe3e4aSElliott Hughespen.addPoint((2, 2), name=None, segmentType='qcurve', smooth=True)
242*e1fe3e4aSElliott Hughespen.addPoint((2.375, 2.375), name=None, segmentType=None, smooth=False)
243*e1fe3e4aSElliott Hughespen.addPoint((3.25, 3.25), name=None, segmentType=None, smooth=False)
244*e1fe3e4aSElliott Hughespen.addPoint((4, 4), name='up', segmentType='qcurve', selected=1, smooth=False)
245*e1fe3e4aSElliott Hughespen.endPath()""".splitlines(),
246*e1fe3e4aSElliott Hughes        )
247*e1fe3e4aSElliott Hughes
248*e1fe3e4aSElliott Hughes    def test__flushContour_restore_starting_point(self):
249*e1fe3e4aSElliott Hughes        pen = DummyPointPen()
250*e1fe3e4aSElliott Hughes        quadpen = Cu2QuPointPen(pen, MAX_ERR)
251*e1fe3e4aSElliott Hughes
252*e1fe3e4aSElliott Hughes        # collect the output of _flushContour before it's sent to _drawPoints
253*e1fe3e4aSElliott Hughes        new_segments = []
254*e1fe3e4aSElliott Hughes
255*e1fe3e4aSElliott Hughes        def _drawPoints(segments):
256*e1fe3e4aSElliott Hughes            new_segments.extend(segments)
257*e1fe3e4aSElliott Hughes            Cu2QuPointPen._drawPoints(quadpen, segments)
258*e1fe3e4aSElliott Hughes
259*e1fe3e4aSElliott Hughes        quadpen._drawPoints = _drawPoints
260*e1fe3e4aSElliott Hughes
261*e1fe3e4aSElliott Hughes        # a closed path (ie. no "move" segmentType)
262*e1fe3e4aSElliott Hughes        quadpen._flushContour(
263*e1fe3e4aSElliott Hughes            [
264*e1fe3e4aSElliott Hughes                (
265*e1fe3e4aSElliott Hughes                    "curve",
266*e1fe3e4aSElliott Hughes                    [
267*e1fe3e4aSElliott Hughes                        ((2, 2), False, None, {}),
268*e1fe3e4aSElliott Hughes                        ((1, 1), False, None, {}),
269*e1fe3e4aSElliott Hughes                        ((0, 0), False, None, {}),
270*e1fe3e4aSElliott Hughes                    ],
271*e1fe3e4aSElliott Hughes                ),
272*e1fe3e4aSElliott Hughes                (
273*e1fe3e4aSElliott Hughes                    "curve",
274*e1fe3e4aSElliott Hughes                    [
275*e1fe3e4aSElliott Hughes                        ((1, 1), False, None, {}),
276*e1fe3e4aSElliott Hughes                        ((2, 2), False, None, {}),
277*e1fe3e4aSElliott Hughes                        ((3, 3), False, None, {}),
278*e1fe3e4aSElliott Hughes                    ],
279*e1fe3e4aSElliott Hughes                ),
280*e1fe3e4aSElliott Hughes            ]
281*e1fe3e4aSElliott Hughes        )
282*e1fe3e4aSElliott Hughes
283*e1fe3e4aSElliott Hughes        # the original starting point is restored: the last segment has become
284*e1fe3e4aSElliott Hughes        # the first
285*e1fe3e4aSElliott Hughes        self.assertEqual(new_segments[0][1][-1][0], (3, 3))
286*e1fe3e4aSElliott Hughes        self.assertEqual(new_segments[-1][1][-1][0], (0, 0))
287*e1fe3e4aSElliott Hughes
288*e1fe3e4aSElliott Hughes        new_segments = []
289*e1fe3e4aSElliott Hughes        # an open path (ie. starting with "move")
290*e1fe3e4aSElliott Hughes        quadpen._flushContour(
291*e1fe3e4aSElliott Hughes            [
292*e1fe3e4aSElliott Hughes                (
293*e1fe3e4aSElliott Hughes                    "move",
294*e1fe3e4aSElliott Hughes                    [
295*e1fe3e4aSElliott Hughes                        ((0, 0), False, None, {}),
296*e1fe3e4aSElliott Hughes                    ],
297*e1fe3e4aSElliott Hughes                ),
298*e1fe3e4aSElliott Hughes                (
299*e1fe3e4aSElliott Hughes                    "curve",
300*e1fe3e4aSElliott Hughes                    [
301*e1fe3e4aSElliott Hughes                        ((1, 1), False, None, {}),
302*e1fe3e4aSElliott Hughes                        ((2, 2), False, None, {}),
303*e1fe3e4aSElliott Hughes                        ((3, 3), False, None, {}),
304*e1fe3e4aSElliott Hughes                    ],
305*e1fe3e4aSElliott Hughes                ),
306*e1fe3e4aSElliott Hughes            ]
307*e1fe3e4aSElliott Hughes        )
308*e1fe3e4aSElliott Hughes
309*e1fe3e4aSElliott Hughes        # the segment order stays the same before and after _flushContour
310*e1fe3e4aSElliott Hughes        self.assertEqual(new_segments[0][1][-1][0], (0, 0))
311*e1fe3e4aSElliott Hughes        self.assertEqual(new_segments[-1][1][-1][0], (3, 3))
312*e1fe3e4aSElliott Hughes
313*e1fe3e4aSElliott Hughes    def test_quad_no_oncurve(self):
314*e1fe3e4aSElliott Hughes        """When passed a contour which has no on-curve points, the
315*e1fe3e4aSElliott Hughes        Cu2QuPointPen will treat it as a special quadratic contour whose
316*e1fe3e4aSElliott Hughes        first point has 'None' coordinates.
317*e1fe3e4aSElliott Hughes        """
318*e1fe3e4aSElliott Hughes        self.maxDiff = None
319*e1fe3e4aSElliott Hughes        pen = DummyPointPen()
320*e1fe3e4aSElliott Hughes        quadpen = Cu2QuPointPen(pen, MAX_ERR)
321*e1fe3e4aSElliott Hughes        quadpen.beginPath()
322*e1fe3e4aSElliott Hughes        quadpen.addPoint((1, 1))
323*e1fe3e4aSElliott Hughes        quadpen.addPoint((2, 2))
324*e1fe3e4aSElliott Hughes        quadpen.addPoint((3, 3))
325*e1fe3e4aSElliott Hughes        quadpen.endPath()
326*e1fe3e4aSElliott Hughes
327*e1fe3e4aSElliott Hughes        self.assertEqual(
328*e1fe3e4aSElliott Hughes            str(pen),
329*e1fe3e4aSElliott Hughes            dedent(
330*e1fe3e4aSElliott Hughes                """\
331*e1fe3e4aSElliott Hughes                pen.beginPath()
332*e1fe3e4aSElliott Hughes                pen.addPoint((1, 1), name=None, segmentType=None, smooth=False)
333*e1fe3e4aSElliott Hughes                pen.addPoint((2, 2), name=None, segmentType=None, smooth=False)
334*e1fe3e4aSElliott Hughes                pen.addPoint((3, 3), name=None, segmentType=None, smooth=False)
335*e1fe3e4aSElliott Hughes                pen.endPath()"""
336*e1fe3e4aSElliott Hughes            ),
337*e1fe3e4aSElliott Hughes        )
338*e1fe3e4aSElliott Hughes
339*e1fe3e4aSElliott Hughes
340*e1fe3e4aSElliott Hughesclass TestCu2QuMultiPen(unittest.TestCase):
341*e1fe3e4aSElliott Hughes    def test_multi_pen(self):
342*e1fe3e4aSElliott Hughes        pens = [RecordingPen(), RecordingPen()]
343*e1fe3e4aSElliott Hughes        pen = Cu2QuMultiPen(pens, 0.1)
344*e1fe3e4aSElliott Hughes        pen.moveTo([((0, 0),), ((0, 0),)])
345*e1fe3e4aSElliott Hughes        pen.lineTo([((0, 1),), ((0, 1),)])
346*e1fe3e4aSElliott Hughes        pen.qCurveTo([((0, 2),), ((0, 2),)])
347*e1fe3e4aSElliott Hughes        pen.qCurveTo([((0, 3), (1, 3)), ((0, 3), (1, 4))])
348*e1fe3e4aSElliott Hughes        pen.curveTo([((2, 3), (0, 3), (0, 0)), ((1.1, 4), (0, 4), (0, 0))])
349*e1fe3e4aSElliott Hughes        pen.closePath()
350*e1fe3e4aSElliott Hughes
351*e1fe3e4aSElliott Hughes        assert len(pens[0].value) == 6
352*e1fe3e4aSElliott Hughes        assert len(pens[1].value) == 6
353*e1fe3e4aSElliott Hughes
354*e1fe3e4aSElliott Hughes        for op0, op1 in zip(pens[0].value, pens[1].value):
355*e1fe3e4aSElliott Hughes            assert op0[0] == op0[0]
356*e1fe3e4aSElliott Hughes            assert op0[0] != "curveTo"
357*e1fe3e4aSElliott Hughes
358*e1fe3e4aSElliott Hughes
359*e1fe3e4aSElliott Hughesclass TestAllQuadraticFalse(unittest.TestCase):
360*e1fe3e4aSElliott Hughes    def test_segment_pen_cubic(self):
361*e1fe3e4aSElliott Hughes        rpen = RecordingPen()
362*e1fe3e4aSElliott Hughes        pen = Cu2QuPen(rpen, 0.1, all_quadratic=False)
363*e1fe3e4aSElliott Hughes
364*e1fe3e4aSElliott Hughes        pen.moveTo((0, 0))
365*e1fe3e4aSElliott Hughes        pen.curveTo((0, 1), (2, 1), (2, 0))
366*e1fe3e4aSElliott Hughes        pen.closePath()
367*e1fe3e4aSElliott Hughes
368*e1fe3e4aSElliott Hughes        assert rpen.value == [
369*e1fe3e4aSElliott Hughes            ("moveTo", ((0, 0),)),
370*e1fe3e4aSElliott Hughes            ("curveTo", ((0, 1), (2, 1), (2, 0))),
371*e1fe3e4aSElliott Hughes            ("closePath", ()),
372*e1fe3e4aSElliott Hughes        ]
373*e1fe3e4aSElliott Hughes
374*e1fe3e4aSElliott Hughes    def test_segment_pen_quadratic(self):
375*e1fe3e4aSElliott Hughes        rpen = RecordingPen()
376*e1fe3e4aSElliott Hughes        pen = Cu2QuPen(rpen, 0.1, all_quadratic=False)
377*e1fe3e4aSElliott Hughes
378*e1fe3e4aSElliott Hughes        pen.moveTo((0, 0))
379*e1fe3e4aSElliott Hughes        pen.curveTo((2, 2), (4, 2), (6, 0))
380*e1fe3e4aSElliott Hughes        pen.closePath()
381*e1fe3e4aSElliott Hughes
382*e1fe3e4aSElliott Hughes        assert rpen.value == [
383*e1fe3e4aSElliott Hughes            ("moveTo", ((0, 0),)),
384*e1fe3e4aSElliott Hughes            ("qCurveTo", ((3, 3), (6, 0))),
385*e1fe3e4aSElliott Hughes            ("closePath", ()),
386*e1fe3e4aSElliott Hughes        ]
387*e1fe3e4aSElliott Hughes
388*e1fe3e4aSElliott Hughes    def test_point_pen_cubic(self):
389*e1fe3e4aSElliott Hughes        rpen = RecordingPointPen()
390*e1fe3e4aSElliott Hughes        pen = Cu2QuPointPen(rpen, 0.1, all_quadratic=False)
391*e1fe3e4aSElliott Hughes
392*e1fe3e4aSElliott Hughes        pen.beginPath()
393*e1fe3e4aSElliott Hughes        pen.addPoint((0, 0), "move")
394*e1fe3e4aSElliott Hughes        pen.addPoint((0, 1))
395*e1fe3e4aSElliott Hughes        pen.addPoint((2, 1))
396*e1fe3e4aSElliott Hughes        pen.addPoint((2, 0), "curve")
397*e1fe3e4aSElliott Hughes        pen.endPath()
398*e1fe3e4aSElliott Hughes
399*e1fe3e4aSElliott Hughes        assert rpen.value == [
400*e1fe3e4aSElliott Hughes            ("beginPath", (), {}),
401*e1fe3e4aSElliott Hughes            ("addPoint", ((0, 0), "move", False, None), {}),
402*e1fe3e4aSElliott Hughes            ("addPoint", ((0, 1), None, False, None), {}),
403*e1fe3e4aSElliott Hughes            ("addPoint", ((2, 1), None, False, None), {}),
404*e1fe3e4aSElliott Hughes            ("addPoint", ((2, 0), "curve", False, None), {}),
405*e1fe3e4aSElliott Hughes            ("endPath", (), {}),
406*e1fe3e4aSElliott Hughes        ]
407*e1fe3e4aSElliott Hughes
408*e1fe3e4aSElliott Hughes    def test_point_pen_quadratic(self):
409*e1fe3e4aSElliott Hughes        rpen = RecordingPointPen()
410*e1fe3e4aSElliott Hughes        pen = Cu2QuPointPen(rpen, 0.1, all_quadratic=False)
411*e1fe3e4aSElliott Hughes
412*e1fe3e4aSElliott Hughes        pen.beginPath()
413*e1fe3e4aSElliott Hughes        pen.addPoint((0, 0), "move")
414*e1fe3e4aSElliott Hughes        pen.addPoint((2, 2))
415*e1fe3e4aSElliott Hughes        pen.addPoint((4, 2))
416*e1fe3e4aSElliott Hughes        pen.addPoint((6, 0), "curve")
417*e1fe3e4aSElliott Hughes        pen.endPath()
418*e1fe3e4aSElliott Hughes
419*e1fe3e4aSElliott Hughes        assert rpen.value == [
420*e1fe3e4aSElliott Hughes            ("beginPath", (), {}),
421*e1fe3e4aSElliott Hughes            ("addPoint", ((0, 0), "move", False, None), {}),
422*e1fe3e4aSElliott Hughes            ("addPoint", ((3, 3), None, False, None), {}),
423*e1fe3e4aSElliott Hughes            ("addPoint", ((6, 0), "qcurve", False, None), {}),
424*e1fe3e4aSElliott Hughes            ("endPath", (), {}),
425*e1fe3e4aSElliott Hughes        ]
426*e1fe3e4aSElliott Hughes
427*e1fe3e4aSElliott Hughes
428*e1fe3e4aSElliott Hughesif __name__ == "__main__":
429*e1fe3e4aSElliott Hughes    unittest.main()
430