1import unittest 2 3try: 4 from fontTools.pens.quartzPen import QuartzPen 5 6 from Quartz.CoreGraphics import CGPathApply 7 from Quartz.CoreGraphics import kCGPathElementMoveToPoint 8 from Quartz.CoreGraphics import kCGPathElementAddLineToPoint 9 from Quartz.CoreGraphics import kCGPathElementAddQuadCurveToPoint 10 from Quartz.CoreGraphics import kCGPathElementAddCurveToPoint 11 from Quartz.CoreGraphics import kCGPathElementCloseSubpath 12 13 PATH_ELEMENTS = { 14 # CG constant key desc num_points 15 kCGPathElementMoveToPoint: ("moveto", 1), 16 kCGPathElementAddLineToPoint: ("lineto", 1), 17 kCGPathElementAddCurveToPoint: ("curveto", 3), 18 kCGPathElementAddQuadCurveToPoint: ("qcurveto", 2), 19 kCGPathElementCloseSubpath: ("close", 0), 20 } 21 22 PYOBJC_AVAILABLE = True 23except ImportError: 24 PYOBJC_AVAILABLE = False 25 26 27def draw(pen): 28 pen.moveTo((50, 0)) 29 pen.lineTo((50, 500)) 30 pen.lineTo((200, 500)) 31 pen.curveTo((350, 500), (450, 400), (450, 250)) 32 pen.curveTo((450, 100), (350, 0), (200, 0)) 33 pen.closePath() 34 35 36def quartzPathApplier(elements, element): 37 num_points = 0 38 elem_type = None 39 if element.type in PATH_ELEMENTS: 40 num_points = PATH_ELEMENTS[element.type][1] 41 elem_type = PATH_ELEMENTS[element.type][0] 42 elements.append((elem_type, element.points.as_tuple(num_points))) 43 44 45def quartzPathElements(path): 46 elements = [] 47 CGPathApply(path, elements, quartzPathApplier) 48 return elements 49 50 51def quartzPathToString(path): 52 elements = quartzPathElements(path) 53 output = [] 54 for element in elements: 55 elem_type, elem_points = element 56 path_points = " ".join([f"{p.x} {p.y}" for p in elem_points]) 57 output.append(f"{elem_type} {path_points}") 58 return " ".join(output) 59 60 61@unittest.skipUnless(PYOBJC_AVAILABLE, "pyobjc not installed") 62class QuartzPenTest(unittest.TestCase): 63 def test_draw(self): 64 pen = QuartzPen(None) 65 draw(pen) 66 self.assertEqual( 67 "moveto 50.0 0.0 lineto 50.0 500.0 lineto 200.0 500.0 curveto 350.0 500.0 450.0 400.0 450.0 250.0 curveto 450.0 100.0 350.0 0.0 200.0 0.0 close ", 68 quartzPathToString(pen.path), 69 ) 70 71 def test_empty(self): 72 pen = QuartzPen(None) 73 self.assertEqual("", quartzPathToString(pen.path)) 74 75 76if __name__ == "__main__": 77 import sys 78 79 sys.exit(unittest.main()) 80