xref: /aosp_15_r20/external/fonttools/Lib/fontTools/pens/ttGlyphPen.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1*e1fe3e4aSElliott Hughesfrom array import array
2*e1fe3e4aSElliott Hughesfrom typing import Any, Callable, Dict, Optional, Tuple
3*e1fe3e4aSElliott Hughesfrom fontTools.misc.fixedTools import MAX_F2DOT14, floatToFixedToFloat
4*e1fe3e4aSElliott Hughesfrom fontTools.misc.loggingTools import LogMixin
5*e1fe3e4aSElliott Hughesfrom fontTools.pens.pointPen import AbstractPointPen
6*e1fe3e4aSElliott Hughesfrom fontTools.misc.roundTools import otRound
7*e1fe3e4aSElliott Hughesfrom fontTools.pens.basePen import LoggingPen, PenError
8*e1fe3e4aSElliott Hughesfrom fontTools.pens.transformPen import TransformPen, TransformPointPen
9*e1fe3e4aSElliott Hughesfrom fontTools.ttLib.tables import ttProgram
10*e1fe3e4aSElliott Hughesfrom fontTools.ttLib.tables._g_l_y_f import flagOnCurve, flagCubic
11*e1fe3e4aSElliott Hughesfrom fontTools.ttLib.tables._g_l_y_f import Glyph
12*e1fe3e4aSElliott Hughesfrom fontTools.ttLib.tables._g_l_y_f import GlyphComponent
13*e1fe3e4aSElliott Hughesfrom fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
14*e1fe3e4aSElliott Hughesfrom fontTools.ttLib.tables._g_l_y_f import dropImpliedOnCurvePoints
15*e1fe3e4aSElliott Hughesimport math
16*e1fe3e4aSElliott Hughes
17*e1fe3e4aSElliott Hughes
18*e1fe3e4aSElliott Hughes__all__ = ["TTGlyphPen", "TTGlyphPointPen"]
19*e1fe3e4aSElliott Hughes
20*e1fe3e4aSElliott Hughes
21*e1fe3e4aSElliott Hughesclass _TTGlyphBasePen:
22*e1fe3e4aSElliott Hughes    def __init__(
23*e1fe3e4aSElliott Hughes        self,
24*e1fe3e4aSElliott Hughes        glyphSet: Optional[Dict[str, Any]],
25*e1fe3e4aSElliott Hughes        handleOverflowingTransforms: bool = True,
26*e1fe3e4aSElliott Hughes    ) -> None:
27*e1fe3e4aSElliott Hughes        """
28*e1fe3e4aSElliott Hughes        Construct a new pen.
29*e1fe3e4aSElliott Hughes
30*e1fe3e4aSElliott Hughes        Args:
31*e1fe3e4aSElliott Hughes            glyphSet (Dict[str, Any]): A glyphset object, used to resolve components.
32*e1fe3e4aSElliott Hughes            handleOverflowingTransforms (bool): See below.
33*e1fe3e4aSElliott Hughes
34*e1fe3e4aSElliott Hughes        If ``handleOverflowingTransforms`` is True, the components' transform values
35*e1fe3e4aSElliott Hughes        are checked that they don't overflow the limits of a F2Dot14 number:
36*e1fe3e4aSElliott Hughes        -2.0 <= v < +2.0. If any transform value exceeds these, the composite
37*e1fe3e4aSElliott Hughes        glyph is decomposed.
38*e1fe3e4aSElliott Hughes
39*e1fe3e4aSElliott Hughes        An exception to this rule is done for values that are very close to +2.0
40*e1fe3e4aSElliott Hughes        (both for consistency with the -2.0 case, and for the relative frequency
41*e1fe3e4aSElliott Hughes        these occur in real fonts). When almost +2.0 values occur (and all other
42*e1fe3e4aSElliott Hughes        values are within the range -2.0 <= x <= +2.0), they are clamped to the
43*e1fe3e4aSElliott Hughes        maximum positive value that can still be encoded as an F2Dot14: i.e.
44*e1fe3e4aSElliott Hughes        1.99993896484375.
45*e1fe3e4aSElliott Hughes
46*e1fe3e4aSElliott Hughes        If False, no check is done and all components are translated unmodified
47*e1fe3e4aSElliott Hughes        into the glyf table, followed by an inevitable ``struct.error`` once an
48*e1fe3e4aSElliott Hughes        attempt is made to compile them.
49*e1fe3e4aSElliott Hughes
50*e1fe3e4aSElliott Hughes        If both contours and components are present in a glyph, the components
51*e1fe3e4aSElliott Hughes        are decomposed.
52*e1fe3e4aSElliott Hughes        """
53*e1fe3e4aSElliott Hughes        self.glyphSet = glyphSet
54*e1fe3e4aSElliott Hughes        self.handleOverflowingTransforms = handleOverflowingTransforms
55*e1fe3e4aSElliott Hughes        self.init()
56*e1fe3e4aSElliott Hughes
57*e1fe3e4aSElliott Hughes    def _decompose(
58*e1fe3e4aSElliott Hughes        self,
59*e1fe3e4aSElliott Hughes        glyphName: str,
60*e1fe3e4aSElliott Hughes        transformation: Tuple[float, float, float, float, float, float],
61*e1fe3e4aSElliott Hughes    ):
62*e1fe3e4aSElliott Hughes        tpen = self.transformPen(self, transformation)
63*e1fe3e4aSElliott Hughes        getattr(self.glyphSet[glyphName], self.drawMethod)(tpen)
64*e1fe3e4aSElliott Hughes
65*e1fe3e4aSElliott Hughes    def _isClosed(self):
66*e1fe3e4aSElliott Hughes        """
67*e1fe3e4aSElliott Hughes        Check if the current path is closed.
68*e1fe3e4aSElliott Hughes        """
69*e1fe3e4aSElliott Hughes        raise NotImplementedError
70*e1fe3e4aSElliott Hughes
71*e1fe3e4aSElliott Hughes    def init(self) -> None:
72*e1fe3e4aSElliott Hughes        self.points = []
73*e1fe3e4aSElliott Hughes        self.endPts = []
74*e1fe3e4aSElliott Hughes        self.types = []
75*e1fe3e4aSElliott Hughes        self.components = []
76*e1fe3e4aSElliott Hughes
77*e1fe3e4aSElliott Hughes    def addComponent(
78*e1fe3e4aSElliott Hughes        self,
79*e1fe3e4aSElliott Hughes        baseGlyphName: str,
80*e1fe3e4aSElliott Hughes        transformation: Tuple[float, float, float, float, float, float],
81*e1fe3e4aSElliott Hughes        identifier: Optional[str] = None,
82*e1fe3e4aSElliott Hughes        **kwargs: Any,
83*e1fe3e4aSElliott Hughes    ) -> None:
84*e1fe3e4aSElliott Hughes        """
85*e1fe3e4aSElliott Hughes        Add a sub glyph.
86*e1fe3e4aSElliott Hughes        """
87*e1fe3e4aSElliott Hughes        self.components.append((baseGlyphName, transformation))
88*e1fe3e4aSElliott Hughes
89*e1fe3e4aSElliott Hughes    def _buildComponents(self, componentFlags):
90*e1fe3e4aSElliott Hughes        if self.handleOverflowingTransforms:
91*e1fe3e4aSElliott Hughes            # we can't encode transform values > 2 or < -2 in F2Dot14,
92*e1fe3e4aSElliott Hughes            # so we must decompose the glyph if any transform exceeds these
93*e1fe3e4aSElliott Hughes            overflowing = any(
94*e1fe3e4aSElliott Hughes                s > 2 or s < -2
95*e1fe3e4aSElliott Hughes                for (glyphName, transformation) in self.components
96*e1fe3e4aSElliott Hughes                for s in transformation[:4]
97*e1fe3e4aSElliott Hughes            )
98*e1fe3e4aSElliott Hughes        components = []
99*e1fe3e4aSElliott Hughes        for glyphName, transformation in self.components:
100*e1fe3e4aSElliott Hughes            if glyphName not in self.glyphSet:
101*e1fe3e4aSElliott Hughes                self.log.warning(f"skipped non-existing component '{glyphName}'")
102*e1fe3e4aSElliott Hughes                continue
103*e1fe3e4aSElliott Hughes            if self.points or (self.handleOverflowingTransforms and overflowing):
104*e1fe3e4aSElliott Hughes                # can't have both coordinates and components, so decompose
105*e1fe3e4aSElliott Hughes                self._decompose(glyphName, transformation)
106*e1fe3e4aSElliott Hughes                continue
107*e1fe3e4aSElliott Hughes
108*e1fe3e4aSElliott Hughes            component = GlyphComponent()
109*e1fe3e4aSElliott Hughes            component.glyphName = glyphName
110*e1fe3e4aSElliott Hughes            component.x, component.y = (otRound(v) for v in transformation[4:])
111*e1fe3e4aSElliott Hughes            # quantize floats to F2Dot14 so we get same values as when decompiled
112*e1fe3e4aSElliott Hughes            # from a binary glyf table
113*e1fe3e4aSElliott Hughes            transformation = tuple(
114*e1fe3e4aSElliott Hughes                floatToFixedToFloat(v, 14) for v in transformation[:4]
115*e1fe3e4aSElliott Hughes            )
116*e1fe3e4aSElliott Hughes            if transformation != (1, 0, 0, 1):
117*e1fe3e4aSElliott Hughes                if self.handleOverflowingTransforms and any(
118*e1fe3e4aSElliott Hughes                    MAX_F2DOT14 < s <= 2 for s in transformation
119*e1fe3e4aSElliott Hughes                ):
120*e1fe3e4aSElliott Hughes                    # clamp values ~= +2.0 so we can keep the component
121*e1fe3e4aSElliott Hughes                    transformation = tuple(
122*e1fe3e4aSElliott Hughes                        MAX_F2DOT14 if MAX_F2DOT14 < s <= 2 else s
123*e1fe3e4aSElliott Hughes                        for s in transformation
124*e1fe3e4aSElliott Hughes                    )
125*e1fe3e4aSElliott Hughes                component.transform = (transformation[:2], transformation[2:])
126*e1fe3e4aSElliott Hughes            component.flags = componentFlags
127*e1fe3e4aSElliott Hughes            components.append(component)
128*e1fe3e4aSElliott Hughes        return components
129*e1fe3e4aSElliott Hughes
130*e1fe3e4aSElliott Hughes    def glyph(
131*e1fe3e4aSElliott Hughes        self,
132*e1fe3e4aSElliott Hughes        componentFlags: int = 0x04,
133*e1fe3e4aSElliott Hughes        dropImpliedOnCurves: bool = False,
134*e1fe3e4aSElliott Hughes        *,
135*e1fe3e4aSElliott Hughes        round: Callable[[float], int] = otRound,
136*e1fe3e4aSElliott Hughes    ) -> Glyph:
137*e1fe3e4aSElliott Hughes        """
138*e1fe3e4aSElliott Hughes        Returns a :py:class:`~._g_l_y_f.Glyph` object representing the glyph.
139*e1fe3e4aSElliott Hughes
140*e1fe3e4aSElliott Hughes        Args:
141*e1fe3e4aSElliott Hughes            componentFlags: Flags to use for component glyphs. (default: 0x04)
142*e1fe3e4aSElliott Hughes
143*e1fe3e4aSElliott Hughes            dropImpliedOnCurves: Whether to remove implied-oncurve points. (default: False)
144*e1fe3e4aSElliott Hughes        """
145*e1fe3e4aSElliott Hughes        if not self._isClosed():
146*e1fe3e4aSElliott Hughes            raise PenError("Didn't close last contour.")
147*e1fe3e4aSElliott Hughes        components = self._buildComponents(componentFlags)
148*e1fe3e4aSElliott Hughes
149*e1fe3e4aSElliott Hughes        glyph = Glyph()
150*e1fe3e4aSElliott Hughes        glyph.coordinates = GlyphCoordinates(self.points)
151*e1fe3e4aSElliott Hughes        glyph.endPtsOfContours = self.endPts
152*e1fe3e4aSElliott Hughes        glyph.flags = array("B", self.types)
153*e1fe3e4aSElliott Hughes        self.init()
154*e1fe3e4aSElliott Hughes
155*e1fe3e4aSElliott Hughes        if components:
156*e1fe3e4aSElliott Hughes            # If both components and contours were present, they have by now
157*e1fe3e4aSElliott Hughes            # been decomposed by _buildComponents.
158*e1fe3e4aSElliott Hughes            glyph.components = components
159*e1fe3e4aSElliott Hughes            glyph.numberOfContours = -1
160*e1fe3e4aSElliott Hughes        else:
161*e1fe3e4aSElliott Hughes            glyph.numberOfContours = len(glyph.endPtsOfContours)
162*e1fe3e4aSElliott Hughes            glyph.program = ttProgram.Program()
163*e1fe3e4aSElliott Hughes            glyph.program.fromBytecode(b"")
164*e1fe3e4aSElliott Hughes            if dropImpliedOnCurves:
165*e1fe3e4aSElliott Hughes                dropImpliedOnCurvePoints(glyph)
166*e1fe3e4aSElliott Hughes            glyph.coordinates.toInt(round=round)
167*e1fe3e4aSElliott Hughes
168*e1fe3e4aSElliott Hughes        return glyph
169*e1fe3e4aSElliott Hughes
170*e1fe3e4aSElliott Hughes
171*e1fe3e4aSElliott Hughesclass TTGlyphPen(_TTGlyphBasePen, LoggingPen):
172*e1fe3e4aSElliott Hughes    """
173*e1fe3e4aSElliott Hughes    Pen used for drawing to a TrueType glyph.
174*e1fe3e4aSElliott Hughes
175*e1fe3e4aSElliott Hughes    This pen can be used to construct or modify glyphs in a TrueType format
176*e1fe3e4aSElliott Hughes    font. After using the pen to draw, use the ``.glyph()`` method to retrieve
177*e1fe3e4aSElliott Hughes    a :py:class:`~._g_l_y_f.Glyph` object representing the glyph.
178*e1fe3e4aSElliott Hughes    """
179*e1fe3e4aSElliott Hughes
180*e1fe3e4aSElliott Hughes    drawMethod = "draw"
181*e1fe3e4aSElliott Hughes    transformPen = TransformPen
182*e1fe3e4aSElliott Hughes
183*e1fe3e4aSElliott Hughes    def __init__(
184*e1fe3e4aSElliott Hughes        self,
185*e1fe3e4aSElliott Hughes        glyphSet: Optional[Dict[str, Any]] = None,
186*e1fe3e4aSElliott Hughes        handleOverflowingTransforms: bool = True,
187*e1fe3e4aSElliott Hughes        outputImpliedClosingLine: bool = False,
188*e1fe3e4aSElliott Hughes    ) -> None:
189*e1fe3e4aSElliott Hughes        super().__init__(glyphSet, handleOverflowingTransforms)
190*e1fe3e4aSElliott Hughes        self.outputImpliedClosingLine = outputImpliedClosingLine
191*e1fe3e4aSElliott Hughes
192*e1fe3e4aSElliott Hughes    def _addPoint(self, pt: Tuple[float, float], tp: int) -> None:
193*e1fe3e4aSElliott Hughes        self.points.append(pt)
194*e1fe3e4aSElliott Hughes        self.types.append(tp)
195*e1fe3e4aSElliott Hughes
196*e1fe3e4aSElliott Hughes    def _popPoint(self) -> None:
197*e1fe3e4aSElliott Hughes        self.points.pop()
198*e1fe3e4aSElliott Hughes        self.types.pop()
199*e1fe3e4aSElliott Hughes
200*e1fe3e4aSElliott Hughes    def _isClosed(self) -> bool:
201*e1fe3e4aSElliott Hughes        return (not self.points) or (
202*e1fe3e4aSElliott Hughes            self.endPts and self.endPts[-1] == len(self.points) - 1
203*e1fe3e4aSElliott Hughes        )
204*e1fe3e4aSElliott Hughes
205*e1fe3e4aSElliott Hughes    def lineTo(self, pt: Tuple[float, float]) -> None:
206*e1fe3e4aSElliott Hughes        self._addPoint(pt, flagOnCurve)
207*e1fe3e4aSElliott Hughes
208*e1fe3e4aSElliott Hughes    def moveTo(self, pt: Tuple[float, float]) -> None:
209*e1fe3e4aSElliott Hughes        if not self._isClosed():
210*e1fe3e4aSElliott Hughes            raise PenError('"move"-type point must begin a new contour.')
211*e1fe3e4aSElliott Hughes        self._addPoint(pt, flagOnCurve)
212*e1fe3e4aSElliott Hughes
213*e1fe3e4aSElliott Hughes    def curveTo(self, *points) -> None:
214*e1fe3e4aSElliott Hughes        assert len(points) % 2 == 1
215*e1fe3e4aSElliott Hughes        for pt in points[:-1]:
216*e1fe3e4aSElliott Hughes            self._addPoint(pt, flagCubic)
217*e1fe3e4aSElliott Hughes
218*e1fe3e4aSElliott Hughes        # last point is None if there are no on-curve points
219*e1fe3e4aSElliott Hughes        if points[-1] is not None:
220*e1fe3e4aSElliott Hughes            self._addPoint(points[-1], 1)
221*e1fe3e4aSElliott Hughes
222*e1fe3e4aSElliott Hughes    def qCurveTo(self, *points) -> None:
223*e1fe3e4aSElliott Hughes        assert len(points) >= 1
224*e1fe3e4aSElliott Hughes        for pt in points[:-1]:
225*e1fe3e4aSElliott Hughes            self._addPoint(pt, 0)
226*e1fe3e4aSElliott Hughes
227*e1fe3e4aSElliott Hughes        # last point is None if there are no on-curve points
228*e1fe3e4aSElliott Hughes        if points[-1] is not None:
229*e1fe3e4aSElliott Hughes            self._addPoint(points[-1], 1)
230*e1fe3e4aSElliott Hughes
231*e1fe3e4aSElliott Hughes    def closePath(self) -> None:
232*e1fe3e4aSElliott Hughes        endPt = len(self.points) - 1
233*e1fe3e4aSElliott Hughes
234*e1fe3e4aSElliott Hughes        # ignore anchors (one-point paths)
235*e1fe3e4aSElliott Hughes        if endPt == 0 or (self.endPts and endPt == self.endPts[-1] + 1):
236*e1fe3e4aSElliott Hughes            self._popPoint()
237*e1fe3e4aSElliott Hughes            return
238*e1fe3e4aSElliott Hughes
239*e1fe3e4aSElliott Hughes        if not self.outputImpliedClosingLine:
240*e1fe3e4aSElliott Hughes            # if first and last point on this path are the same, remove last
241*e1fe3e4aSElliott Hughes            startPt = 0
242*e1fe3e4aSElliott Hughes            if self.endPts:
243*e1fe3e4aSElliott Hughes                startPt = self.endPts[-1] + 1
244*e1fe3e4aSElliott Hughes            if self.points[startPt] == self.points[endPt]:
245*e1fe3e4aSElliott Hughes                self._popPoint()
246*e1fe3e4aSElliott Hughes                endPt -= 1
247*e1fe3e4aSElliott Hughes
248*e1fe3e4aSElliott Hughes        self.endPts.append(endPt)
249*e1fe3e4aSElliott Hughes
250*e1fe3e4aSElliott Hughes    def endPath(self) -> None:
251*e1fe3e4aSElliott Hughes        # TrueType contours are always "closed"
252*e1fe3e4aSElliott Hughes        self.closePath()
253*e1fe3e4aSElliott Hughes
254*e1fe3e4aSElliott Hughes
255*e1fe3e4aSElliott Hughesclass TTGlyphPointPen(_TTGlyphBasePen, LogMixin, AbstractPointPen):
256*e1fe3e4aSElliott Hughes    """
257*e1fe3e4aSElliott Hughes    Point pen used for drawing to a TrueType glyph.
258*e1fe3e4aSElliott Hughes
259*e1fe3e4aSElliott Hughes    This pen can be used to construct or modify glyphs in a TrueType format
260*e1fe3e4aSElliott Hughes    font. After using the pen to draw, use the ``.glyph()`` method to retrieve
261*e1fe3e4aSElliott Hughes    a :py:class:`~._g_l_y_f.Glyph` object representing the glyph.
262*e1fe3e4aSElliott Hughes    """
263*e1fe3e4aSElliott Hughes
264*e1fe3e4aSElliott Hughes    drawMethod = "drawPoints"
265*e1fe3e4aSElliott Hughes    transformPen = TransformPointPen
266*e1fe3e4aSElliott Hughes
267*e1fe3e4aSElliott Hughes    def init(self) -> None:
268*e1fe3e4aSElliott Hughes        super().init()
269*e1fe3e4aSElliott Hughes        self._currentContourStartIndex = None
270*e1fe3e4aSElliott Hughes
271*e1fe3e4aSElliott Hughes    def _isClosed(self) -> bool:
272*e1fe3e4aSElliott Hughes        return self._currentContourStartIndex is None
273*e1fe3e4aSElliott Hughes
274*e1fe3e4aSElliott Hughes    def beginPath(self, identifier: Optional[str] = None, **kwargs: Any) -> None:
275*e1fe3e4aSElliott Hughes        """
276*e1fe3e4aSElliott Hughes        Start a new sub path.
277*e1fe3e4aSElliott Hughes        """
278*e1fe3e4aSElliott Hughes        if not self._isClosed():
279*e1fe3e4aSElliott Hughes            raise PenError("Didn't close previous contour.")
280*e1fe3e4aSElliott Hughes        self._currentContourStartIndex = len(self.points)
281*e1fe3e4aSElliott Hughes
282*e1fe3e4aSElliott Hughes    def endPath(self) -> None:
283*e1fe3e4aSElliott Hughes        """
284*e1fe3e4aSElliott Hughes        End the current sub path.
285*e1fe3e4aSElliott Hughes        """
286*e1fe3e4aSElliott Hughes        # TrueType contours are always "closed"
287*e1fe3e4aSElliott Hughes        if self._isClosed():
288*e1fe3e4aSElliott Hughes            raise PenError("Contour is already closed.")
289*e1fe3e4aSElliott Hughes        if self._currentContourStartIndex == len(self.points):
290*e1fe3e4aSElliott Hughes            # ignore empty contours
291*e1fe3e4aSElliott Hughes            self._currentContourStartIndex = None
292*e1fe3e4aSElliott Hughes            return
293*e1fe3e4aSElliott Hughes
294*e1fe3e4aSElliott Hughes        contourStart = self.endPts[-1] + 1 if self.endPts else 0
295*e1fe3e4aSElliott Hughes        self.endPts.append(len(self.points) - 1)
296*e1fe3e4aSElliott Hughes        self._currentContourStartIndex = None
297*e1fe3e4aSElliott Hughes
298*e1fe3e4aSElliott Hughes        # Resolve types for any cubic segments
299*e1fe3e4aSElliott Hughes        flags = self.types
300*e1fe3e4aSElliott Hughes        for i in range(contourStart, len(flags)):
301*e1fe3e4aSElliott Hughes            if flags[i] == "curve":
302*e1fe3e4aSElliott Hughes                j = i - 1
303*e1fe3e4aSElliott Hughes                if j < contourStart:
304*e1fe3e4aSElliott Hughes                    j = len(flags) - 1
305*e1fe3e4aSElliott Hughes                while flags[j] == 0:
306*e1fe3e4aSElliott Hughes                    flags[j] = flagCubic
307*e1fe3e4aSElliott Hughes                    j -= 1
308*e1fe3e4aSElliott Hughes                flags[i] = flagOnCurve
309*e1fe3e4aSElliott Hughes
310*e1fe3e4aSElliott Hughes    def addPoint(
311*e1fe3e4aSElliott Hughes        self,
312*e1fe3e4aSElliott Hughes        pt: Tuple[float, float],
313*e1fe3e4aSElliott Hughes        segmentType: Optional[str] = None,
314*e1fe3e4aSElliott Hughes        smooth: bool = False,
315*e1fe3e4aSElliott Hughes        name: Optional[str] = None,
316*e1fe3e4aSElliott Hughes        identifier: Optional[str] = None,
317*e1fe3e4aSElliott Hughes        **kwargs: Any,
318*e1fe3e4aSElliott Hughes    ) -> None:
319*e1fe3e4aSElliott Hughes        """
320*e1fe3e4aSElliott Hughes        Add a point to the current sub path.
321*e1fe3e4aSElliott Hughes        """
322*e1fe3e4aSElliott Hughes        if self._isClosed():
323*e1fe3e4aSElliott Hughes            raise PenError("Can't add a point to a closed contour.")
324*e1fe3e4aSElliott Hughes        if segmentType is None:
325*e1fe3e4aSElliott Hughes            self.types.append(0)
326*e1fe3e4aSElliott Hughes        elif segmentType in ("line", "move"):
327*e1fe3e4aSElliott Hughes            self.types.append(flagOnCurve)
328*e1fe3e4aSElliott Hughes        elif segmentType == "qcurve":
329*e1fe3e4aSElliott Hughes            self.types.append(flagOnCurve)
330*e1fe3e4aSElliott Hughes        elif segmentType == "curve":
331*e1fe3e4aSElliott Hughes            self.types.append("curve")
332*e1fe3e4aSElliott Hughes        else:
333*e1fe3e4aSElliott Hughes            raise AssertionError(segmentType)
334*e1fe3e4aSElliott Hughes
335*e1fe3e4aSElliott Hughes        self.points.append(pt)
336