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 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 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])
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 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