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