def draw(layer, instance, pen): pen = PointToSegmentPen(pen) for path in layer.paths: nodes = list(path.nodes) pen.beginPath() if nodes: if not path.closed: node = nodes.pop(0) assert node.type == "line", "Open path starts with off-curve points" pen.addPoint(tuple(node.position), segmentType="move") else: # In Glyphs.app, the starting node of a closed contour is always # stored at the end of the nodes list. nodes.insert(0, nodes.pop()) for node in nodes: node_type = node.type if node_type not in ["line", "curve", "qcurve"]: node_type = None pen.addPoint(tuple(node.position), segmentType=node_type, smooth=node.smooth) pen.endPath(); for component in layer.components: componentLayer = getLayer(component.component, instance) transform = component.transform.value componentPen = pen.pen if transform != DEFAULT_TRANSFORM: componentPen = TransformPen(pen.pen, transform) xx, xy, yx, yy = transform[:4] if xx * yy - xy * yx < 0: componentPen = ReverseContourPen(componentPen) draw(componentLayer, instance, componentPen) return pen.pen
def test_open(self): pen = _TestSegmentPen() ppen = PointToSegmentPen(pen) ppen.beginPath() ppen.addPoint((10, 10), "move") ppen.addPoint((10, 20), "line") ppen.endPath() self.assertEqual("10 10 moveto 10 20 lineto endpath", repr(pen))
def test_quad_onlyOffCurvePoints(self): pen = _TestSegmentPen() ppen = PointToSegmentPen(pen) ppen.beginPath() ppen.addPoint((10, 10)) ppen.addPoint((10, 40)) ppen.addPoint((40, 40)) ppen.endPath() self.assertEqual("10 10 10 40 40 40 None qcurveto closepath", repr(pen))
def test_quad(self): pen = _TestSegmentPen() ppen = PointToSegmentPen(pen) ppen.beginPath(identifier='foo') ppen.addPoint((10, 10), "line") ppen.addPoint((10, 40)) ppen.addPoint((40, 40)) ppen.addPoint((10, 40), "qcurve") ppen.endPath() self.assertEqual("10 10 moveto 10 40 40 40 10 40 qcurveto closepath", repr(pen))
def test_cubic(self): pen = _TestSegmentPen() ppen = PointToSegmentPen(pen) ppen.beginPath() ppen.addPoint((10, 10), "line") ppen.addPoint((10, 20)) ppen.addPoint((20, 20)) ppen.addPoint((20, 40), "curve") ppen.endPath() self.assertEqual("10 10 moveto 10 20 20 20 20 40 curveto closepath", repr(pen))
def test_roundTrip1(self): tpen = _TestPointPen() ppen = PointToSegmentPen(SegmentToPointPen(tpen)) ppen.beginPath() ppen.addPoint((10, 10), "line") ppen.addPoint((10, 20)) ppen.addPoint((20, 20)) ppen.addPoint((20, 40), "curve") ppen.endPath() self.assertEqual("beginPath() addPoint((10, 10), segmentType='line') addPoint((10, 20)) " "addPoint((20, 20)) addPoint((20, 40), segmentType='curve') endPath()", repr(tpen))
def test_closed_outputImpliedClosingLine(self): tpen = _TestSegmentPen() ppen = PointToSegmentPen(tpen, outputImpliedClosingLine=True) ppen.beginPath() ppen.addPoint((10, 10), "line") ppen.addPoint((10, 20), "line") ppen.addPoint((20, 20), "line") ppen.endPath() self.assertEqual( "10 10 moveto " "10 20 lineto " "20 20 lineto " "10 10 lineto " # explicit closing line "closepath", repr(tpen))
def test_roundTrip2(self): tpen = _TestPointPen() ppen = PointToSegmentPen(SegmentToPointPen(tpen)) ppen.beginPath() ppen.addPoint((0, 651), segmentType="line") ppen.addPoint((0, 101), segmentType="line") ppen.addPoint((0, 101), segmentType="line") ppen.addPoint((0, 651), segmentType="line") ppen.endPath() self.assertEqual( "beginPath() " "addPoint((0, 651), segmentType='line') " "addPoint((0, 101), segmentType='line') " "addPoint((0, 101), segmentType='line') " "addPoint((0, 651), segmentType='line') " "endPath()", repr(tpen))
def draw(self, pen): ppen = PointToSegmentPen(pen) startIndex = 0 points = self.getPoints() for endIndex in self.contours: lastTag = self.tags[endIndex] endIndex += 1 contourTags = self.tags[startIndex:endIndex] contourPoints = points[startIndex:endIndex] ppen.beginPath() for tag, (x, y) in zip(contourTags, contourPoints): if tag == FT_CURVE_TAG_ON: segmentType = segmentTypes[lastTag] else: segmentType = None ppen.addPoint((x, y), segmentType=segmentType) lastTag = tag ppen.endPath() startIndex = endIndex
def test_closed_line_overlapping_start_end_points(self): # Test case from https://github.com/googlefonts/fontmake/issues/572. tpen = _TestSegmentPen() ppen = PointToSegmentPen(tpen, outputImpliedClosingLine=False) # The last oncurve point on this closed contour is a "line" segment and has # same coordinates as the starting point. ppen.beginPath() ppen.addPoint((0, 651), segmentType="line") ppen.addPoint((0, 101), segmentType="line") ppen.addPoint((0, 101), segmentType="line") ppen.addPoint((0, 651), segmentType="line") ppen.endPath() # Check that we always output an explicit 'lineTo' segment at the end, # regardless of the value of 'outputImpliedClosingLine', to disambiguate # the duplicate point from the implied closing line. self.assertEqual( "0 651 moveto " "0 101 lineto " "0 101 lineto " "0 651 lineto " "0 651 lineto " "closepath", repr(tpen))