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))
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 testReverseContourOpenPath(self): digestPen = DigestPointPen() TestShapes.openPath(digestPen) d1 = digestPen.getDigest() digestPen = DigestPointPen() pen = ReverseContourPointPen(digestPen) pen.beginPath() pen.addPoint((600, 100), "move") pen.addPoint((600, 600), "line") pen.addPoint((100, 600), "line") pen.addPoint((100, 100), "line") pen.endPath() d2 = digestPen.getDigest() self.assertEqual(d1, d2)
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 robofab.pens.reverseContourPointPen 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) # draw the points back into this contour self.disableNotifications() otherContour.drawPoints(self) self.enableNotifications() # 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 testReversContourFromGlyphSet(self): glyphSet = GlyphSet(getDemoFontGlyphSetPath()) digestPen = DigestPointPen() glyphSet["testglyph1"].drawPoints(digestPen) digest1 = digestPen.getDigest() digestPen = DigestPointPen() pen = ReverseContourPointPen(digestPen) glyphSet["testglyph1.reversed"].drawPoints(pen) digest2 = digestPen.getDigest() self.assertEqual(digest1, digest2)
def reverseContour(self): """reverse the contour""" from robofab.pens.reverseContourPointPen import ReverseContourPointPen index = self.index glyph = self.getParent() pen = glyph.getPointPen() reversePen = ReverseContourPointPen(pen) self.drawPoints(reversePen) # we've drawn the reversed contour onto our parent glyph, # so it sits at the end of the contours list: newContour = glyph.contours.pop(-1) for segment in newContour.segments: segment.setParent(self) self.segments = newContour.segments self._hasChanged()
def reverse(self): """ Reverse the direction of the contour. This posts a *Contour.Changed* notification. """ from robofab.pens.reverseContourPointPen import ReverseContourPointPen # put the current points in another contour otherContour = self.__class__(self._pointClass) # draw the points in this contour through # the reversing pen. reversePen = ReverseContourPointPen(otherContour) self.drawPoints(reversePen) # clear the points in this contour # and copy the points from the other # contour to this contour. self._clear(postNotification=False) self._points = list(otherContour._points) # post a notification self.dirty = True
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 with the pen a rect in the glyph 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 with the pen an oval in the glyph 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()
def convert(glyph, maxDistance, minLength, useArcLength): nbPoints = 0 conts = [] for contour in glyph: conts.append([]) cmds = conts[-1] p0 = getFirstOnPoint(contour) nseg = len(contour) prevSeg = contour[nseg - 1] for s in range(nseg): seg = contour[s] if seg.type == 'line': p1 = seg.points[0] cmds.append((lineto, p1)) nbPoints += 1 p0 = p1 elif seg.type == 'qcurve': #print "Should not have quadratic segment in here. Skipping.", p0 = seg.points[-1] elif seg.type == 'curve': p1, p2, p3 = seg.points pt0 = Point(p0.x, p0.y) pt1 = Point(p1.x, p1.y) pt2 = Point(p2.x, p2.y) pt3 = Point(p3.x, p3.y) qsegs = [] inputCubic = (pt0, pt1, pt2, pt3) for cubic in splitCubicOnInflection(inputCubic, minLength): qsegs = qsegs + adaptiveSmoothCubicSplit( cubic, maxDistance, minLength, useArcLength) nbQSegMinusOne = len(qsegs) - 1 smooth = True for i, qseg in enumerate(qsegs): # We have to split the quad segment because Robofont does not (seem to) support # ON-OFF-ON quadratic bezier curves. If ever Robofont can handle this, # then it would suffice to write something like: # (a0, a1, a2) = qseg # cmds.append((curveto, (a1, a2))) if i == nbQSegMinusOne: smooth = seg.smooth q1, q2 = qseg cmds.append((curveto, (q1[1], q2[1], q2[2], smooth))) #ql, qr = splitQuadratic(0.5, qseg) #cmds.append((curveto, (ql[1], qr[1], qr[2], smooth))) nbPoints += 3 p0 = p3 else: #print "Unknown segment type: "+seg.type+". Skipping.", p0 = seg.points[-1] prevSeg = seg glyph.clearContours() glyph.preferredSegmentStyle = 'qcurve' pen = ReverseContourPointPen(glyph.getPointPen()) for cmds in conts: if cmds == []: continue pen.beginPath() for action, args in cmds: action(pen, args) pen.endPath() # Now, we make sure that each contour starts with a ON control point for contour in glyph: contour.setStartSegment(0) glyph.update() return nbPoints
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 with the pen a rect in the glyph 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 with the pen an oval in the glyph 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()
def makeBlueprint(font): # copy fg to bg and mark the glyph red if it contains any contours for name in font: glyph = font[name] background = glyph.layers[0] foreground = glyph.layers[1] if len(background): print glyph, 'had a background ({0} contours)'.format(len(background)) # copy fg to bg glyph.layers[0] = foreground; if len(foreground): # Glyphs marked red are the ones that need new outlines # not red marked glyphs contain only references glyph.color = 0xff0000 else: glyph.color = 0xffffff # This draws a scrambled echo of the original glyphs to the foreground # so it is easy to spot where work is needed and also still which glyph # is in which place. #we are going to draw with cubics font.layers['Fore'].is_quadratic = False; for name in font: glyph = font[name] width = glyph.width vwidth = glyph.vwidth anchorPoints = tuple(glyph.anchorPoints) newFg = fontforge.layer(); newFg.is_quadratic = False; glyph.layers[1] = newFg; background = glyph.background # this creates a copy if not len(background): continue # convert the copy to cubics the real background stays quadratics background.is_quadratic = False layerPen = glyph.glyphPen() # <= pen will remove more than it should # outer line of the outline toSegments = PointToSegmentPen(layerPen) rand = RandomizePointPen(toSegments, [-7, 7]) moved = MovePointsPointPen(rand, -15, cmath.pi * .5) points = SegmentToPointPen(moved) background.draw(points) # inner line of the outline toSegments = PointToSegmentPen(layerPen) rand = RandomizePointPen(toSegments, [-7, 7]) moved = MovePointsPointPen(rand, 15, -cmath.pi * .5) reverse = ReverseContourPointPen(moved) points = SegmentToPointPen(reverse) background.draw(points) # restore stuff that a pen should rather not change automagically # in fact, the pen should not reset anything besides outline and components. glyph.width = width glyph.vwidth = vwidth [glyph.addAnchorPoint(*p) for p in anchorPoints]
def addShapeInGlyphForPoint(self, glyph, point): w = h = self.size if self.useGrid: x = int(floor(point.x / float(w))) * w y = int(floor(point.y / float(h))) * h else: x = point.x - w*.5 y = point.y - h*.5 pen = glyph.getPointPen() if glyph.preferedSegmentType == "qcurve": pen = ReverseContourPointPen(pen) if self.drawingMode == RECT_MODE: 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() elif self.drawingMode == OVAL_MODE: hw = w/2. hh = h/2. r = .55 segmentType = glyph.preferedSegmentType if glyph.preferedSegmentType == "qcurve": r = .42 pen.beginPath() pen.addPoint(_roundPoint(x + hw, y), segmentType) 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) 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) pen.addPoint(_roundPoint(x + hw - hw*r, y + h)) pen.addPoint(_roundPoint(x, y + hh + hh*r)) pen.addPoint(_roundPoint(x, y + hh), segmentType) pen.addPoint(_roundPoint(x, y + hh - hh*r)) pen.addPoint(_roundPoint(x + hw - hw*r, y)) pen.endPath() elif self.drawingMode == COMPONENT_MODE and self.componentName and self.componentName != glyph.name: pen.addComponent(self.componentName, [1, 0, 0, 1, x, y])