xref: /aosp_15_r20/external/fonttools/Tests/pens/quartzPen_test.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
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