def drawShapeWithRectInGlyph(self, shape, rect, glyph): # draw the shape into the glyph # tell the glyph something is going to happen (undo is going to be prepared) glyph.prepareUndo("Drawing Shapes") # get the pen to draw with pen = glyph.getPointPen() if glyph.preferredSegmentType == "qcurve" and not self.shouldReverse: pen = ReverseContourPointPen(pen) elif self.shouldReverse: pen = ReverseContourPointPen(pen) x, y, w, h = rect # draw a rectangle in the glyph using the pen if shape == "rect": pen.beginPath() pen.addPoint(_roundPoint(x, y), "line") pen.addPoint(_roundPoint(x + w, y), "line") pen.addPoint(_roundPoint(x + w, y + h), "line") pen.addPoint(_roundPoint(x, y + h), "line") pen.endPath() # draw an oval in the glyph using the pen elif shape == "oval": hw = w/2. hh = h/2. r = .55 segmentType = glyph.preferredSegmentType if glyph.preferredSegmentType == "qcurve": r = .42 pen.beginPath() pen.addPoint(_roundPoint(x + hw, y), segmentType, True) pen.addPoint(_roundPoint(x + hw + hw*r, y)) pen.addPoint(_roundPoint(x + w, y + hh - hh*r)) pen.addPoint(_roundPoint(x + w, y + hh), segmentType, True) pen.addPoint(_roundPoint(x + w, y + hh + hh*r)) pen.addPoint(_roundPoint(x + hw + hw*r, y + h)) pen.addPoint(_roundPoint(x + hw, y + h), segmentType, True) pen.addPoint(_roundPoint(x + hw - hw*r, y + h)) pen.addPoint(_roundPoint(x, y + hh + hh*r)) pen.addPoint(_roundPoint(x, y + hh), segmentType, True) pen.addPoint(_roundPoint(x, y + hh - hh*r)) pen.addPoint(_roundPoint(x + hw - hw*r, y)) pen.endPath() # tell the glyph you are done with your actions so it can handle the undo properly glyph.performUndo() glyph.changed()
def drawPoints(self, pointPen): if self.drawInner: reversePen = ReverseContourPointPen(pointPen) self.innerGlyph.drawPoints(CleanPointPen(reversePen)) if self.drawOuter: self.outerGlyph.drawPoints(CleanPointPen(pointPen)) if self.drawOriginal: if self.drawOuter: pointPen = ReverseContourPointPen(pointPen) self.originalGlyph.drawPoints(CleanPointPen(pointPen)) for glyphName, transform in self.components: pointPen.addComponent(glyphName, transform)
def reverse(self): """ Reverse the direction of the contour. It's important to note that the actual points stored in this object will be completely repalced by new points. This will post *Contour.WindingDirectionChanged*, *Contour.PointsChanged* and *Contour.Changed* notifications. """ from fontTools.pens.pointPen import ReverseContourPointPen oldDirection = self.clockwise # put the current points in another contour otherContour = self.__class__(glyph=None, pointClass=self.pointClass) # draw the points in this contour through # the reversing pen. reversePen = ReverseContourPointPen(otherContour) self.drawPoints(reversePen) # clear the points in this contour self._clear(postNotification=False) # set the points back into this contour self._points = otherContour._points # post a notification self.postNotification("Contour.WindingDirectionChanged", data=dict(oldValue=oldDirection, newValue=self.clockwise)) self.postNotification("Contour.PointsChanged") self.dirty = True
def reverseContours(glyph): glyphCopy = RGlyph() glyphCopy.width = glyph.width pointPen = glyphCopy.getPointPen() reversePen = ReverseContourPointPen(pointPen) glyph.drawPoints(reversePen) return glyphCopy
def __init__(self, other_point_pen, max_err, reverse_direction=False, stats=None): BasePointToSegmentPen.__init__(self) if reverse_direction: self.pen = ReverseContourPointPen(other_point_pen) else: self.pen = other_point_pen self.max_err = max_err self.stats = stats
def test_singlePoint(self): tpen = _TestPointPen() pen = ReverseContourPointPen(tpen) pen.beginPath() pen.addPoint((0, 0), segmentType="move") pen.endPath() self.assertEqual( "beginPath() " "addPoint((0, 0), segmentType='move') " "endPath()", repr(tpen))
def test_triangle(self): tpen = _TestPointPen() pen = ReverseContourPointPen(tpen) pen.beginPath() pen.addPoint((0, 0), segmentType="line") pen.addPoint((0, 100), segmentType="line") pen.addPoint((100, 100), segmentType="line") pen.endPath() self.assertEqual( "beginPath() " "addPoint((0, 0), segmentType='line') " "addPoint((100, 100), segmentType='line') " "addPoint((0, 100), segmentType='line') " "endPath()", repr(tpen))
def test_quadClosedOffCurveStart(self): tpen = _TestPointPen() pen = ReverseContourPointPen(tpen) pen.beginPath() pen.addPoint((100, 200)) pen.addPoint((200, 200), segmentType="qcurve") pen.addPoint((0, 0), segmentType="line") pen.addPoint((0, 100)) pen.endPath() self.assertEqual( "beginPath() " "addPoint((100, 200)) " "addPoint((0, 100)) " "addPoint((0, 0), segmentType='qcurve') " "addPoint((200, 200), segmentType='line') " "endPath()", repr(tpen))
def test_cubicOpen(self): tpen = _TestPointPen() pen = ReverseContourPointPen(tpen) pen.beginPath() pen.addPoint((0, 0), segmentType="move") pen.addPoint((0, 100)) pen.addPoint((100, 200)) pen.addPoint((200, 200), segmentType="curve") pen.endPath() self.assertEqual( "beginPath() " "addPoint((200, 200), segmentType='move') " "addPoint((100, 200)) " "addPoint((0, 100)) " "addPoint((0, 0), segmentType='curve') " "endPath()", repr(tpen))
def test_closed_line_overlapping_start_end_points(self): # Test case from https://github.com/googlefonts/fontmake/issues/572 tpen = _TestPointPen() pen = ReverseContourPointPen(tpen) pen.beginPath() pen.addPoint((0, 651), segmentType="line") pen.addPoint((0, 101), segmentType="line") pen.addPoint((0, 101), segmentType="line") pen.addPoint((0, 651), segmentType="line") pen.endPath() self.assertEqual( "beginPath() " "addPoint((0, 651), segmentType='line') " "addPoint((0, 651), segmentType='line') " "addPoint((0, 101), segmentType='line') " "addPoint((0, 101), segmentType='line') " "endPath()", repr(tpen))
def test_quadNoOnCurve(self): tpen = _TestPointPen() pen = ReverseContourPointPen(tpen) pen.beginPath(identifier='bar') pen.addPoint((0, 0)) pen.addPoint((0, 100), identifier='foo', arbitrary='foo') pen.addPoint((100, 200), arbitrary=123) pen.addPoint((200, 200)) pen.endPath() pen.addComponent("base", [1, 0, 0, 1, 0, 0], identifier='foo') self.assertEqual("beginPath(identifier='bar') " "addPoint((0, 0)) " "addPoint((200, 200)) " "addPoint((100, 200), arbitrary=123) " "addPoint((0, 100), identifier='foo', arbitrary='foo') " "endPath() " "addComponent('base', [1, 0, 0, 1, 0, 0], identifier='foo')", repr(tpen))
def _copyGlyph(glyph, glyphFactory=None, reverseContour=False): # copy everything except unused attributes: 'guidelines', 'note', 'image' if glyphFactory is None: glyphFactory = _getNewGlyphFactory(glyph) copy = glyphFactory(glyph.name) copy.width = glyph.width copy.height = glyph.height copy.unicodes = list(glyph.unicodes) copy.anchors = [dict(a) for a in glyph.anchors] copy.lib = deepcopy(glyph.lib) pointPen = copy.getPointPen() if reverseContour: from fontTools.pens.pointPen import ReverseContourPointPen pointPen = ReverseContourPointPen(pointPen) glyph.drawPoints(pointPen) return copy
def getReversePen(self): adapterPen = PointToSegmentPen(self.otherPen) reversePen = ReverseContourPointPen(adapterPen) return SegmentToPointPen(reversePen)