def _lineTo(self, pt): x0, y0 = self._getCurrentPoint() x, y = pt db.fill(None) db.stroke(r.random(), r.random(), r.random(), 1) db.strokeWidth(self.width) # db.newPath() db.moveTo((x0, y0)) db.lineTo(pt) db.drawPath() # Or use line() instead of newPath, moveTo, lineTo, drawPath combo # line((x0, y0), (x, y)) # Use rectangle below... still not sure why one over the other # angle = self.getAngle((x0, y0), (x, y)) # distance = self.getDistance((x0, y0), (x, y)) # fill(0, 0, 1, 1) # with savedState(): # rotate(angle, (x0, y0)) # rect(x0, y0 - self.width / 2, distance, self.width) self.pointsList.append(pt)
def drawMissingElementRect(self, e, origin): u"""When designing templates and pages, this will draw a filled rectangle on the element bounding box (if self.css('missingElementFill' is defined) and a cross, indicating that this element has missing content (as in unused image frames). Only draw if self.css('showGrid') is True.""" if self.showMissingElementRect: p = pointOffset(e.point, origin) p = e._applyOrigin(p) p = e._applyScale(p) px, py, _ = e._applyAlignment(p) # Ignore z-axis for now. self.setShadow() sMissingElementFill = self.css('viewMissingElementFill', NO_COLOR) if sMissingElementFill is not NO_COLOR: setFillColor(sMissingElementFill) setStrokeColor(None) rect(px, py, self.w, self.h) # Draw crossed rectangle. setFillColor(None) setStrokeColor(0, 0.5) rect(px, py, self.w, self.h) newPath() moveTo((px, py)) lineTo((px + self.w, py + self.h)) moveTo((px + self.w, py)) lineTo((px, py + self.h)) drawPath() self.resetShadow() e._restoreScale()
def _curveToOne(self, pt1, pt2, pt3): x0, y0 = self._getCurrentPoint() db.fill(None) db.stroke(r.random(), r.random(), r.random(), 1) db.strokeWidth(self.width) # db.newPath() db.moveTo((x0, y0)) db.curveTo(pt1, pt2, pt3) db.drawPath() self.pointsList.append(pt3)
def draw(self, origin, view): p = pointOffset(self.oPoint, origin) p = self._applyScale(p) px, py, _ = p = self._applyAlignment(p) # Ignore z-axis for now. setStrokeColor(self.css('stroke', NO_COLOR), self.css('strokeWidth')) newPath() moveTo((px, py)) lineTo((px + self.w, py + self.h)) drawPath() # If there are child elements, draw them over the line. self._drawElements(p, view) self._restoreScale() view.drawElementMetaInfo(self, origin)
def drawArrow(e, view, xs, ys, xt, yt, onText=1, startMarker=False, endMarker=False): u"""Draw curved arrow marker between the two points. TODO: Add drawing of real arrow-heads, rotated in the right direction.""" fms = e.css('flowMarkerSize') fmf = e.css('flowCurvatureFactor') if onText == 1: c = e.css('flowConnectionStroke2', NO_COLOR) else: c = e.css('flowConnectionStroke1', NO_COLOR) setStrokeColor(c, e.css('flowConnectionStrokeWidth')) if startMarker: setFillColor(e.css('flowMarkerFill', NO_COLOR)) oval(xs - fms, ys - fms, 2 * fms, 2 * fms) xm = (xt + xs)/2 ym = (yt + ys)/2 xb1 = xm + onText * (yt - ys) * fmf yb1 = ym - onText * (xt - xs) * fmf xb2 = xm - onText * (yt - ys) * fmf yb2 = ym + onText * (xt - xs) * fmf # Arrow head position arrowSize = 12 arrowAngle = 0.4 angle = atan2(xt-xb2, yt-yb2) hookedAngle = radians(degrees(angle)-90) ax1 = xt - cos(hookedAngle+arrowAngle) * arrowSize ay1 = yt + sin(hookedAngle+arrowAngle) * arrowSize ax2 = xt - cos(hookedAngle-arrowAngle) * arrowSize ay2 = yt + sin(hookedAngle-arrowAngle) * arrowSize newPath() setFillColor(None) moveTo((xs, ys)) curveTo((xb1, yb1), (xb2, yb2), ((ax1+ax2)/2, (ay1+ay2)/2)) # End in middle of arrow head. drawPath() # Draw the arrow head. newPath() setFillColor(c) setStrokeColor(None) moveTo((xt, yt)) lineTo((ax1, ay1)) lineTo((ax2, ay2)) closePath() drawPath() if endMarker: oval(xt - fms, yt - fms, 2 * fms, 2 * fms)
def drawGrid(self, e, origin): u"""Draw grid of lines and/or rectangles if colors are set in the style. Normally px and py will be 0, but it's possible to give them a fixed offset.""" # Drawing the grid as squares. if not self.showGrid: return #if not self.showGridColumns or not self.showGrid: # return p = pointOffset(e.oPoint, origin) p = self._applyScale(p) px, py, _ = e._applyAlignment(p) # Ignore z-axis for now. sGridFill = e.css('viewGridFill', NO_COLOR) gutterW = e.gw # Gutter width gutterH = e.gh # Gutter height columnWidth = e.cw # Column width columnHeight = e.ch # Column height padL = e.pl # Padding left padT = e.pt # Padding top padR = e.pr # padding right padB = e.pb # padding bottom padW = e.pw # Padding width padH = e.ph # Padding height w = e.w h = e.h if e.isRight(): ox = px + padR else: ox = px + padL oy = py + padB if self.showGrid and self.css('viewGridStroke', NO_COLOR) is not NO_COLOR: setFillColor(None) setStrokeColor(self.css('viewGridStroke', NO_COLOR), self.css('viewGridStrokeWidth')) newPath() for cx, cw in e.getGridColumns(): moveTo((ox + cx, oy)) lineTo((ox + cx, oy + padH)) moveTo((ox + cx + cw, oy)) lineTo((ox + cx + cw, oy + padH)) for cy, ch in e.getGridRows(): moveTo((ox, oy + cy)) lineTo((ox + padW, oy + cy)) moveTo((ox, oy + cy + ch)) lineTo((ox + padW, oy + cy + ch)) drawPath() #text(fs+repr(index), (ox + M * 0.3, oy + M / 4)) """
def drawRegistrationMark(origin, cmSize, cmStrokeWidth, vertical): u"""Draw registration mark as position x, y.""" x, y = origin if vertical: dx = cmSize / 2 dy = cmSize else: dx = cmSize dy = cmSize / 2 fill(None) cmykStroke(1, 1, 1, 1) strokeWidth(cmStrokeWidth) newPath() # Registration circle oval(x - cmSize / 4, y - cmSize / 4, cmSize / 2, cmSize / 2) # Registration cross, in length of direction. moveTo((x - dx, y)) # Horizontal line. lineTo((x + dx, y)) moveTo((x, y + dy)) # Vertical line. lineTo((x, y - dy)) drawPath()
def drawBaselineGrid(self, e, origin): u"""Draw baseline grid if line color is set in the style. TODO: Make fixed values part of calculation or part of grid style. Normally px and py will be 0, but it's possible to give them a fixed offset.""" if not self.showBaselineGrid: return p = pointOffset(self.oPoint, origin) p = self._applyScale(p) px, py, _ = self._applyAlignment(p) # Ignore z-axis for now. M = 16 startY = e.css('baselineGridStart') if startY is None: startY = e.pt # Otherwise use the top padding as start Y. oy = e.h - startY #- py line = 0 # Format of line numbers. # TODO: DrawBot align and fill don't work properly now. fs = newFS( '', self, dict(font=e.css('fallbackFont', 'Verdana'), xTextAlign=RIGHT, fontSize=M / 2, stroke=None, textFill=e.css('gridStroke'))) while oy > e.pb or 0: setFillColor(None) setStrokeColor(e.css('baselineGridStroke', NO_COLOR), e.css('gridStrokeWidth')) newPath() moveTo((px + e.pl, py + oy)) lineTo((px + e.w - e.pr, py + oy)) drawPath() text(fs + repr(line), (px + e.pl - 2, py + oy - e.pl * 0.6)) text(fs + repr(line), (px + e.w - e.pr - 8, py + oy - e.pr * 0.6)) line += 1 # Increment line index. oy -= e.css('baselineGrid' ) # Next vertical line position of baseline grid.
def drawPageCropMarks(self, e, origin): u"""If the show flag is set, then draw the cropmarks or page frame.""" if self.showPageCropMarks: x, y, _ = point3D(origin) # Ignore z-axus for now. w, h = e.w, e.h folds = self.css('folds') bleed = self.css('bleed') / 2 # 1/2 overlap with image bleed cmSize = min(self.css('viewCropMarkSize', 32), self.pl) cmStrokeWidth = self.css('viewCropMarkStrokeWidth') fill(None) cmykStroke(1, 1, 1, 1) strokeWidth(cmStrokeWidth) newPath() # Bottom left moveTo((x - bleed, y)) lineTo((x - cmSize, y)) moveTo((x, y - bleed)) lineTo((x, y - cmSize)) # Bottom right moveTo((x + w + bleed, y)) lineTo((x + w + cmSize, y)) moveTo((x + w, y - bleed)) lineTo((x + w, y - cmSize)) # Top left moveTo((x - bleed, y + h)) lineTo((x - cmSize, y + h)) moveTo((x, y + h + bleed)) lineTo((x, y + h + cmSize)) # Top right moveTo((x + w + bleed, y + h)) lineTo((x + w + cmSize, y + h)) moveTo((x + w, y + h + bleed)) lineTo((x + w, y + h + cmSize)) # Any fold lines to draw? if folds is not None: for fx, fy in folds: if fx is not None: moveTo((x + fx, y - bleed)) lineTo((x + fx, y - cmSize)) moveTo((x + fx, y + h + bleed)) lineTo((x + fx, y + h + cmSize)) if fy is not None: moveTo((x - bleed, y + fy)) lineTo((x - cmSize, y + fy)) moveTo((x + w + bleed, y + fy)) lineTo((x + w + cmSize, y + fy)) drawPath()
def draw(self, page, x, y): u"""Draw the circle info-graphic, showing most info about the variation font as can be interpreted from the file.""" fill(0.9) stroke(None) mx = x + self.w / 2 my = y + self.h / 2 # Gray circle that defines the area of oval(x, y, self.w, self.h) # Draw axis spikes first, so we can cover them by the circle markers. axes = self.font.axes markerSize = self.style.get('fontSize', self.DEFAULT_FONT_SIZE) # Calculate sorted relative angle pairs. xAngles = {} # X-ref, key is angle, value is list of axisName for axisName in axes: angle = globals()[axisName] if not angle in xAngles: # Ignore overlapping xAngles[angle] = axisName #print xAngles sortedAngles = sorted(xAngles) anglePairs = [] a1 = None for a2 in sortedAngles: if a1 is not None: if abs(a2 - a1) < CONNECT: # Max angle to connect anglePairs.append((a1, a2)) a1 = a2 # Draw name of the font fill(0) text( FormattedString(self.font.info.familyName, font=self.style['labelFont'], fontSize=self.style['titleFontSize']), (x - markerSize / 2, y + self.h + markerSize / 4)) # Draw spokes fill(None) stroke(0.7) strokeWidth(1) # Gray on full circle newPath() for axisName, angle in self.angles.items(): markerX, markerY = self._angle2XY(angle, self.w / 2) moveTo((mx - markerX, my - markerY)) lineTo((mx + markerX, my + markerY)) drawPath() # Black on range of axis. stroke(0) newPath() for axisName, angle in self.angles.items(): minValue, defaultValue, maxValue = axes[axisName] markerX, markerY = self._angle2XY(angle, self.w / 2) if minValue < defaultValue: moveTo((mx, my)) lineTo((mx - markerX, my - markerY)) if defaultValue < maxValue: moveTo((mx, my)) lineTo((mx + markerX, my + markerY)) drawPath() # Pair combinations if anglePairs: newPath() for a1, a2 in anglePairs: markerX1, markerY1 = self._angle2XY(a1, self.w / 2) markerX2, markerY2 = self._angle2XY(a2, self.w / 2) moveTo((mx + markerX1, my + markerY1)) lineTo((mx + markerX2, my + markerY2)) moveTo((mx + markerX1 * INTERPOLATION, my + markerY1 * INTERPOLATION)) lineTo((mx + markerX2 * INTERPOLATION, my + markerY2 * INTERPOLATION)) stroke(0, 0, 1) fill(None) drawPath() # Draw default glyph marker in middle. glyphName = self.glyphNames[0] defaultLocation = {} self._drawGlyphMarker(mx, my, glyphName, markerSize, defaultLocation) # http://stackoverflow.com/questions/1734745/how-to-create-circle-with-bézier-curves # Draw DeltaLocation circles. for axisName, (minValue, defaultValue, maxValue) in axes.items(): angle = self.angles[axisName] if defaultValue < maxValue: # Outside maxValue location = {axisName: maxValue} markerX, markerY = self._angle2XY(angle, self.w / 2) self._drawGlyphMarker(mx + markerX, my + markerY, glyphName, markerSize, location) # Interpolated DeltaLocation circles. location = { axisName: defaultValue + (maxValue - defaultValue) * INTERPOLATION } markerX, markerY = self._angle2XY(angle, self.w / 4) self._drawGlyphMarker(mx + markerX * INTERPOLATION * 2, my + markerY * INTERPOLATION * 2, glyphName, markerSize, location) if minValue < defaultValue: # Outside minValue. location = {axisName: minValue} markerX, markerY = self._angle2XY(angle, self.w / 2) self._drawGlyphMarker(mx - markerX, my - markerY, glyphName, markerSize, location) # Interpolated DeltaLocation circles. location = { axisName: minValue + (defaultValue - minValue) * INTERPOLATION } markerX, markerY = self._angle2XY(angle, self.w / 4) self._drawGlyphMarker(mx - markerX * 2 * INTERPOLATION, my - markerY * 2 * INTERPOLATION, glyphName, markerSize, location) # If there are any pairs, draw the interpolation between them #if anglePairs: # for a1, a2 in anglePairs: # axis1 = # Draw axis names and DeltaLocation values if self.showAxisNames: for axisName, (minValue, defaultValue, maxValue) in axes.items(): if minValue < defaultValue: angle = self.angles[axisName] valueFontSize = self.style.get('valueFontSize', 12) axisNameFontSize = self.style.get('axisNameFontSize', 12) markerX, markerY = self._angle2XY(angle, self.w / 2) fs = FormattedString( makeAxisName(axisName), font=self.style.get('labelFont', 'Verdana'), fontSize=axisNameFontSize, fill=self.style.get('axisNameColor', 0)) tw, th = textSize(fs) fill(0.7, 0.7, 0.7, 0.6) stroke(None) rect(mx - markerX - tw / 2 - 4, my - markerY - axisNameFontSize / 2 - th * 1.5 - 4, tw + 8, th) text(fs, (mx - markerX - tw / 2, my - markerY - axisNameFontSize / 2 - th * 1.5)) # DeltaLocation master value if 0 < minValue < 10: sMinValue = '%0.2f' % minValue else: sMinValue = ` int(round(minValue)) ` fs = FormattedString( sMinValue, font=self.style.get('labelFont', 'Verdana'), fontSize=valueFontSize, fill=self.style.get('axisValueColor', 0)) tw, th = textSize(fs) fill(0.7, 0.7, 0.7, 0.6) stroke(None) rect(mx - markerX - tw / 2 - 4, my - markerY + valueFontSize / 2 + th * 1.5 - 4, tw + 8, th) text(fs, (mx - markerX - tw / 2, my - markerY + valueFontSize / 2 + th * 1.5)) # DeltaLocation value interpolationValue = minValue + (defaultValue - minValue) * INTERPOLATION if 0 < interpolationValue < 10: sValue = '%0.2f' % interpolationValue else: sValue = ` int(round(interpolationValue)) ` fs = FormattedString( sValue, font=self.style.get('labelFont', 'Verdana'), fontSize=valueFontSize, fill=self.style.get('axisValueColor', 0)) tw, th = textSize(fs) fill(0.7, 0.7, 0.7, 0.6) stroke(None) rect( mx - markerX * INTERPOLATION - tw / 2 - 4, my - markerY * INTERPOLATION + valueFontSize / 2 + th * 1.5 - 4, tw + 8, th) text(fs, (mx - markerX * INTERPOLATION - tw / 2, my - markerY * INTERPOLATION + valueFontSize / 2 + th * 1.5)) # DeltaLocation value if 0 < defaultValue < 10: sValue = '%0.2f' % defaultValue else: sValue = ` int(round(defaultValue)) ` fs = FormattedString( sValue, font=self.style.get('labelFont', 'Verdana'), fontSize=valueFontSize, fill=self.style.get('axisValueColor', 0)) tw, th = textSize(fs) fill(0.7, 0.7, 0.7, 0.6) stroke(None) minM = 0.15 rect(mx - markerX * minM - tw / 2 - 4, my - markerY * minM - 8, tw + 8, th) text(fs, (mx - markerX * minM - tw / 2, my - markerY * minM - 4)) if defaultValue < maxValue: angle = self.angles[axisName] valueFontSize = self.style.get('valueFontSize', 12) axisNameFontSize = self.style.get('axisNameFontSize', 12) markerX, markerY = self._angle2XY(angle, self.w / 2) fs = FormattedString( makeAxisName(axisName), font=self.style.get('labelFont', 'Verdana'), fontSize=axisNameFontSize, fill=self.style.get('axisNameColor', 0)) tw, th = textSize(fs) fill(0.7, 0.7, 0.7, 0.6) stroke(None) rect(mx + markerX - tw / 2 - 4, my + markerY - axisNameFontSize / 2 - th * 1.5 - 4, tw + 8, th) text(fs, (mx + markerX - tw / 2, my + markerY - axisNameFontSize / 2 - th * 1.5)) # DeltaLocation master value if 0 < maxValue < 10: sMaxValue = '%0.2f' % maxValue else: sMaxValue = ` int(round(maxValue)) ` fs = FormattedString( sMaxValue, font=self.style.get('labelFont', 'Verdana'), fontSize=valueFontSize, fill=self.style.get('axisValueColor', 0)) tw, th = textSize(fs) fill(0.7, 0.7, 0.7, 0.6) stroke(None) rect(mx + markerX - tw / 2 - 4, my + markerY + valueFontSize / 2 + th * 1.5 - 4, tw + 8, th) text(fs, (mx + markerX - tw / 2, my + markerY + valueFontSize / 2 + th * 1.5)) # DeltaLocation value interpolationValue = defaultValue + ( maxValue - defaultValue) * INTERPOLATION if 0 < interpolationValue < 10: sValue = '%0.2f' % interpolationValue else: sValue = ` int(round(interpolationValue)) ` fs = FormattedString( sValue, font=self.style.get('labelFont', 'Verdana'), fontSize=valueFontSize, fill=self.style.get('axisValueColor', 0)) tw, th = textSize(fs) fill(0.7, 0.7, 0.7, 0.6) stroke(None) rect( mx + markerX * INTERPOLATION - tw / 2 - 4, my + markerY * INTERPOLATION + valueFontSize / 2 + th * 1.5 - 4, tw + 8, th) text(fs, (mx + markerX * INTERPOLATION - tw / 2, my + markerY * INTERPOLATION + valueFontSize / 2 + th * 1.5)) # DeltaLocation value if defaultValue < 10: sValue = '%0.2f' % defaultValue else: sValue = ` int(round(defaultValue)) ` fs = FormattedString( sValue, font=self.style.get('labelFont', 'Verdana'), fontSize=valueFontSize, fill=self.style.get('axisValueColor', 0)) tw, th = textSize(fs) fill(0.7, 0.7, 0.7, 0.6) stroke(None) minM = 0.15 rect(mx + markerX * minM - tw / 2 - 4, my + markerY * minM - 8, tw + 8, th) text(fs, (mx + markerX * minM - tw / 2, my + markerY * minM - 4))
import drawBot drawBot.size(200, 200) drawBot.newPath() drawBot.moveTo((20, 20)) drawBot.lineTo((20, 100)) drawBot.lineTo((100, 100)) drawBot.lineTo((100, 180)) drawBot.curveTo((150, 180), (180, 150), (180, 100)) drawBot.lineTo((180, 20)) drawBot.fill(1, 0, 0) drawBot.stroke(0) drawBot.strokeWidth(10) drawBot.drawPath() drawBot.closePath() drawBot.fill(None) drawBot.stroke(1) drawBot.translate(40, 15) drawBot.scale(0.7) drawBot.lineCap("round") drawBot.lineJoin("round") drawBot.drawPath()
def _drawFontCircle(self, px, py): fontSize = self.css('fontSize', self.DEFAULT_FONT_SIZE) markerSize = fontSize * self.R # Calculate the max square size w = self.w - markerSize h = self.h - markerSize fill(0.9) stroke(None) mx = px + self.pw / 2 my = py + self.ph / 2 # Gray circle that defines the area of the axis extremes. oval(px + markerSize / 2, py + markerSize / 2, w, h) # Draw axis spikes first, so we can cover them by the circle markers. axes = self.font.axes # Draw default glyph circle marker in middle. glyphName = self.glyphNames[0] varLocation = getVarLocation( self.font, self.location) # Show neutral, unless a location is requested self._drawGlyphMarker(None, mx, my, glyphName, fontSize, varLocation, strokeW=3) # Draw angle = 0 for axisName, (minValue, defaultValue, maxValue) in axes.items(): # Draw needles, depending on the axis values and the status of self.location if self.draw3D: needleStart = 0.40 # Just enough overlap with edge of neutral circle marker else: needleStart = 2 / 3 # Start at edge of neutral circle marker rStart = fontSize rEnd = w / 2 if self.location is not None and axisName in self.location: rEnd = rStart + (rEnd - rStart) * self.location[axisName] rStart = fontSize * needleStart #print rStart, rEnd startX, startY = self._angle2XY(angle, rStart) endX, endY = self._angle2XY(angle, rEnd) if (w / 2 + rStart) - rEnd - fontSize > fontSize: startX1, startY1 = self._angle2XY(angle - 180, fontSize / 2) endX1, endY1 = self._angle2XY(angle - 180, (w / 2 + rStart) - rEnd - fontSize) else: startX1 = None stroke(None) fill(0.3) oval(mx + startX - 2, my + startY - 2, 4, 4) fill(None) stroke(0) strokeWidth(1) newPath() moveTo((mx + startX, my + startY)) lineTo((mx + endX, my + endY)) if startX1 is not None: moveTo((mx + startX1, my + startY1)) lineTo((mx + endX1, my + endY1)) drawPath() # Show the glyph shape as it is at the max location of the axis. location = {axisName: maxValue} self._drawGlyphMarker(axisName, mx + endX, my + endY, glyphName, fontSize, location) angle += 360 / len(axes)
def _closePath(self): db.moveTo(self.pointsList[0]) db.lineTo(self.pointsList[-1]) db.drawPath() self.drawCircles()
import drawBot drawBot.size(200, 200) drawBot.newPath() drawBot.moveTo((20, 20)) drawBot.lineTo((20, 100)) drawBot.lineTo((100, 100)) drawBot.lineTo((100, 180)) drawBot.curveTo((150, 180), (180, 150), (180, 100)) drawBot.lineTo((180, 50)) drawBot.qCurveTo((180, 20), (150, 20)) drawBot.fill(1, 0, 0) drawBot.stroke(0) drawBot.strokeWidth(10) drawBot.drawPath() drawBot.closePath() drawBot.fill(None) drawBot.stroke(1) drawBot.translate(40, 15) drawBot.scale(0.7) drawBot.lineCap("round") drawBot.lineJoin("round") drawBot.drawPath()
def drawCropMarks(origin, w, h, bleed, cmSize, cmStrokeWidth, folds=None): u"""If the show flag is set, then draw the cropmarks or page frame.""" x, y, _ = point3D(origin) # Ignore z-axus for now. fill(None) cmykStroke(1, 1, 1, 1) strokeWidth(cmStrokeWidth) newPath() # Bottom left moveTo((x - bleed, y)) lineTo((x - cmSize, y)) moveTo((x, y - bleed)) lineTo((x, y - cmSize)) # Bottom right moveTo((x + w + bleed, y)) lineTo((x + w + cmSize, y)) moveTo((x + w, y - bleed)) lineTo((x + w, y - cmSize)) # Top left moveTo((x - bleed, y + h)) lineTo((x - cmSize, y + h)) moveTo((x, y + h + bleed)) lineTo((x, y + h + cmSize)) # Top right moveTo((x + w + bleed, y + h)) lineTo((x + w + cmSize, y + h)) moveTo((x + w, y + h + bleed)) lineTo((x + w, y + h + cmSize)) # Any fold lines to draw? if folds is not None: for fx, fy in folds: if fx is not None: moveTo((x + fx, y - bleed)) lineTo((x + fx, y - cmSize)) moveTo((x + fx, y + h + bleed)) lineTo((x + fx, y + h + cmSize)) if fy is not None: moveTo((x - bleed, y + fy)) lineTo((x - cmSize, y + fy)) moveTo((x + w + bleed, y + fy)) lineTo((x + w + cmSize, y + fy)) drawPath()
import drawBot drawBot.size(200, 200) drawBot.newPath() drawBot.moveTo((20, 20)) drawBot.lineTo((20, 100)) drawBot.lineTo((100, 100)) drawBot.lineTo((100, 180)) drawBot.curveTo((150, 180), (180, 150), (180, 100)) drawBot.lineTo((180, 20)) drawBot.closePath() drawBot.moveTo((40, 40)) drawBot.lineTo((160, 40)) drawBot.curveTo((160, 65), (145, 80), (120, 80)) drawBot.lineTo((40, 80)) drawBot.closePath() drawBot.fill(0.5, 0, 0) drawBot.stroke(None) drawBot.strokeWidth(10) drawBot.drawPath()
def draw(self, page, x, y): u"""Draw the circle info-graphic, showing most info about the variation font as can be interpreted from the file.""" fill(0.9) stroke(None) mx = x + self.w / 2 my = y + self.h / 2 # Gray circle that defines the area of oval(x, y, self.w, self.h) # Draw axis spikes first, so we can cover them by the circle markers. axes = self.font.axes fontSize = self.style.get('fontSize', self.DEFAULT_FONT_SIZE) # Draw name of the font fill(0) text( FormattedString(self.font.info.familyName, font=self.style['labelFont'], fontSize=self.style['axisNameFontSize']), (x - fontSize / 2, y + self.h + fontSize / 2)) # Draw spokes fill(None) stroke(0) strokeWidth(1) newPath() for axisName, angle in self.angles.items(): markerX, markerY = self._angle2XY(angle, self.w / 2) moveTo((mx, my)) lineTo((mx + markerX, my + markerY)) drawPath() # Draw default glyph marker in middle. glyphName = self.glyphNames[0] defaultLocation = {} self._drawGlyphMarker(mx, my, glyphName, fontSize, defaultLocation, strokeW=3) # Draw DeltaLocation circles. for axisName, (minValue, defaultValue, maxValue) in axes.items(): angle = self.angles[axisName] # Outside maxValue location = {axisName: maxValue} markerX, markerY = self._angle2XY(angle, self.w / 2) self._drawGlyphMarker(mx + markerX, my + markerY, glyphName, fontSize / 2, location) # Interpolated DeltaLocation circles. location = { axisName: minValue + (maxValue - minValue) * INTERPOLATION } markerX, markerY = self._angle2XY(angle, self.w / 4) self._drawGlyphMarker(mx + markerX * INTERPOLATION * 2, my + markerY * INTERPOLATION * 2, glyphName, fontSize / 2, location) # Draw axis names and DeltaLocation values if self.showAxisNames: for axisName, (minValue, defaultValue, maxValue) in axes.items(): angle = self.angles[axisName] location = {axisName: maxValue} valueFontSize = self.style.get('valueFontSize', 12) axisNameFontSize = self.style.get('axisNameFontSize', 12) markerX, markerY = self._angle2XY(angle, self.w / 2) fs = FormattedString(makeAxisName(axisName), font=self.style.get( 'labelFont', 'Verdana'), fontSize=axisNameFontSize, fill=self.style.get('axisNameColor', 0)) tw, th = textSize(fs) fill(0.7, 0.7, 0.7, 0.6) stroke(None) rect(mx + markerX - tw / 2 - 4, my + markerY - axisNameFontSize / 2 - th * 1.5 - 4, tw + 8, th) text(fs, (mx + markerX - tw / 2, my + markerY - axisNameFontSize / 2 - th * 1.5)) # DeltaLocation master value if maxValue < 10: sMaxValue = '%0.2f' % maxValue else: sMaxValue = ` int(round(maxValue)) ` fs = FormattedString(sMaxValue, font=self.style.get( 'labelFont', 'Verdana'), fontSize=valueFontSize, fill=self.style.get('axisValueColor', 0)) tw, th = textSize(fs) fill(0.7, 0.7, 0.7, 0.6) stroke(None) rect(mx + markerX - tw / 2 - 4, my + markerY + valueFontSize / 2 + th * 1.5 - 4, tw + 8, th) text(fs, (mx + markerX - tw / 2, my + markerY + valueFontSize / 2 + th * 1.5)) # DeltaLocation value interpolationValue = minValue + (maxValue - minValue) * INTERPOLATION if interpolationValue < 10: sValue = '%0.2f' % interpolationValue else: sValue = ` int(round(interpolationValue)) ` fs = FormattedString(sValue, font=self.style.get( 'labelFont', 'Verdana'), fontSize=valueFontSize, fill=self.style.get('axisValueColor', 0)) tw, th = textSize(fs) fill(0.7, 0.7, 0.7, 0.6) stroke(None) rect( mx + markerX * INTERPOLATION - tw / 2 - 4, my + markerY * INTERPOLATION + valueFontSize / 2 + th * 1.5 - 4, tw + 8, th) text(fs, (mx + markerX * INTERPOLATION - tw / 2, my + markerY * INTERPOLATION + valueFontSize / 2 + th * 1.5)) # DeltaLocation value if minValue < 10: sValue = '%0.2f' % minValue else: sValue = ` int(round(minValue)) ` fs = FormattedString(sValue, font=self.style.get( 'labelFont', 'Verdana'), fontSize=valueFontSize, fill=self.style.get('axisValueColor', 0)) tw, th = textSize(fs) fill(0.7, 0.7, 0.7, 0.6) stroke(None) minM = 0.2 rect(mx + markerX * minM - tw / 2 - 4, my + markerY * minM + th * 0.5 - 4, tw + 8, th) text(fs, (mx + markerX * minM - tw / 2, my + markerY * minM + th * 0.5))
def move(self, point): ctx.moveTo((point.x, point.y))