def draw(): for i in range(0, 100): drawBot.newDrawing() drawBot.newPage(1000, 1000) drawBot.radialGradient( (randint(1,500), randint(1,500)), # startPoint (randint(1,800), randint(1,800)), # endPoint [(randint(0,1), randint(0,1), randint(0,1)), (randint(0,1), randint(0,1), randint(0,1)), (randint(0,1), randint(0,1), randint(0,1))], # colors [randint(0,1), randint(0,1), randint(0,1)], # locations randint(0,1), # startRadius randint(0,800) # endRadius ) # draw a rectangle drawBot.rect(randint(0,100), randint(0,100), randint(0,1000), randint(0,1000)) # draw the path drawBot.drawPath() drawBot.blendMode("multiply") # set a color drawBot.rect(randint(1,10), randint(1,10), randint(1,100), randint(1,100)) # draw oval x, y, width, height drawBot.oval(randint(1,500), randint(1,500), randint(1,500), randint(1,500)) drawBot.oval(randint(1,500), randint(1,500), randint(1,500), randint(1,500)) drawBot.cmykFill(randint(0,1), randint(0,1), randint(0,1), randint(0,1)) # draw a rectangle drawBot.rect(randint(1,10), randint(1,10), randint(1,1000), randint(1,1000)) # set an other color drawBot.cmykFill(randint(0,1), randint(0,1), randint(0,1), randint(0,1)) # overlap a second rectangle drawBot.rect(randint(1,500), randint(1,500), randint(1,600), randint(1,600)) drawBot.saveImage(str(i) + '.png' ) drawBot.endDrawing() print(str(i) + ' done.')
def _drawGlyphMarker(self, axisName, mx, my, glyphName, fontSize, location, strokeW=2): # Middle circle fill(1) stroke(0.7) strokeWidth(strokeW) oval(mx - fontSize / 2 * self.R, my - fontSize / 2 * self.R, fontSize * self.R, fontSize * self.R) variableFont = getVariableFont(self.font, location) # Show axis name below circle marker? if self.showAxisNames and axisName is not None: fs = newFS(axisName, style=dict(font=variableFont.installedName, fontSize=fontSize / 4, textFill=0)) tw, th = textSize(fs) text(fs, (mx - tw / 2, my - fontSize / 2 * self.R - th * 2 / 3)) glyphPathScale = fontSize / self.font.info.unitsPerEm drawGlyphPath(variableFont, glyphName, mx, my - fontSize / 3, s=glyphPathScale, fillColor=0)
def drawArrow_drawBot(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.""" context = view.context # Get current context b = context.b 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 b.newPath() context.setFillColor(None) b.moveTo((xs, ys)) b.curveTo( (xb1, yb1), (xb2, yb2), ((ax1 + ax2) / 2, (ay1 + ay2) / 2)) # End in middle of arrow head. b.drawPath() # Draw the arrow head. b.newPath() context.setFillColor(c) context.setStrokeColor(None) b.moveTo((xt, yt)) b.lineTo((ax1, ay1)) b.lineTo((ax2, ay2)) b.closePath() b.drawPath() if endMarker: oval(xt - fms, yt - fms, 2 * fms, 2 * fms)
def _drawGlyphMarker(self, mx, my, glyphName, fontSize, location, strokeW=2): # Middle circle fill(1) stroke(0) strokeWidth(strokeW) oval(mx-fontSize*self.R, my-fontSize*self.R, fontSize*2*self.R, fontSize*2*self.R) glyphPathScale = fontSize/self.font.info.unitsPerEm drawGlyphPath(self.font.ttFont, glyphName, mx, my-fontSize/4, location, s=glyphPathScale, fillColor=0)
def _drawGlyphMarker(self, mx, my, glyphName, markerSize, location, strokeW=2): # Middle circle fill(1) stroke(0) strokeWidth(strokeW) oval(mx-markerSize/2, my-markerSize/2, markerSize, markerSize) glyphPathScale = markerSize/self.font.info.unitsPerEm*3/4 drawGlyphPath(self.font.ttFont, glyphName, mx, my-markerSize/4, location, s=glyphPathScale, fillColor=0)
def drawCircles(self): """ Draw circle at all points in pointsList """ # db.blendMode("multiply") db.fill(1, 0, 0, 1) db.stroke(None) for point in self.pointsList: x, y = point db.newPath() db.oval(x - self.width / 2, y - self.width / 2, self.width, self.width)
def circle(x, y, r, color='pink'): u""" >>> circle(100, 100, 5, color='green') """ stroke(None) # Draws on/offcurve dots. if color == 'pink': fill(1, 0, 1, 0.5) elif color == 'green': fill(0, 1, 0, 0.5) elif color == 'blue': fill(0, 0.5, 1, 0.5) oval(x - r, y - r, r*2, r*2) stroke(1)
def drawAnchor(self): r = self.anchorSize * 0.5 color = self.colorScheme.colorsRGB['anchor'] drawBot.save() drawBot.strokeWidth(self.anchorStrokeWidth) drawBot.stroke(*color) drawBot.fill(None) for char in self.txt: uni = ord(char) glyphName = UV2AGL.get(uni) glyph = self.font[glyphName] if len(glyph.anchors): for anchor in glyph.anchors: x, y = anchor.x, anchor.y drawBot.oval(x-r, y-r, r*2, r*2) drawBot.line((x-r, anchor.y), (x+r, anchor.y)) drawBot.line((anchor.x, y-r), (anchor.x, y+r)) drawBot.translate(glyph.width, 0) drawBot.restore()
def draw_circle_tunnel(size, margin, prob_black_lines): steps = (size // margin) >> 1 step = 1 / (2 * steps) change_color(BLACK) draw.rect(0, 0, RESOLUTION[0], RESOLUTION[1]) for i in range(steps): if random() > 0.5 * (1 - i / steps) + prob_black_lines: change_color(RED) else: change_color(BLACK) draw.oval(i * margin, i * margin, size - 2 * i * margin, size - 2 * i * margin)
def test_imageAntiAliasing(self): from testScripts import DrawBotTest expectedPath = os.path.join(testDataDir, "expected_imageAntiAliasing.png") drawBot.newDrawing() drawBot.size(100, 100) drawBot.fill(1, 0, 0) drawBot.oval(10, 10, 40, 80) drawBot.fill(0) drawBot.stroke(0) drawBot.line((-0.5, -0.5), (100.5, 100.5)) drawBot.line((0, 20.5), (100, 20.5)) drawBot.fontSize(20) drawBot.text("a", (62, 30)) with TempFile(suffix=".png") as tmp: drawBot.saveImage(tmp.path, antiAliasing=False) self.assertImageFilesEqual(tmp.path, expectedPath)
def drawElementOrigin(self, e, origin): px, py, _ = pointOffset(e.oPoint, origin) S = self.css('viewInfoOriginMarkerSize', 4) if self.showElementOrigin: # Draw origin of the element setFillColor( (0.5, 0.5, 0.5, 0.1) ) # Transparant fill, so we can see the marker on dark backgrounds. setStrokeColor(0, 0.25) oval(px - S, py - S, 2 * S, 2 * S) line((px - S, py), (px + S, py)) line((px, py - S), (px, py + S)) if self.showElementDimensions: fs = newFS(point2S(e.point3D), style=dict(font=self.css('viewInfoFont'), fontSize=self.css('viewInfoFontSize'), leading=self.css('viewInfoLeading'), textFill=0.1)) w, h = textSize(fs) text(fs, (px - w / 2, py + S * 1.5))
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 drawSegment(self): color = self.colorScheme.colorsRGB['segment'] r = self.bPointSize * 0.5 drawBot.save() drawBot.fontSize(self.captionSize) drawBot.font(self.captionFont) for char in self.txt: uni = ord(char) glyphName = UV2AGL.get(uni) # interpolate g1 = self.font[glyphName].getLayer('regular') g2 = self.font[glyphName].getLayer('bold') glyph = RGlyph() glyph.name = g1.name glyph.unicode = g1.unicode glyph.interpolate(self.interpolationFactor, g1, g2) # draw segment contours drawBot.stroke(*color) drawBot.strokeWidth(self.segmentStrokeWidth) drawBot.fill(None) B = drawBot.BezierPath() glyph.draw(B) drawBot.drawPath(B) # draw segment points drawBot.stroke(None) drawBot.fill(*color) for x, y in B.onCurvePoints: drawBot.oval(x - r, y - r, r * 2, r * 2) drawBot.translate(glyph.width, 0) drawBot.restore()
def drawPoint(self): r = self.pointSize * 0.5 color = self.colorScheme.colorsRGB['point'] drawBot.save() drawBot.fill(*color) for char in self.txt: uni = ord(char) glyphName = UV2AGL.get(uni) # interpolate g1 = self.font[glyphName].getLayer('regular') g2 = self.font[glyphName].getLayer('bold') glyph = RGlyph() glyph.name = g1.name glyph.unicode = g1.unicode glyph.interpolate(self.interpolationFactor, g1, g2) for c in glyph.contours: for pt in c.points: x, y = pt.x, pt.y drawBot.oval(x-r, y-r, r*2, r*2) drawBot.translate(glyph.width, 0) drawBot.restore()
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. self.drawFrame(p, view) # Draw optional frame or borders. if self.drawBefore is not None: # Call if defined self.drawBefore(self, p, view) setFillColor(self.css('fill', NO_COLOR)) setStrokeColor(self.css('stroke', NO_COLOR), self.css('strokeWidth')) oval(px, py, self.w, self.h) # If there are child elements, draw them over the text. self._drawElements(p, view) if self.drawAfter is not None: # Call if defined self.drawAfter(self, p, view) self._restoreScale() view.drawElementMetaInfo(self, origin)
def draw(txt="a", variations={}, caption=""): db.newPage(w * scale, h * scale) db.scale(scale) db.fill(*BACKCOL) db.stroke(None) db.rect(0, 0, w, h) fs = db.FormattedString(txt, font="Handjet-Regular", fontSize=4600, fontVariations=variations) path = db.BezierPath() path.text(fs, (w / 2, 1.58 * h), align="center") path_optim = path.copy() # remove overlaps when drawing the fill # but use the original contour when drawing the nodes path_optim.removeOverlap() path_optim.optimizePath() # draw the fill db.fill(*TEXTCOL) db.drawPath(path_optim) # draw nodes if path.contours: # drawing just the first contour is enough for s in path.contours[0]: for x, y in s: if (x, y) in path.onCurvePoints: db.fill(*NODECOL) db.stroke(*TEXTCOL) db.strokeWidth(1) db.oval(x - 4, y - 4, 8, 8) # draw caption fs = db.FormattedString(caption, font="AdapterMonoPE-Regular", fontSize=10, fill=TEXTCOL) if caption: db.text(fs, (w / 2, 40), align="center")
def drawBPoint(self): r1 = self.bPointSize * 0.5 r2 = self.pointSize * 0.5 color = self.colorScheme.colorsRGB['bPoint'] drawBot.save() for char in self.txt: uni = ord(char) glyphName = UV2AGL.get(uni) # interpolate g1 = self.font[glyphName].getLayer('regular') g2 = self.font[glyphName].getLayer('bold') glyph = RGlyph() glyph.name = g1.name glyph.unicode = g1.unicode glyph.interpolate(self.interpolationFactor, g1, g2) for c in glyph.contours: for pt in c.bPoints: x, y = pt.anchor xIn, yIn = pt.bcpIn xOut, yOut = pt.bcpOut drawBot.fill(*color) drawBot.stroke(None) drawBot.oval(x - r1, y - r1, r1 * 2, r1 * 2) if not self.layers['point']: drawBot.oval(x + xIn - r2, y + yIn - r2, r2 * 2, r2 * 2) drawBot.oval(x + xOut - r2, y + yOut - r2, r2 * 2, r2 * 2) drawBot.fill(None) drawBot.stroke(*color) drawBot.strokeWidth(5) drawBot.line((x, y), (x + xIn, y + yIn)) drawBot.line((x, y), (x + xOut, y + yOut)) drawBot.translate(glyph.width, 0) drawBot.restore()
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))
def makeInstance(self, axes, gname, glyph): nbAxes = maxNbAxes = len(axes) # steps = [1, 2] # maxNbAxes = max(steps) # for nbAxes in steps: speeds = [1 for i in range(nbAxes)] # LCM = self.ilcm(speeds) LCM = 60 # print(LCM) # while ((LCM < 600 or LCM > 1200) or self.checkEqual(speeds)): # speeds = [int(10/nbAxes + random.random()*60/nbAxes) for i in range(nbAxes)] # LCM = self.ilcm(speeds) # print(speeds, LCM, (LCM < 600 or LCM > 1200)) alpha = 2 * math.pi / maxNbAxes ld = [{'Axis': l, 'PreviewValue': 0} for l in axes] # glyph.preview.computeDeepComponentsPreview(ld) origineGlyph = RGlyph() for atomicInstance in glyph.preview(): atomicInstance = atomicInstance.glyph atomicInstance.draw(origineGlyph.getPen()) # origineGlyph = glyph.preview.variationPreview.copy() origineGlyph.name = "interpo" db.newDrawing() for k in range(nbAxes): start = time.time() ld = [{ 'Axis': l, 'PreviewValue': j == k } for j, l in enumerate(axes)] # glyph.preview.computeDeepComponentsPreview(ld) for g in range(LCM): H = 700 W = 700 db.newPage(W * 2.5, H) db.frameDuration(1 / 30) db.fill(1) db.rect(0, 0, W * 2.5, H) r = W / 3 ainc = 0 lines = [] rands = [] values = [] for i in range(nbAxes): path = db.BezierPath() path.moveTo((H / 2, W / 2)) line = (r * math.sin(ainc), r * math.cos(ainc)) path.lineTo((H / 2 + line[0], W / 2 + line[1])) dx = line[0] * .05 dy = line[1] * .05 path.moveTo((H / 2 + line[0] - dy, W / 2 + line[1] + dx)) path.lineTo((H / 2 + line[0] + dy, W / 2 + line[1] - dx)) db.stroke(.2) db.strokeWidth(1.5) db.fill(None) db.drawPath(path) ainc += alpha lines.append((line, axes[i]["sourceName"])) # v = getValueForAxeAtFrame(i, g, nbAxes, LCM, speeds[i]) # values.append(v) if i == k: rands.append([ 1000 * abs( math.sin(math.pi * (speeds[i] * c / LCM + speeds[i]))) for c in range(LCM) ]) else: rands.append([0 for c in range(LCM)]) db.fill(1) db.oval(H / 2 - H * .01, W / 2 - W * .01, H * .02, W * .02) patharea = db.BezierPath() patharea.moveTo((H / 2, W / 2)) patharea.lineTo((H / 2 + lines[0][0][0] * rands[0][g] / 1000, W / 2 + lines[0][0][1] * rands[0][g] / 1000)) db.fill(0, 0, 0, .1) db.stroke(None) for c, (line, lineName) in enumerate(lines): patharea.lineTo((H / 2 + line[0] * rands[c][g] / 1000, W / 2 + line[1] * rands[c][g] / 1000)) patharea.lineTo((H / 2 + lines[0][0][0] * rands[0][g] / 1000, W / 2 + lines[0][0][1] * rands[0][g] / 1000)) patharea.lineTo((H / 2, W / 2)) db.drawPath(patharea) for c, (line, lineName) in enumerate(lines): db.fill(0) #1-rands[c] db.stroke(.2) db.strokeWidth(1) db.oval(H / 2 + line[0] * rands[c][g] / 1000 - 4.5, W / 2 + line[1] * rands[c][g] / 1000 - 4.5, 9, 9) db.fill(.2) ftxt = db.FormattedString(txt=lineName, font="GrtskZetta-Light", fontSize=14, align="center") db.textBox(ftxt, (H / 2 + line[0] * 1.3 - 30, W / 2 + line[1] * 1.3 - 10, 60, 20)) ######### db.save() # ld = [] # for j, l in enumerate(axes): # ld.append({'Axis': l, 'PreviewValue':rands[j][g]/1000}) # # d = {l:rands[j][g]/1000 for (j, l) in enumerate(axes)} # # glyph = interpolation(NewFont().newGlyph('temp'), ufo[gname], layersInfo = d) # # glyph = self.RCJKI.currentFont.get(gname) # glyph.preview.computeDeepComponentsPreview(ld) ######### # print(glyph) db.translate(W * 1.3, H * .15) db.scale(.7 * H / 1000) db.stroke(.5) db.fill(None) db.rect(0, 0, 1000, 1000) db.fill(0) db.stroke(None) db.save() db.translate(0, 120) ratioX = ratioY = (rands[k][g]) / 1000 resultGlyph = RGlyph() locations = {} for e in ld: locations[e["Axis"]["sourceName"]] = e["PreviewValue"] for c in glyph.preview(locations): c = c.glyph c.draw(resultGlyph.getPen()) interpoGlyph = interpolation.interpol_glyph_glyph_ratioX_ratioY_scaleX_scaleY( origineGlyph, resultGlyph, ratioX, ratioY, 1, 1, NewFont(showUI=False)) db.drawGlyph(interpoGlyph) # for aes in glyph.preview: # # axis2layerName = {axisName:layerName for axisName, layerName in self.RCJKI.currentFont[aes['name']].lib['robocjk.atomicElement.glyphVariations'].items()} # # lInfos = {axis2layerName[axisName]:v for axisName, v in aes['coord'].items()} # # print(ae['coord']) # for ae in aes.values(): # glyph = ae[0] # print(glyph) # db.save() # self._drawGlyph(glyph) # db.restore() db.restore() db.restore() caption = db.FormattedString(txt='%s-axis' % (nbAxes), font="GrtskMega-Medium", fontSize=14, align="left") db.textBox(caption, (10, 10, W - 20, 20)) stop = time.time() print(stop - start, "seconde for axis") pdfData = db.pdfImage()
db.newPage(CANVAS, CANVAS) db.frameDuration(duration) db.stroke(None) if len(particles) < n_particles: p = Particle(*position, random.uniform(0, 1) * 8 + 5, math.pi / 2 + (random.uniform(0, 1) * 0.2 - 0.1), 0.1) p.radius = random.uniform(0, 1) * 5 + 5 particles.append(p) for i, p in enumerate(particles): p.update() db.fill(i * 5 / CANVAS, (n_particles - i) * 5 / CANVAS, 0.7, 1) db.oval(p.position.x - p.radius, p.position.y - p.radius, p.radius * 2, p.radius * 2) if p.position.y - p.radius < 0: if frame < total_frames * 2 / 3: p.position.set_x(position[0]) p.position.set_y(position[1]) p.velocity.set_length(random.uniform(0, 1) * 8 + 5) p.velocity.set_angle(math.pi / 2 + (random.uniform(0, 1) * 0.2 - 0.1)) elif frame == total_frames - 1: particles.clear() else: particles.remove(p) # Save image save_dir = os.path.expanduser('~/Downloads')
import drawBot drawBot.size(200, 200) for i in range(14): f = i / 14.0 drawBot.fill(1-f, 1 - f, 0) drawBot.oval(10, 10, 50, 50) drawBot.translate(10, 10)
# -*- coding: UTF-8 -*- # ----------------------------------------------------------------------------- # # P A G E B O T N A N O # # Copyright (c) 2020+ Buro Petr van Blokland + Claudia Mens # www.pagebot.io # Licensed under MIT conditions # import sys import drawBot if __name__ == "__main__": sys.path.insert( 0, "..") # So we can import pagebotnano003 without installing. from pagebotnano_000 import export W = H = 600 # Create a new page canvas of 1000 x 1000 px drawBot.newPage(W, H) # Fill page with white background drawBot.fill(1) drawBot.rect(0, 0, W, H) # Set fill color to red (r, g, b) drawBot.fill(0.2, 0.2, 1) # Draw a black square (x, y, width, height) drawBot.oval(50, 50, 500, 500) # Export as png file in created _export folder (that does not sync in Github) export('_export/0011-ColorCircle.png')
def makeTestDrawing(self): drawBot.newDrawing() drawBot.newPage(500, 500) drawBot.oval(100, 100, 300, 300)
def draw_point(point: tuple) -> None: draw.fill(random_lighter(), random_lighter(), random_lighter(), 1) draw.strokeWidth(0) draw.oval(point[0] - POINT_SIZE / 2, point[1] - POINT_SIZE / 2, POINT_SIZE, POINT_SIZE)
import drawBot drawBot.size(200, 200) for i in range(14): f = i / 14.0 drawBot.fill(1 - f, 1 - f, 0) drawBot.oval(10, 10, 50, 50) drawBot.translate(10, 10)
def drawArrow(self, e, xs, ys, xt, yt, onText=1, startMarker=False, endMarker=False, fms=None, fmf=None, fill=None, stroke=None, strokeWidth=None): u"""Draw curved arrow marker between the two points. TODO: Add drawing of real arrow-heads, rotated in the right direction.""" if fms is None: fms = self.css('viewFlowMarkerSize') if fmf is None: fmf or self.css('viewFlowCurvatureFactor') if stroke is None: if onText == 1: stroke = self.css('viewFlowConnectionStroke2', NO_COLOR) else: stroke = self.css('viewFlowConnectionStroke1', NO_COLOR) if strokeWidth is None: strokeWidth = self.css('viewFlowConnectionStrokeWidth', 0.5) setStrokeColor(stroke, strokeWidth) if startMarker: if fill is None: fill = self.css('viewFlowMarkerFill', NO_COLOR) setFillColor(fill) 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(stroke) setStrokeColor(None) moveTo((xt, yt)) lineTo((ax1, ay1)) lineTo((ax2, ay2)) closePath() drawPath() if endMarker: setFillColor(self.css('viewFlowMarkerFill', NO_COLOR)) oval(xt - fms, yt - fms, 2 * fms, 2 * fms)
def drawCircle(sf, a): x, y, wid = a.x, a.y, a.width d.fill(None) d.stroke(1, 0, 0, 0.5) d.strokeWidth(annoThickness / sf) d.oval(x - wid, y - wid, wid * 2, wid * 2)
import drawBot drawBot.size(100, 100) drawBot.fill(.5, .5) drawBot.oval(0, 0, 100, 100) for x in range(10): for y in range(10): drawBot.fill(x / 10, 1 - y / 10, y / 10, y / 20 + .5) drawBot.rect(x*10, y*10, 10, 10)
def new(layer, totalPages): d.newPage(paperSize) w, h = d.width(), d.height() m = l.associatedFontMaster() d.font(".SF Compact Text", 10) d.text("%s %s" % (layer.parent.name, layer.name), (margin, margin)) d.text("%s/%s" % (d.pageCount(), totalPages - 1), (w - margin, margin), align="right") ma, md, mx, mc = m.ascender, m.descender, m.xHeight, m.capHeight zones = [az.position + az.size for az in m.alignmentZones] + [ma, md] boundsTop, boundsBtm = max(zones), min(zones) sf = float(h - margin * 3) / (boundsTop - boundsBtm) #scalefactor d.scale(sf) wNew = w / sf # scaled paper size d.translate((margin / sf), -boundsBtm + (margin * 2) / sf) # drawing metrics lines d.stroke(0, 0, 0, 0.5) d.strokeWidth(0.5 / sf) d.fill(None) lw = layer.width d.rect(0, md, lw, ma - md) d.line((0, mc), (lw, mc)) # x-height d.line((0, mx), (lw, mx)) # x-height d.line((0, 0), (lw, 0)) # baseline # alignment zones d.stroke(None) d.fill(0.7, 0.3, 0, 0.1) for az in m.alignmentZones: d.rect(0, az.position, lw, az.size) # drawing nodes offcurves = [] smooths = [] sharps = [] for p in layer.paths: smooths += [n for n in p.nodes if n.connection == GSSMOOTH] sharps += [ n for n in p.nodes if n.type != OFFCURVE and n.connection != GSSMOOTH ] offcurves += [n for n in p.nodes if n.type == OFFCURVE] d.stroke(0, 0, 0, 0.2) for n in p.nodes: if n.type == OFFCURVE: if n.nextNode.type != OFFCURVE: d.line((n.x, n.y), (n.nextNode.x, n.nextNode.y)) elif n.prevNode.type != OFFCURVE: d.line((n.prevNode.x, n.prevNode.y), (n.x, n.y)) d.stroke(None) nodeSize = 3 / sf hf = nodeSize / 2 #half d.fill(0, 0, 1, 0.5) for n in sharps: d.rect(n.x - hf, n.y - hf, nodeSize, nodeSize) d.fill(0, 0.7, 0, 0.5) for n in smooths: d.oval(n.x - hf, n.y - hf, nodeSize, nodeSize) d.fill(0, 0, 0, 0.2) for n in offcurves: d.oval(n.x - hf, n.y - hf, nodeSize, nodeSize) # drawing anchors d.stroke(None) d.fill(0.7, 0.25, 0.0, 0.75) nodeSize = 4 / sf hf = nodeSize * 0.7 for a in layer.anchors: # print(a, (ma, md, mc, mx, 0)) if a.y in (ma, md, mc, mx, 0): d.polygon((a.x - hf, a.y), (a.x, a.y - hf), (a.x + hf, a.y), (a.x, a.y + hf), close=True) else: d.oval(a.x - hf, a.y - hf, nodeSize, nodeSize) # glyph outline d.fill(0, 0, 0, 0.3) d.stroke(0, 0, 0, 1) d.drawPath(layer.completeBezierPath) return sf, ma, md
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))
# www.pagebot.io # Licensed under MIT conditions # import sys import drawBot if __name__ == "__main__": sys.path.insert( 0, "..") # So we can import pagebotnano003 without installing. from pagebotnano_000 import export W = H = 600 M = 50 SW = 200 # Square size # Create a new page canvas of 1000 x 1000 px drawBot.newPage(W, H) # Fill page with white background drawBot.fill(1) drawBot.rect(0, 0, W, H) # Set fill color to red (r, g, b) drawBot.fill(0, 0.5, 0) # Draw a black square (x, y, width, height) drawBot.oval(M, M, SW, SW) drawBot.oval(M, W - M - SW, SW, SW) drawBot.oval(W - M - SW, H - M - SW, SW, SW) drawBot.oval(W - M - SW, M, SW, SW) # Export as png file in created _export folder (that does not sync in Github) export('_export/0012-CirclesPar.png')