def drawLines(self, lineThickness): # Don't do anything if no segments have been selected, # or if more than 1 contour has been selected if not self.selectedSegments or len(self.selectedContours) > 1: return contourPoints = self._collectPointsInContour(self.selectedContours[0]) for segment in self.selectedSegments: selectedOnCurves = [] selectedOffCurves = [] for point in segment.points: if point.type == "offcurve": selectedOffCurves.append(point) else: selectedOnCurves.append(point) pt0 = self._findPrevOnCurvePt(selectedOnCurves[0], contourPoints).position pt1 = selectedOnCurves[0].position pt2 = selectedOffCurves[0].position pt3 = selectedOffCurves[1].position # if lines are parallel, lines are green; otherwise, red if self._checkParallel((pt0, pt1), (pt2, pt3)): dt.stroke(0, 1, 0, 1) else: dt.stroke(1, 0, 0, 1) dt.strokeWidth(lineThickness) dt.line(pt0, pt1) dt.line(pt2, pt3)
def _handlesPreview(self, info): _doodle_glyph = info["glyph"] if roboFontVersion > "3.1": _doodle_glyph_selected_points = _doodle_glyph.selectedPoints else: _doodle_glyph_selected_points = _doodle_glyph.selection if CurrentGlyph() is not None \ and _doodle_glyph is not None \ and len(_doodle_glyph.components) == 0 \ and _doodle_glyph_selected_points != []: glyph = self.tmp_glyph #.copy() ref_glyph = CurrentGlyph() save() stroke(0, 0, 0, 0.3) strokeWidth(info["scale"]) fill(None) l = 4 * info["scale"] for contourIndex in range(len(glyph)): contour = self.tmp_glyph.contours[contourIndex] ref_contour = ref_glyph.contours[contourIndex] for i in range(len(contour.segments)): segment = contour[i] if ref_contour[i].selected and segment.type == "curve": for p in segment.points[0:2]: x = p.x y = p.y line((x-l, y-l), (x+l, y+l)) line((x-l, y+l), (x+l, y-l)) restore()
def _drawBaseline(self, glyphName): glyphToDisplay = self.fontObj[glyphName] dt.save() dt.stroke(*BLACK) dt.fill(None) # reversed scaling factor dt.strokeWidth( 1 / (self.ctrlHeight / (self.canvasScalingFactor * self.fontObj.info.unitsPerEm))) dt.line((0, 0), (glyphToDisplay.width, 0)) dt.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 _drawSidebearings(self, glyphName): glyphToDisplay = self.fontObj[glyphName] dt.save() dt.stroke(*BLACK) dt.fill(None) # reversed scaling factor dt.strokeWidth( 1 / (self.ctrlHeight / (self.canvasScalingFactor * self.fontObj.info.unitsPerEm))) dt.fill(*LIGHT_GRAY) dt.line( (0, self.fontObj.info.descender), (0, self.fontObj.info.descender + self.fontObj.info.unitsPerEm)) dt.line((glyphToDisplay.width, self.fontObj.info.descender), (glyphToDisplay.width, self.fontObj.info.descender + self.fontObj.info.unitsPerEm)) dt.restore()
def _drawGeometry(self, info): reference_glyph = CurrentGlyph() #rect(0, 0, 200, 100) #rect(0, 0, self.w.eqCurvatureSlider.get() * 200, 100) if roboFontVersion > "3.1": reference_glyph_selected_points = reference_glyph.selectedPoints else: reference_glyph_selected_points = reference_glyph.selection stroke(0.5, 0.6, 0.9, 0.8) strokeWidth(0.8 * info["scale"]) if reference_glyph_selected_points != []: for contourIndex in range(len(reference_glyph.contours)): reference_contour = reference_glyph.contours[contourIndex] for i in range(len(reference_contour.segments)): reference_segment = reference_contour[i] if reference_segment.selected and reference_segment.type == "curve": # last point of the previous segment p0 = reference_contour[i-1][-1] if len(reference_segment.points) == 3: p1, p2, p3 = reference_segment.points alpha = atan2(p1.y - p0.y, p1.x - p0.x) beta = atan2(p2.y - p3.y, p2.x - p3.x) if abs(alpha - beta) >= 0.7853981633974483: if isOnLeft(p0, p3, p1) and isOnLeft(p0, p3, p2) or isOnRight(p0, p3, p1) and isOnRight(p0, p3, p2): #alpha, beta, gamma = getTriangleAngles(p0, p1, p2, p3) a, b, c = getTriangleSides(p0, p1, p2, p3) line((p0.x, p0.y), (p0.x + (c+5) * cos(alpha), p0.y + (c+5) * sin(alpha))) line((p3.x, p3.y), (p3.x + (a+5) * cos(beta) , p3.y + (a+5) * sin(beta) )) line((p0.x, p0.y), (p3.x, p3.y))
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): try: dt.save() dt.font(SYSTEM_FONT_NAME) dt.fontSize(CAPTION_BODY_SIZE) for indexGlyphName, eachGlyphName in enumerate( self.glyphNamesToDisplay): # in this way it does not draw what's outside the canvas frame! if SPACING_COL_WIDTH * indexGlyphName > self.getPosSize()[2]: continue self._drawMatrixColumn(eachGlyphName) dt.translate(SPACING_COL_WIDTH, 0) self._setBoxQualities() dt.line((0, 0), (0, self.getPosSize()[3])) dt.restore() except Exception, error: print traceback.format_exc()
def _drawMetricsData(self, glyphName, offset): dt.save() glyphToDisplay = self.fontObj[glyphName] dt.translate(0, self.fontObj.info.descender) reverseScalingFactor = 1 / ( self.ctrlHeight / (self.canvasScalingFactor * self.fontObj.info.unitsPerEm)) if self.isSidebearingsActive is True: dt.fill(None) dt.stroke(*BLACK) dt.strokeWidth(reverseScalingFactor) dt.line((0, 0), (0, -offset * reverseScalingFactor)) dt.line((glyphToDisplay.width, 0), (glyphToDisplay.width, -offset * reverseScalingFactor)) dt.restore() dt.save() dt.translate(0, self.fontObj.info.descender) dt.translate(0, -offset * reverseScalingFactor) dt.fill(*BLACK) dt.stroke(None) dt.font(SYSTEM_FONT_NAME) dt.fontSize(BODY_SIZE * reverseScalingFactor) textWidth, textHeight = dt.textSize(u'{}'.format(glyphToDisplay.width)) dt.textBox(u'{:d}'.format(int(glyphToDisplay.width)), (0, 0, glyphToDisplay.width, textHeight * 2), align='center') dt.textBox(u'\n{:d}'.format(int(glyphToDisplay.leftMargin)), (0, 0, glyphToDisplay.width / 2., textHeight * 2), align='center') dt.textBox(u'\n{:d}'.format(int(glyphToDisplay.rightMargin)), (glyphToDisplay.width / 2., 0, glyphToDisplay.width / 2., textHeight * 2), align='center') dt.restore()
def _drawDiagonals(self, currentGlyph, scalingFactor, offset_X=0): if DIAGONALS_KEY not in currentGlyph.lib: return None diagonalsData = calcDiagonalsData(currentGlyph, DIAGONALS_KEY) for ptsToDisplay, angle, distance in diagonalsData: pt1, pt2 = ptsToDisplay dt.save() dt.stroke(*self.diagonalColor) dt.fill(None) dt.strokeWidth(1 * scalingFactor) if 90 < angle <= 180 or -180 < angle < -90: direction = -1 adjustedAngle = angle + 180 + 90 else: direction = 1 adjustedAngle = angle + 90 diagonalPt1 = pt1[0] + cos(radians(adjustedAngle)) * ( (DIAGONAL_OFFSET - 1) * direction), pt1[1] + sin( radians(adjustedAngle)) * ( (DIAGONAL_OFFSET - 1) * direction) diagonalPt2 = pt2[0] + cos(radians(adjustedAngle)) * ( (DIAGONAL_OFFSET - 1) * direction), pt2[1] + sin( radians(adjustedAngle)) * ( (DIAGONAL_OFFSET - 1) * direction) offsetPt1 = pt1[0] + cos(radians( adjustedAngle)) * DIAGONAL_OFFSET * direction, pt1[1] + sin( radians(adjustedAngle)) * DIAGONAL_OFFSET * direction offsetPt2 = pt2[0] + cos(radians( adjustedAngle)) * DIAGONAL_OFFSET * direction, pt2[1] + sin( radians(adjustedAngle)) * DIAGONAL_OFFSET * direction dt.line((pt1), (offsetPt1)) dt.line((pt2), (offsetPt2)) dt.line((diagonalPt1), (diagonalPt2)) dt.restore() dt.save() textQualities(BODYSIZE_CAPTION * scalingFactor) offsetMidPoint = calcMidPoint(offsetPt1, offsetPt2) dt.translate(offsetMidPoint[0], offsetMidPoint[1]) if 90 < angle <= 180 or -180 < angle < -90: dt.rotate(angle + 180) textBoxY = -BODYSIZE_CAPTION * 1.2 * scalingFactor else: dt.rotate(angle) textBoxY = 0 dataToPlot = u'∡{:.1f} ↗{:d}'.format(angle % 180, int(distance)) textWidth, textHeight = dt.textSize(dataToPlot) dt.textBox(dataToPlot, (-textWidth / 2., textBoxY, textWidth, BODYSIZE_CAPTION * 1.2 * scalingFactor), align='center') dt.restore()
def draw(self, infoOrScale, glyph=None, lineWeightMultiplier=1): """ Draw lines. This method is called by both the observer watching "draw" (turned on when "/" is pressed) and by the tool, when it's active. When used by the observer, it returns "info", a dict from which we need to grab scale. When used by the tool, it returns scale, so we can use it right away. """ # This is just for naming... self.scale = infoOrScale if isinstance(infoOrScale, dict) and glyph is None: self.scale = infoOrScale["scale"] glyph = infoOrScale["glyph"] # Just in case... if self.scale is None or glyph is None: return # Also do this here in case mouseDown isn't fired # (eg. user uses keyboard to select segments) self._analyzeSelection(glyph) for selected in self._selectedSegments: p1, segment = selected h1, h2, p2 = segment if hf.areTheyParallel((p1, p2,), (h1, h2), self.tolerance): dt.stroke(0, 0, 1, 1) else: dt.stroke(1, 0, 0, 1) dt.strokeWidth(self.scale) dt.line((p1.x, p1.y), (p2.x, p2.y)) dt.strokeWidth(self.scale * lineWeightMultiplier) dt.line((h1.x, h1.y), (h2.x, h2.y))
def draw_histogram(self, font, upm, color, show_glyphs=False, histogram=None): if histogram is None: if self.histogram is None: return histogram = self.histogram drawing.save() drawing.fill(1, 0.5, 0.2, 1.0) drawing.stroke(color[0], color[1], color[2], color[3]) for width in sorted(histogram.keys()): num = len(histogram[width]) x = 10 + width * self.histogram_width / (upm * self.ems_horizontal) drawing.save() if show_glyphs: drawing.save() drawing.fill(color[0], color[1], color[2], 0.2) drawing.fontsize(self.scale_vertical) for i in range(len(histogram[width])): glyph_name = histogram[width][i] if glyph_name in font: u = font[glyph_name].unicode if u: drawing.text("%s" % unichr(u), x + 4, 18 + i * self.scale_vertical) else: drawing.text("%s" % glyph_name, x + 4, 18 + i * self.scale_vertical) else: drawing.text("%s" % glyph_name, x + 4, 18 + i * self.scale_vertical) drawing.restore() drawing.strokewidth(2) else: drawing.strokewidth(6) # draw bars drawing.line(x, 20, x, 20 + num * self.scale_vertical) drawing.strokewidth(0) drawing.text("%s" % (num), x - 3 * len(str(num)), 22 + num * self.scale_vertical) drawing.restore() drawing.restore()
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 _drawArrow(self, position, kind, size, width): x, y = position save() translate(x, y) fill(0, 0.8, 0, 0.1) strokeWidth(width) stroke(0.9, 0.1, 0, 0.85) line(-width/2, 0, size, 0) line(0, width/2, 0, -size) line(0, 0, size, -size) #rect(x-scale, y-scale, scale, scale) if self.showLabels: fill(0.4, 0.4, 0.4, 0.7) stroke(None) font("LucidaGrande") fontSize(int(round(size * 1.1))) text(kind, (int(round(size * 1.8)), int(round(-size)))) restore()
def _drawArrow(self, position, kind, size, width): x, y = position save() translate(x, y) fill(0, 0.8, 0, 0.1) strokeWidth(width) stroke(0.9, 0.1, 0, 0.85) line(-width / 2, 0, size, 0) line(0, width / 2, 0, -size) line(0, 0, size, -size) #rect(x-scale, y-scale, scale, scale) if self.showLabels: fill(0.4, 0.4, 0.4, 0.7) stroke(None) font("LucidaGrande") fontSize(int(round(size * 1.1))) text(kind, (int(round(size * 1.8)), int(round(-size)))) restore()
def _drawGlyphCellArrow(self, num_errors): x = 3 y = 3 width = 2 size = 7 save() translate(4, 4) fill(0.9, 0.4, 0.3, 1) rect(-1, -1, size+1, size+1) lineJoin("round") lineCap("butt") # butt, square, round strokeWidth(width) stroke(1, 1, 1) line(-width/2, 0, size, 0) line(0, -width/2, 0, size) line(width/2, width/2, size-0.5, size-0.5) restore()
def _drawGrid(self): label_every = 1 if self.units > 24: label_every = 2 drawing.save() drawing.strokeWidth(0) drawing.stroke(None) drawing.fill(0.88, 0.92, 0.98) if self.system is not None: if self.system.min_units is not None: drawing.rect(0, 0, 10 + self.system.min_units * self.histogram_width / (self.units * self.ems_horizontal), self.histogram_height) if self.system.max_units is not None: drawing.rect(10 + self.system.max_units * self.histogram_width / (self.units * self.ems_horizontal), 0, self.histogram_width, self.histogram_height) drawing.strokeWidth(1.0) drawing.stroke(0.8, 0.8, 0.8) drawing.fill(0.6, 0.6, 0.6) for u in range(0, int(ceil(self.units * self.ems_horizontal))): x = 10 + u * self.histogram_width / (self.units * self.ems_horizontal) if u == self.units: # mark the full em drawing.stroke(0, 0, 0) drawing.line(x, 20, x, self.histogram_height-10) drawing.strokeWidth(0) drawing.text("1 em", x + 4, self.histogram_height - 21) drawing.strokeWidth(1.0) elif u % 10 == 0: # make every 10th line darker drawing.stroke(0.5, 0.5, 0.5) drawing.line(x, 20, x, self.histogram_height - 20) else: drawing.stroke(0.8, 0.8, 0.8) drawing.line(x, 20, x, self.histogram_height - 30) if u % label_every == 0: drawing.strokeWidth(0) drawing.text("%s" % (u), x - 3 * len(str(u)), 5) drawing.restore()
def _drawGlyphCellArrow(self, num_errors): x = 3 y = 3 width = 2 size = 7 save() translate(4, 4) stroke(0.2) strokeWidth(0.5) lineJoin("miter") fill(0.9, 0.4, 0.3) rect(-1, -1, size + 1, size + 1) lineCap("butt") # butt, square, round strokeWidth(width) stroke(1, 0.9, 0.65) line((0, width / 2 - 0.5), (size - width / 2 + 0.5, width / 2 - 0.5)) line((width / 2 - 0.5, width / 2 - 1.5), (width / 2 - 0.5, size - width / 2 + 0.5)) lineCap("round") line((width // 2, width // 2), (size - 1.5, size - 1.5)) restore()
def _drawMatrixColumn(self, glyphName): dt.save() # definitive dt.translate( 0, self.getPosSize()[3] - vanillaControlsSize['EditTextSmallHeight']) # top dt.fill(*BLACK) dt.stroke(None) textWidth, textHeight = dt.textSize(glyphName) self._setTypeQualities(BLACK) dt.text(glyphName, (SPACING_COL_WIDTH / 2. - textWidth / 2., BASELINE_CORRECTION)) dt.translate(0, -vanillaControlsSize['EditTextSmallHeight']) # metrics for eachFont in self.fontsOrder: try: eachGlyph = eachFont[glyphName] except Exception, error: continue if eachGlyph == self.lineViewSelectedGlyph: color = RED else: color = BLACK # line over glyph width self._setBoxQualities() dt.line((0, vanillaControlsSize['EditTextSmallHeight']), (SPACING_COL_WIDTH, vanillaControlsSize['EditTextSmallHeight'])) widthString = '{:d}'.format(int(round(eachGlyph.width, 0))) textWidth, textHeight = dt.textSize(widthString) self._setTypeQualities(color) dt.text( widthString, (SPACING_COL_WIDTH / 2. - textWidth / 2., BASELINE_CORRECTION)) # line over sidebearings self._setBoxQualities() dt.line((0, 0), (SPACING_COL_WIDTH, 0)) dt.translate(0, -vanillaControlsSize['EditTextSmallHeight']) leftMarginString = '{:d}'.format( int(round(eachGlyph.leftMargin, 0))) textWidth, textHeight = dt.textSize(leftMarginString) self._setTypeQualities(color) dt.text( leftMarginString, (SPACING_COL_WIDTH / 4. - textWidth / 2., BASELINE_CORRECTION)) self._setBoxQualities() dt.line((SPACING_COL_WIDTH / 2., 0), (SPACING_COL_WIDTH / 2., vanillaControlsSize['EditTextSmallHeight'])) rightMarginString = '{:d}'.format( int(round(eachGlyph.rightMargin, 0))) textWidth, textHeight = dt.textSize(rightMarginString) self._setTypeQualities(color) dt.text(rightMarginString, (SPACING_COL_WIDTH * 3 / 4. - textWidth / 2., BASELINE_CORRECTION)) dt.translate(0, -vanillaControlsSize['EditTextSmallHeight'])
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()
def _canvas_draw_metrics(self): save() strokeWidth(1 / self.scale) stroke(0.8, 0.8, 0.8) line((0, 0), (self.width, 0)) line((0, self.metrics[0]), (self.width, self.metrics[0])) line((0, self.metrics[1]), (self.width, self.metrics[1])) line((0, self.metrics[2]), (self.width, self.metrics[2])) line((0, self.metrics[3]), (self.width, self.metrics[3])) line((0, self.metrics[3]), (0, self.metrics[0])) line((self.width, self.metrics[3]), (self.width, self.metrics[0])) restore()
def drawAxisPreview(self, glyph, color, scale, customColor, view=False, flatComponentColor=(.8, .6, 0, .7), drawSelectedElements=True): mjdt.save() index = None # loc = {} # if glyph.selectedSourceAxis: # loc = {glyph.selectedSourceAxis:1} # for i, atomicInstance in enumerate(glyph.preview()): for i, atomicInstance in enumerate( glyph.preview(forceRefresh=False, axisPreview=True)): # for i, atomicInstance in enumerate(glyph.previewGlyph): transformIntance = atomicInstance._transformation atomicInstance = atomicInstance.glyph mjdt.fill(*color) if drawSelectedElements and i in glyph.selectedElement: mjdt.save() mjdt.stroke(1, 0, 0, 1) mjdt.strokeWidth(1 * scale) tx = transformIntance['x'] + transformIntance['tcenterx'] ty = transformIntance['y'] + transformIntance['tcentery'] mjdt.line((tx - 5 * scale, ty), (tx + 5 * scale, ty)) mjdt.line((tx, ty - 5 * scale), (tx, ty + 5 * scale)) mjdt.stroke(None) mjdt.fill(1, 0, 0, 1) mjdt.fontSize(8 * scale) mjdt.textBox( f"{int(transformIntance['tcenterx'])} {int(transformIntance['tcentery'])}", ((tx - 30 * scale, ty - 30 * scale, 60 * scale, 20 * scale)), align="center") mjdt.restore() mjdt.fill(0, .8, .8, .5) # for c in atomicInstance: # if c.clockwise: # mjdt.stroke(1, 0, 0, 1) # mjdt.strokeWidth(2*scale) mjdt.save() # mjdt.drawGlyph(atomicInstance.getTransformedGlyph(round = self.RCJKI.roundToGrid)) mjdt.drawGlyph(atomicInstance) mjdt.restore() if customColor is None and view: if i != index: self.drawIndexOfElements(i, atomicInstance, view) if glyph.type == "characterGlyph": response = self.RCJKI.currentFont.mysqlGlyphData.get( glyph.name, False) try: if response: for dc in response["made_of"]: if dc["name"] != glyph._deepComponents[ i].name: continue char = getChar(dc["name"]) if not char: continue txt = "%s/%s\nused at %s%s" % ( len(dc["used_by"]), len(self.RCJKI.currentFont. deepComponents2Chars[char]), round( (len(dc["used_by"]) / len(self.RCJKI.currentFont. deepComponents2Chars[char])) * 100), "%") x, y = atomicInstance[0].points[ 0].x, atomicInstance[0].points[0].y mjdt.fill(1, 0, 1, 1) mjdt.fontSize(10 * scale) mjdt.text(txt, (x, y - 30 * scale)) except Exception as e: pass index = i if customColor is None: mjdt.fill(customColor) else: mjdt.fill(*customColor) mjdt.drawGlyph(glyph) mjdt.restore() for c in glyph.flatComponents: if self.RCJKI.currentFont[c.baseGlyph].type == "atomicElement": mjdt.drawGlyph( self.roundGlyph(self.RCJKI.currentFont[c.baseGlyph])) else: # self.RCJKI.currentFont[c.baseGlyph].preview.computeDeepComponents(update = False) self.drawAxisPreview(self.RCJKI.currentFont[c.baseGlyph], flatComponentColor, scale, customColor, view)
def _drawGrids(self, frameOrigin, frameSize, italicAngle, scalingFactor): if not italicAngle: italicAngle = 0 for eachGridDescription in reversed(self.gridsDB): gridColor = eachGridDescription['color'] isHorizontal = eachGridDescription['horizontal'] isVertical = eachGridDescription['vertical'] gridStep = eachGridDescription['step'] if isHorizontal is False and isVertical is False: continue if not gridStep: continue dt.save() dt.skew(-italicAngle, 0) dt.stroke(*gridColor) dt.strokeWidth(.5 * scalingFactor) dt.fill(None) if isVertical is True: # to the right (from 0) extraSlant = int( ceil(tan(radians(italicAngle)) * frameOrigin[1])) for eachX in range(0, frameOrigin[0] + frameSize[0] + extraSlant, gridStep): dt.line((eachX, frameOrigin[1] - GRID_TOLERANCE), (eachX, frameOrigin[1] + frameSize[1] + GRID_TOLERANCE)) # to the left (from 0) extraSlant = int( ceil( tan(radians(italicAngle)) * (frameSize[1] + frameOrigin[1]))) for eachX in [ i for i in range(frameOrigin[0] + extraSlant, 0) if i % gridStep == 0 ]: dt.line((eachX, frameOrigin[1] - GRID_TOLERANCE), (eachX, frameOrigin[1] + frameSize[1] + GRID_TOLERANCE)) if isHorizontal is True: # to the top (from baseline) for eachY in range(0, frameOrigin[1] + frameSize[1], gridStep): dt.line((frameOrigin[0] - GRID_TOLERANCE, eachY), (frameOrigin[0] + frameSize[0] + GRID_TOLERANCE, eachY)) # to the bottom (from baseline) for eachY in [ i for i in range(frameOrigin[1], 0) if i % gridStep == 0 ]: dt.line((frameOrigin[0] - GRID_TOLERANCE, eachY), (frameOrigin[0] + frameSize[0] + GRID_TOLERANCE, eachY)) dt.restore()