def draw(self): self.graph_in_window = [] c_width, c_height = self.parent.graph_width, self.parent.graph_height drawBot.fill(None) # horizontal line drawBot.stroke(0) drawBot.strokeWidth(0.5) drawBot.line((0, c_height / 2), (c_width, c_height / 2)) # vertical lines # the combination of both margins equal one additional step graph_margin = self.parent.step_dist / 2 for i in range(self.parent.steps + 1): x = graph_margin + i * self.parent.step_dist drawBot.line((x, 0), (x, c_height)) # the graph drawBot.stroke(0, 0, 1) drawBot.strokeWidth(5) drawBot.lineCap('round') prev = None max_value = max([abs(v) for v in self.parent.number_values]) zero_point = c_height / 2 min_scale = 40 self.max_allowed_value = 500 self.graph_scale = max_value / self.parent.graph_height self.min_graph_scale = min_scale / self.parent.graph_height slider_controls = [] for i, value in enumerate(self.parent.number_values): if max_value > min_scale: self.amplitude = value / max_value else: self.amplitude = value / min_scale x = graph_margin + i * self.parent.step_dist y = zero_point + c_height * 0.4 * self.amplitude y_window = (self.parent.w_height - self.parent.graph_height + y - self.parent.padding) self.graph_in_window.append((x, y_window)) if prev: drawBot.line(prev, (x, y)) prev = x, y slider_controls.append((x, y)) # slider heads for x, y in slider_controls: radius = 10 drawBot.fill(1) drawBot.stroke(0) drawBot.strokeWidth(0.5) drawBot.oval(x - radius, y - radius, 2 * radius, 2 * radius)
def draw(self, scale): size = 20 * scale save() fill(0.2, 0.5, 0.35, 0.3) stroke(None) #for contour in self.errors.keys(): # for p in contour: # oval(p[0]-5, p[1]-5, 10, 10) for p in self.errors: oval(p[0]-size/2, p[1]-size/2, size, size) restore()
def dot(self, p, s=4, scale=1, stacked=False): # draw a dot ctx.save() ctx.stroke(None) if stacked: ctx.fill(0, .5, 1) else: ctx.fill(1, .5, 0) s *= scale ctx.oval(p[0] - .5 * s, p[1] - .5 * s, s, s) ctx.restore()
def draw(self, scale): size = 20 * scale save() fill(0.2, 0.5, 0.35, 0.3) stroke(None) #for contour in self.errors.keys(): # for p in contour: # oval(p[0]-5, p[1]-5, 10, 10) for p in self.errors: oval(p[0] - size / 2, p[1] - size / 2, size, size) restore()
def drawPoints(self, info): newPoints = self.getValues(None) if newPoints != None: glyph = CurrentGlyph() onCurveSize = getDefault("glyphViewOncurvePointsSize") * 5 offCurveSize = getDefault("glyphViewOncurvePointsSize") * 3 fillColor = tuple([i for i in getDefault("glyphViewCurvePointsFill")]) upmScale = (glyph.font.info.unitsPerEm/1000) scale = info["scale"] oPtSize = onCurveSize * scale fPtSize = offCurveSize * scale d.save() # thanks Erik! textLoc = newPoints[0][3][0] + math.cos(self.returnAngle(newPoints)) * (scale*.25*120) * 2, newPoints[0][3][1] + math.sin(self.returnAngle(newPoints)) * (scale*.25*120) * 2 for b in newPoints: for a in b: if a == newPoints[1][0] or a == newPoints[0][-1]: d.oval(a[0]-oPtSize/2,a[1]-oPtSize/2, oPtSize, oPtSize) else: d.oval(a[0]-fPtSize/2,a[1]-fPtSize/2, fPtSize, fPtSize) d.fill(fillColor[0],fillColor[1],fillColor[2],fillColor[3]) d.stroke(fillColor[0],fillColor[1],fillColor[2],fillColor[3]) d.strokeWidth(scale) d.line(newPoints[0][2],newPoints[1][1]) d.restore() # https://robofont.com/documentation/building-tools/toolspace/observers/draw-info-text-in-glyph-view/?highlight=draw%20text glyphWindow = CurrentGlyphWindow() if not glyphWindow: return glyphView = glyphWindow.getGlyphView() textAttributes = { AppKit.NSFontAttributeName: AppKit.NSFont.userFixedPitchFontOfSize_(11), } glyphView.drawTextAtPoint( f'{round(abs(math.degrees(self.returnAngle(newPoints)))%180,4)}°\n{str(round(self.returnRatio(newPoints),4))}', textAttributes, textLoc, yOffset=0, drawBackground=True, centerX=True, centerY=True, roundBackground=False,) UpdateCurrentGlyphView()
def _drawGlyphOutline(self, glyph, scalingFactor, offset_X=0): dt.save() dt.translate(offset_X, 0) dt.fill(None) dt.strokeWidth(1 * scalingFactor) dt.stroke(*LIGHT_GRAY_COLOR) dt.drawGlyph(glyph) scaledRadius = BCP_RADIUS * scalingFactor for eachContour in glyph: for eachBPT in eachContour.bPoints: dt.stroke(None) dt.fill(*LIGHT_GRAY_COLOR) dt.rect(eachBPT.anchor[0] - scaledRadius / 2., eachBPT.anchor[1] - scaledRadius / 2., scaledRadius, scaledRadius) if eachBPT.bcpIn != (0, 0): dt.stroke(None) dt.fill(*LIGHT_GRAY_COLOR) dt.oval( eachBPT.anchor[0] + eachBPT.bcpIn[0] - scaledRadius / 2., eachBPT.anchor[1] + eachBPT.bcpIn[1] - scaledRadius / 2., scaledRadius, scaledRadius) dt.stroke(*LIGHT_GRAY_COLOR) dt.fill(None) dt.line((eachBPT.anchor[0], eachBPT.anchor[1]), (eachBPT.anchor[0] + eachBPT.bcpIn[0], eachBPT.anchor[1] + eachBPT.bcpIn[1])) if eachBPT.bcpOut != (0, 0): dt.stroke(None) dt.fill(*LIGHT_GRAY_COLOR) dt.oval( eachBPT.anchor[0] + eachBPT.bcpOut[0] - scaledRadius / 2., eachBPT.anchor[1] + eachBPT.bcpOut[1] - scaledRadius / 2., scaledRadius, scaledRadius) dt.stroke(*LIGHT_GRAY_COLOR) dt.fill(None) dt.line((eachBPT.anchor[0], eachBPT.anchor[1]), (eachBPT.anchor[0] + eachBPT.bcpOut[0], eachBPT.anchor[1] + eachBPT.bcpOut[1])) dt.restore()
def _drawOffgridPoints(self, glyph, scalingFactor): dt.save() dt.fill(*RED_COLOR) dt.stroke(None) scaledRadius = OFFGRID_RADIUS * scalingFactor for eachContour in glyph: for eachBPT in eachContour.bPoints: if eachBPT.anchor[0] % 4 != 0 or eachBPT.anchor[1] % 4 != 0: dt.oval(eachBPT.anchor[0] - scaledRadius / 2., eachBPT.anchor[1] - scaledRadius / 2., scaledRadius, scaledRadius) if eachBPT.bcpIn != (0, 0): bcpInAbs = eachBPT.anchor[0] + eachBPT.bcpIn[ 0], eachBPT.anchor[1] + eachBPT.bcpIn[1] if bcpInAbs[0] % 4 != 0 or bcpInAbs[1] % 4 != 0: dt.oval(bcpInAbs[0] - scaledRadius / 2., bcpInAbs[1] - scaledRadius / 2., scaledRadius, scaledRadius) if eachBPT.bcpOut != (0, 0): bcpOutAbs = eachBPT.anchor[0] + eachBPT.bcpOut[ 0], eachBPT.anchor[1] + eachBPT.bcpOut[1] if bcpOutAbs[0] % 4 != 0 or bcpOutAbs[1] % 4 != 0: dt.oval(bcpOutAbs[0] - scaledRadius / 2., bcpOutAbs[1] - scaledRadius / 2., scaledRadius, scaledRadius) dt.restore()
def drawBkgnd(self, info): # Draw the interpolated glyph outlines scale = info["scale"] ptSize = 7 * scale if self.interpolatedGlyph: # Draw the glyph outline pen = CocoaPen(None) self.interpolatedGlyph.draw(pen) dt.fill(r=None, g=None, b=None, a=1) dt.stroke(r=0, g=0, b=0, a=0.4) dt.strokeWidth(2 * scale) dt.save() dt.translate(self.currentGlyph.width) dt.drawPath(pen.path) dt.stroke(r=0, g=0, b=0, a=1) # Draw the points and handles for contour in self.interpolatedGlyph.contours: for bPoint in contour.bPoints: inLoc = self.addPoints(bPoint.anchor, bPoint.bcpIn) outLoc = self.addPoints(bPoint.anchor, bPoint.bcpOut) dt.line(inLoc, bPoint.anchor) dt.line(bPoint.anchor, outLoc) dt.fill(r=1, g=1, b=1, a=1) dt.oval(bPoint.anchor[0] - (ptSize * 0.5), bPoint.anchor[1] - (ptSize * 0.5), ptSize, ptSize) dt.fill(0) # Draw an "X" over each BCP if not bPoint.bcpIn == (0, 0): dt.oval(inLoc[0] - (ptSize * 0.5), inLoc[1] - (ptSize * 0.5), ptSize, ptSize) #dt.line((inLoc[0]-(ptSize*0.5), inLoc[1]-(ptSize*0.5)), (inLoc[0]+(ptSize*0.5), inLoc[1]+(ptSize*0.5))) #dt.line((inLoc[0]+(ptSize*0.5), inLoc[1]-(ptSize*0.5)), (inLoc[0]-(ptSize*0.5), inLoc[1]+(ptSize*0.5))) if not bPoint.bcpOut == (0, 0): dt.oval(outLoc[0] - (ptSize * 0.5), outLoc[1] - (ptSize * 0.5), ptSize, ptSize) #dt.line((outLoc[0]-(ptSize*0.5), outLoc[1]-(ptSize*0.5)), (outLoc[0]+(ptSize*0.5), outLoc[1]+(ptSize*0.5))) #dt.line((outLoc[0]+(ptSize*0.5), outLoc[1]-(ptSize*0.5)), (outLoc[0]-(ptSize*0.5), outLoc[1]+(ptSize*0.5))) dt.restore()
def draw(self, scale): circleRadius = 12 * scale if self.selectionBounds: # The selection rect rect = (self.selectionBounds[0], self.selectionBounds[1], self.selectionBounds[2] - self.selectionBounds[0], self.selectionBounds[3] - self.selectionBounds[1]) dt.save() dt.font("Lucida Grande") dt.fontSize(11 * scale) # Circles around opoints dt.fill(None) dt.stroke(*self.selectionColor[0:3], 0.25) dt.strokeWidth(7 * scale) for point in self.glyph.selection: dt.oval(point.x - circleRadius, point.y - circleRadius, circleRadius * 2, circleRadius * 2) # Bounding box dt.strokeWidth(1 * scale) dt.stroke(*self.selectionColor) dt.rect(*rect) # Boxes on the handles for handle, handleLoc in self.selectionHandles.items(): dt.strokeWidth(2 * scale) dt.stroke(*self.selectionColor[0:3], 1) if handle == self.selectedHandle: dt.fill(*self.selectionColor[0:3], 1) boxRadius = 6 * scale else: dt.fill(None) boxRadius = 4 * scale # Draw the handle dt.rect(handleLoc[0] - boxRadius, handleLoc[1] - boxRadius, boxRadius * 2, boxRadius * 2) # Draw the handle delta text dt.stroke(None) dt.fill(*self.selectionColor[0:3], 1) if handle == "N": dt.textBox(str( int(self.selectionBounds[3] - self.cachedSelectionBounds[3])), (handleLoc[0] - (100 * scale), handleLoc[1], (200 * scale), (20 * scale)), align="center") if handle == "S": dt.textBox(str( int(self.selectionBounds[1] - self.cachedSelectionBounds[1])), (handleLoc[0] - (100 * scale), handleLoc[1] - (30 * scale), (200 * scale), (20 * scale)), align="center") if handle == "E": dt.textBox(str( int(self.selectionBounds[2] - self.cachedSelectionBounds[2])), (handleLoc[0] + (10 * scale), handleLoc[1] - (11 * scale), (200 * scale), (20 * scale)), align="left") if handle == "W": dt.textBox(str( int(self.selectionBounds[0] - self.cachedSelectionBounds[0])), (handleLoc[0] - (211 * scale), handleLoc[1] - (11 * scale), (200 * scale), (20 * scale)), align="right") # Draw the scale text dt.stroke(None) dt.fill(*self.selectionColor[0:3], 1) infoText = "Scale: %.3f %.3f" % self.currentScale dt.text(infoText, self.selectionBounds[2] + (10 * scale), self.selectionBounds[1] - (20 * scale)) dt.restore()
def draw(self): w = self.w.c.width() h = self.w.c.height() m = 130 center = w * .5, h * .5 d = self.dotSize r = min(.5 * (h - 2 * m), .5 * (w - 2 * m)) if self.pointer is None: self.pointer = center a1 = self.orientation * math.pi a2 = a1 + 2 / 3 * math.pi a3 = a1 - 2 / 3 * math.pi self.p1 = p1 = center[0] + (r * math.sin(a1)), center[1] + ( r * math.cos(a1)) self.p2 = p2 = center[0] + (r * math.sin(a2)), center[1] + ( r * math.cos(a2)) self.p3 = p3 = center[0] + (r * math.sin(a3)), center[1] + ( r * math.cos(a3)) self.snapped = None if self.closeToPoint(self.p1, self.pointer): self.pointer = self.p1 self.snapped = 0 if self.closeToPoint(self.p2, self.pointer): self.pointer = self.p2 self.snapped = 1 if self.closeToPoint(self.p3, self.pointer): self.pointer = self.p3 self.snapped = 2 p1d = p1[0] - .5 * d, p1[1] - .5 * d, d, d p2d = p2[0] - .5 * d, p2[1] - .5 * d, d, d p3d = p3[0] - .5 * d, p3[1] - .5 * d, d, d ctx.save() ctx.stroke(.8, .8, .7) ctx.strokeWidth(.4) ctx.strokeWidth(.8) ctx.line(p1, p2) ctx.line(p2, p3) ctx.line(p3, p1) if self.pointer is not None: ctx.line(p1, self.pointer) ctx.line(p2, self.pointer) ctx.line(p3, self.pointer) ctx.stroke(None) ctx.fill(0) ctx.oval(*p1d) ctx.oval(*p2d) ctx.oval(*p3d) g1, g2, g3 = self.glyphs if g1 is not None: ctx.save() ctx.translate(p1[0], p1[1]) ctx.scale(self.glyphScale) ctx.translate(100, 0) ctx.drawGlyph(g1) ctx.restore() if g2 is not None: ctx.save() ctx.translate(p2[0], p2[1]) ctx.scale(self.glyphScale) ctx.translate(100, 0) ctx.drawGlyph(g2) ctx.restore() if g3 is not None: ctx.save() ctx.translate(p3[0], p3[1]) ctx.scale(self.glyphScale) ctx.translate(100, 0) ctx.drawGlyph(g3) ctx.restore() if self.pointer: ctx.save() ctx.fill(1, 0, 0) ctx.stroke(None) d = 10 ctx.oval(self.pointer[0] - .5 * d, self.pointer[1] - .5 * d, d, d) f1, f2, f3 = ip(p1, p2, p3, self.pointer) self._factors = f1, f2, f3 r = None if self.mGlyphs is not None: if None not in self.mGlyphs: try: self.result = r = f1 * self.mGlyphs[ 0] + f2 * self.mGlyphs[1] + f3 * self.mGlyphs[2] except IndexError or TypeError: print("Sorry, these glyphs can't interpolate..") if r: ctx.save() ctx.translate(self.pointer[0], self.pointer[1]) ctx.scale(self.glyphScale) ctx.translate(100, 0) g = RGlyph() g.fromMathGlyph(r) ctx.drawGlyph(g) t = "{:02.2f}, {:02.2f}, {:02.2f}".format(f1, f2, f3) ctx.font("Menlo-Regular") ctx.fontSize(6 / self.glyphScale) ctx.text(t, (0, -200)) ctx.restore() ctx.restore() ctx.restore()