xref: /aosp_15_r20/external/fonttools/Lib/fontTools/pens/explicitClosingLinePen.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1*e1fe3e4aSElliott Hughesfrom fontTools.pens.filterPen import ContourFilterPen
2*e1fe3e4aSElliott Hughes
3*e1fe3e4aSElliott Hughes
4*e1fe3e4aSElliott Hughesclass ExplicitClosingLinePen(ContourFilterPen):
5*e1fe3e4aSElliott Hughes    """A filter pen that adds an explicit lineTo to the first point of each closed
6*e1fe3e4aSElliott Hughes    contour if the end point of the last segment is not already the same as the first point.
7*e1fe3e4aSElliott Hughes    Otherwise, it passes the contour through unchanged.
8*e1fe3e4aSElliott Hughes
9*e1fe3e4aSElliott Hughes    >>> from pprint import pprint
10*e1fe3e4aSElliott Hughes    >>> from fontTools.pens.recordingPen import RecordingPen
11*e1fe3e4aSElliott Hughes    >>> rec = RecordingPen()
12*e1fe3e4aSElliott Hughes    >>> pen = ExplicitClosingLinePen(rec)
13*e1fe3e4aSElliott Hughes    >>> pen.moveTo((0, 0))
14*e1fe3e4aSElliott Hughes    >>> pen.lineTo((100, 0))
15*e1fe3e4aSElliott Hughes    >>> pen.lineTo((100, 100))
16*e1fe3e4aSElliott Hughes    >>> pen.closePath()
17*e1fe3e4aSElliott Hughes    >>> pprint(rec.value)
18*e1fe3e4aSElliott Hughes    [('moveTo', ((0, 0),)),
19*e1fe3e4aSElliott Hughes     ('lineTo', ((100, 0),)),
20*e1fe3e4aSElliott Hughes     ('lineTo', ((100, 100),)),
21*e1fe3e4aSElliott Hughes     ('lineTo', ((0, 0),)),
22*e1fe3e4aSElliott Hughes     ('closePath', ())]
23*e1fe3e4aSElliott Hughes    >>> rec = RecordingPen()
24*e1fe3e4aSElliott Hughes    >>> pen = ExplicitClosingLinePen(rec)
25*e1fe3e4aSElliott Hughes    >>> pen.moveTo((0, 0))
26*e1fe3e4aSElliott Hughes    >>> pen.lineTo((100, 0))
27*e1fe3e4aSElliott Hughes    >>> pen.lineTo((100, 100))
28*e1fe3e4aSElliott Hughes    >>> pen.lineTo((0, 0))
29*e1fe3e4aSElliott Hughes    >>> pen.closePath()
30*e1fe3e4aSElliott Hughes    >>> pprint(rec.value)
31*e1fe3e4aSElliott Hughes    [('moveTo', ((0, 0),)),
32*e1fe3e4aSElliott Hughes     ('lineTo', ((100, 0),)),
33*e1fe3e4aSElliott Hughes     ('lineTo', ((100, 100),)),
34*e1fe3e4aSElliott Hughes     ('lineTo', ((0, 0),)),
35*e1fe3e4aSElliott Hughes     ('closePath', ())]
36*e1fe3e4aSElliott Hughes    >>> rec = RecordingPen()
37*e1fe3e4aSElliott Hughes    >>> pen = ExplicitClosingLinePen(rec)
38*e1fe3e4aSElliott Hughes    >>> pen.moveTo((0, 0))
39*e1fe3e4aSElliott Hughes    >>> pen.curveTo((100, 0), (0, 100), (100, 100))
40*e1fe3e4aSElliott Hughes    >>> pen.closePath()
41*e1fe3e4aSElliott Hughes    >>> pprint(rec.value)
42*e1fe3e4aSElliott Hughes    [('moveTo', ((0, 0),)),
43*e1fe3e4aSElliott Hughes     ('curveTo', ((100, 0), (0, 100), (100, 100))),
44*e1fe3e4aSElliott Hughes     ('lineTo', ((0, 0),)),
45*e1fe3e4aSElliott Hughes     ('closePath', ())]
46*e1fe3e4aSElliott Hughes    >>> rec = RecordingPen()
47*e1fe3e4aSElliott Hughes    >>> pen = ExplicitClosingLinePen(rec)
48*e1fe3e4aSElliott Hughes    >>> pen.moveTo((0, 0))
49*e1fe3e4aSElliott Hughes    >>> pen.curveTo((100, 0), (0, 100), (100, 100))
50*e1fe3e4aSElliott Hughes    >>> pen.lineTo((0, 0))
51*e1fe3e4aSElliott Hughes    >>> pen.closePath()
52*e1fe3e4aSElliott Hughes    >>> pprint(rec.value)
53*e1fe3e4aSElliott Hughes    [('moveTo', ((0, 0),)),
54*e1fe3e4aSElliott Hughes     ('curveTo', ((100, 0), (0, 100), (100, 100))),
55*e1fe3e4aSElliott Hughes     ('lineTo', ((0, 0),)),
56*e1fe3e4aSElliott Hughes     ('closePath', ())]
57*e1fe3e4aSElliott Hughes    >>> rec = RecordingPen()
58*e1fe3e4aSElliott Hughes    >>> pen = ExplicitClosingLinePen(rec)
59*e1fe3e4aSElliott Hughes    >>> pen.moveTo((0, 0))
60*e1fe3e4aSElliott Hughes    >>> pen.curveTo((100, 0), (0, 100), (0, 0))
61*e1fe3e4aSElliott Hughes    >>> pen.closePath()
62*e1fe3e4aSElliott Hughes    >>> pprint(rec.value)
63*e1fe3e4aSElliott Hughes    [('moveTo', ((0, 0),)),
64*e1fe3e4aSElliott Hughes     ('curveTo', ((100, 0), (0, 100), (0, 0))),
65*e1fe3e4aSElliott Hughes     ('closePath', ())]
66*e1fe3e4aSElliott Hughes    >>> rec = RecordingPen()
67*e1fe3e4aSElliott Hughes    >>> pen = ExplicitClosingLinePen(rec)
68*e1fe3e4aSElliott Hughes    >>> pen.moveTo((0, 0))
69*e1fe3e4aSElliott Hughes    >>> pen.closePath()
70*e1fe3e4aSElliott Hughes    >>> pprint(rec.value)
71*e1fe3e4aSElliott Hughes    [('moveTo', ((0, 0),)), ('closePath', ())]
72*e1fe3e4aSElliott Hughes    >>> rec = RecordingPen()
73*e1fe3e4aSElliott Hughes    >>> pen = ExplicitClosingLinePen(rec)
74*e1fe3e4aSElliott Hughes    >>> pen.closePath()
75*e1fe3e4aSElliott Hughes    >>> pprint(rec.value)
76*e1fe3e4aSElliott Hughes    [('closePath', ())]
77*e1fe3e4aSElliott Hughes    >>> rec = RecordingPen()
78*e1fe3e4aSElliott Hughes    >>> pen = ExplicitClosingLinePen(rec)
79*e1fe3e4aSElliott Hughes    >>> pen.moveTo((0, 0))
80*e1fe3e4aSElliott Hughes    >>> pen.lineTo((100, 0))
81*e1fe3e4aSElliott Hughes    >>> pen.lineTo((100, 100))
82*e1fe3e4aSElliott Hughes    >>> pen.endPath()
83*e1fe3e4aSElliott Hughes    >>> pprint(rec.value)
84*e1fe3e4aSElliott Hughes    [('moveTo', ((0, 0),)),
85*e1fe3e4aSElliott Hughes     ('lineTo', ((100, 0),)),
86*e1fe3e4aSElliott Hughes     ('lineTo', ((100, 100),)),
87*e1fe3e4aSElliott Hughes     ('endPath', ())]
88*e1fe3e4aSElliott Hughes    """
89*e1fe3e4aSElliott Hughes
90*e1fe3e4aSElliott Hughes    def filterContour(self, contour):
91*e1fe3e4aSElliott Hughes        if (
92*e1fe3e4aSElliott Hughes            not contour
93*e1fe3e4aSElliott Hughes            or contour[0][0] != "moveTo"
94*e1fe3e4aSElliott Hughes            or contour[-1][0] != "closePath"
95*e1fe3e4aSElliott Hughes            or len(contour) < 3
96*e1fe3e4aSElliott Hughes        ):
97*e1fe3e4aSElliott Hughes            return
98*e1fe3e4aSElliott Hughes        movePt = contour[0][1][0]
99*e1fe3e4aSElliott Hughes        lastSeg = contour[-2][1]
100*e1fe3e4aSElliott Hughes        if lastSeg and movePt != lastSeg[-1]:
101*e1fe3e4aSElliott Hughes            contour[-1:] = [("lineTo", (movePt,)), ("closePath", ())]
102