def export(self, path): """Draw a page and export the document into the _export folder. Note that in this version, we still generate the document page just before it is exported. Not Page instances are stored in the Document yet. >>> doc = Document() >>> doc.export('_export/Document-export.jpg') # Exporting the JPG """ # Make sure that the _export folder exists, as it does not standard # dowload from Github, nor it is committed to Github. if path.startswith(EXPORT_DIR) and not os.path.exists(EXPORT_DIR): os.mkdir(EXPORT_DIR) # Now let DrawBot do its work, creating the page canvas, filling it # black, add the title text and then saving it. drawBot.newPage(self.w, self.h) # For now to have something visible, draw a gray rectangle filling the page. drawBot.fill(0.2) # Set fill color at 20% dark gray. drawBot.rect(0, 0, self.w, self.h) # Draw the rectangle for the entire page. # Create a Formatted String for white text with the specified font/fontSize. fs = drawBot.FormattedString('My specimen', font='Georgia', fontSize=80, fill=1) # Draw the FormattedString on this fixed position: x from left and y from top. drawBot.text(fs, (50, self.h - 100)) # Save the drawn DrawBot page into the _export folder, using `path` as file name. # File in the _export folder are ignored by Git, so they don't upload. drawBot.saveImage(path)
def drawContour(self): color = self.colorScheme.colorsRGB['contour'] 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 contours drawBot.stroke(*color) drawBot.strokeWidth(self.contourStrokeWidth) drawBot.fill(None) B = drawBot.BezierPath() for contour in glyph.contours: contour.draw(B) drawBot.drawPath(B) # done glyph drawBot.translate(glyph.width, 0) drawBot.restore()
def drawCurrentGlyph(self): db.newDrawing() db.translate(100, 100) db.scale(0.8) db.fill(None) db.stroke(0.2, 0.3, 1) db.rect(0, 0, 1000, 1000) db.stroke(None) db.translate( 0, 120 ) # Baseline at 120 from the bottom of the Ideographic Em Square db.fill(0, 1, 0, 0.3) db.stroke(0) db.lineJoin("round") dcSelection = set(self.w.deepComponentList.getSelection()) aeSelection = set(self.w.atomicElementList.getSelection()) if self._currentGlyphOutline is not None: drawOutline(self._currentGlyphOutline) if self._currentGlyphComponents: for dcIndex, (dcName, atomicElements) in enumerate( self._currentGlyphComponents ): for aeIndex, (aeName, atomicOutline) in enumerate(atomicElements): if dcIndex in dcSelection: if aeIndex in aeSelection: db.fill(1, 0, 0, 0.3) else: db.fill(0, 0, 1, 0.3) else: db.fill(0, 0.3) drawOutline(atomicOutline) db.endDrawing()
def makeFlash(s, w, h, px, py, color1=None, color2=None, flashSpeed=4): if color1 is None: r1, g1, b1 = 1, 0, 0 else: r1, g1, b1 = color1 if color2 is None: r2, g2, b2 = 0.2, 0, 0 else: r2, g2, b2 = color2 for n in range(flashSpeed): newPage(w, h) fill(0) rect(0, 0, w, h) drawString(s, px, py, 'PropSingleBold', (r1, g1, b1, 0.2)) drawString(s, px, py, 'PropSingleMedium', (r1, g1, b1, 0.5)) if HIGHLIGHT: drawString(s, px, py, 'PropSingle', (r1 * 0.9, g1 * 0.9, b1 * 0.9, 1)) drawString(s, px - 1, py + 1, 'PropSingleLight', (r1, g1, b1, 1)) else: drawString(s, px, py, 'PropSingle', (r1, g1, b1, 1)) for n in range(flashSpeed): newPage(w, h) fill(0) rect(0, 0, w, h) drawString(s, px, py, 'PropSingleBold', (r2, g2, b2, 0.2)) drawString(s, px, py, 'PropSingleMedium', (r2, g2, b2, 0.5)) if HIGHLIGHT: drawString(s, px, py, 'PropSingle', (r2 * 0.9, g2 * 0.9, b2 * 0.9, 1)) drawString(s, px - 1, py + 1, 'PropSingleLight', (r2, g2, b2, 1)) else: drawString(s, px, py, 'PropSingle', (r2, g2, b2, 1))
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 setFillColor(c, fs=None, cmyk=False): u"""Set the color for global or the color of the formatted string.""" if c is NO_COLOR: pass # Color is undefined, do nothing. elif c is None or isinstance( c, (float, long, int)): # Because None is a valid value. if cmyk: if fs is None: cmykFill(c) else: fs.cmykFill(c) else: if fs is None: fill(c) else: fs.fill(c) elif isinstance(c, (list, tuple)) and len(c) in (3, 4): if cmyk: if fs is None: cmykFill(*c) else: fs.cmykFill(*c) else: if fs is None: fill(*c) else: fs.fill(*c) else: raise ValueError('Error in color format "%s"' % repr(c))
def drawLetters(self): xFactor = self.xHeightTarget / xHeightCurrent descenderTarget = descender * xFactor pageWidth = drawBot.width() pageHeight = drawBot.height() if self.descBox == 1: drawBot.stroke(1,0,0, 1) drawBot.line((margin, pageHeight-margin-self.xHeightTarget+descenderTarget),(pageWidth-dpi, pageHeight-margin-self.xHeightTarget+descenderTarget)) elif self.descBox == 0: drawBot.stroke(0,0,0,0) drawBot.fill(0,0,0, 1) drawBot.stroke(0,0,0, 0) drawBot.translate(margin, pageHeight-margin-self.xHeightTarget) drawBot.scale(xFactor) for g in self.text: pen = CocoaPen(f) f[g].draw(pen) drawBot.drawPath(pen.path) drawBot.translate(f[g].width, 0) pdf = drawBot.pdfImage() self.w.canvas.setPDFDocument(pdf)
def makeTestICNSDrawing(self, formats): drawBot.newDrawing() for i, size in enumerate(formats): drawBot.newPage(size, size) f = i / (len(formats) + 1) drawBot.fill(f, f, 1 - f) drawBot.rect(0, 0, size, size)
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 fold(startX, startY, height, currentPage): colorOffset = int(startX / canvasWidth * 300) horizontalColorOffset = startX / canvasWidth verticalColorOffset = startY / canvasHeight color = (220 - horizontalColorOffset * 50, 30 + horizontalColorOffset * 30, 90 + horizontalColorOffset * 40) color = breathingColor(currentPage, *color) gradientSteps = 80 for x in range(0, gradientSteps): colorOffset -= colorOffset + x / gradientSteps * 50 # if(x % 2 == 0): # db.fill(*rgb(color[0]+ colorOffset, color[1] + colorOffset, color[2] + colorOffset)) # else: # db.fill(1,1,1) db.fill(*rgb(color[0] + colorOffset, color[1] + colorOffset, color[2] + colorOffset)) db.polygon( (startX + ((height * 0.3) * x / gradientSteps), startY + height * 0.3 * x / gradientSteps), (startX + height * 2 - ((height * 0.2) * x / gradientSteps), startY + ((height * 0.3) * x / gradientSteps)), (startX + height * 1.5, startY + height * 0.8), (startX - height / 2 + (height * 0.3 * x / gradientSteps), startY + height - 0.1 * (height * 0.3) * x / gradientSteps), )
def draw(self): self.xFactor = self.targetXheight / currentXheight drawBot.newDrawing() drawBot.newPage("LetterLandscape") pageWidth = drawBot.width() drawBot.fill(0, 0, 0, 0.5) drawBot.stroke(0, 0, 0, 1) drawBot.rect(.5 * dpi, .5 * dpi, pageWidth - (1 * dpi), self.targetXheight) drawBot.translate(0.5 * dpi, .5 * dpi) drawBot.scale(self.xFactor) for g in self.text: pen = CocoaPen(f) f[g].draw(pen) drawBot.drawPath(pen.path) drawBot.translate(f[g].width, 0) pdf = drawBot.pdfImage() # set the pdf data in the canvas self.w.canvas.setPDFDocument(pdf)
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. save() sh = 1.0 * self.h / self.ih transform((1, 0, 0, 1, px, py)) scale(sh) if self.pathFilter is not None: self.pathFilter(self, self.glyph.path) if self.css('fill') != NO_COLOR or self.css('stroke') != NO_COLOR: setFillColor(self.css('fill')) print(self.css('strokeWidth') or 1), sh setStrokeColor(self.css('stroke', NO_COLOR), (self.css('strokeWidth') or 20)) fill(0) stroke(1, 0, 0) strokeWidth(20) drawPath(self.glyph.path) restore() # If there are child elements, draw them over the polygon. self._drawElements(p, view) # Draw optional bounding box. #self.drawFrame(origin, view) self._restoreScale() view.drawElementMetaInfo( self, origin) # Depends on css flag 'showElementInfo'
def __enter__(self): db.save() for k, v in self.style.items(): db.fill(None) db.stroke(None) db.strokeWidth(1) getattr(db, k)(*v) return self
def drawPageFrame(self, page, origin): u"""Draw the page frame if the the flag is on and if there ie padding enough to show other meta info. Otherwise the padding is truncated to 0: no use to draw the frame.""" if self.showPageFrame: # Different from base View, no check on padding. fill(None) stroke(0.5) strokeWidth(0.5) rect(origin[0], origin[1], page.w, page.h)
def draw_sierpinski(side, limit=10): c_x, c_y = RESOLUTION[0] / 2, RESOLUTION[1] / 2 adj = RESOLUTION[1] / 7.5 desp = sqrt(3 / 4) * side draw.fill(BLACK[0], BLACK[1], BLACK[2], BLACK[3]) draw.rect(0, 0, RESOLUTION[0], RESOLUTION[1]) draw_sierpinski_r(c_x - side / 2, c_y + desp / 2 - adj, c_x + side / 2, c_y + desp / 2 - adj, c_x, c_y - desp / 2 - adj, limit)
def fill(self, color): if color: if isinstance(color, Gradient): self.gradient(color) elif isinstance(color, Color): db.fill(color.r, color.g, color.b, color.a) else: db.fill(None)
def db_fill(color): if color: if isinstance(color, Gradient): db_gradient(color) elif isinstance(color, Color): db.fill(color.r, color.g, color.b, color.a) else: db.fill(None)
def page_with_lines(width, height, x_lines, y_lines, mult, dur, color=False): drawBot.newPage(width*mult, height*mult) drawBot.frameDuration(dur) drawBot.fill(1, 1, 1) drawBot.rect(0, 0, width*mult, height*mult) if color: draw_colors(x_lines, y_lines, width, height, mult) draw_lines(x_lines, y_lines, mult)
def typeQualities(isBold=False): fill(*BLACK) stroke(None) openTypeFeatures(tnum=True) if not isBold: font('.SFNS-Regular', 9) else: font('.SFNS-Bold', 9)
def draw_spiral(size: float): points = generate_points(size) draw.fill(0, 0, 0, 1) draw.rect(0, 0, size, size) for i in range(len(points) - 1): draw_square(points[i], points[i + 1])
def drawGlyph(self): color = self.colorScheme.colorsRGB['glyph'] 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) # contours drawBot.fill(*color) B = drawBot.BezierPath() for contour in glyph.contours: contour.draw(B) drawBot.drawPath(B) # advance width if self.glyphWidthDraw: drawBot.save() drawBot.strokeWidth(self.glyphWidthStrokeWidth) drawBot.stroke(*color) drawBot.line((0, self.yBottom), (0, self.yTop)) drawBot.restore() # glyph data if self.glyphDataDraw: h = self.captionSize * 1.5 m = 40 w = glyph.width - m * 2 drawBot.save() drawBot.stroke(None) drawBot.fill(*color) y = self.yTop - h drawBot.textBox(glyph.name, (m, y, w, h)) drawBot.textBox(str(glyph.unicode), (m, y, w, h), align='right') y = self.yBottom drawBot.textBox(str(int(glyph.width)), (m, y, w, h), align='center') drawBot.restore() # done glyph drawBot.translate(glyph.width, 0) # last margin if self.glyphWidthDraw: drawBot.strokeWidth(self.glyphWidthStrokeWidth) drawBot.stroke(*color) drawBot.line((0, self.yBottom), (0, self.yTop)) # done drawBot.restore()
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 fill(self, isFill, color): if not isFill: ctx.fill(None) return if type(color) is str and color.startswith('#'): color = hexToRGB(color) ctx.fill(*color)
def draw(self, page, x, y): fillColor = self.style.get('fill') if fillColor is not None: setFillColor(fillColor) setStrokColor(None) stroke(0.8) strokeWidth(0.5) fill(None) rect(x, y, self.w, self.h) if len(self.dimensions) == 1: raise ValueError('Not supporting 1 axis now') if len(self.dimensions) > 2: raise ValueError('Not supporting >2 axis now') axisNames = sorted(self.dimensions.keys()) axisX = axisNames[0] sizeX = self.dimensions[axisX] axisY = axisNames[1] sizeY = self.dimensions[axisY] stepX = self.w / (sizeX + 1) stepY = self.h / (sizeY + 1) """Add more parametric layout behavior here.""" RANGE = 1000 for indexX in range(sizeX + 1): for indexY in range(sizeY + 1): ox = 30 oy = 25 px = ox + x + indexX * stepX py = oy + y + indexY * stepY self.location[axisX] = indexX * RANGE / sizeX self.location[axisY] = indexY * RANGE / sizeY glyphPathScale = self.fontSize / self.font.info.unitsPerEm drawGlyphPath(self.font.ttFont, self.glyphNames[0], px, py, self.location, s=glyphPathScale, fillColor=(0, 0, 0)) fs = FormattedString('%s %d\n%s %d' % (axisX, indexX * RANGE / sizeX, axisY, indexY * RANGE / sizeY), fontSize=6, fill=0) w, h = fs.size() page.text( fs, px - stepX / 4, py - 16) # Bit of hack, we need the width of the glyph here. fs = FormattedString('Other axes: %s' % self.location, fontSize=6, fill=0) w, h = fs.size() page.text(fs, x, y - 16)
def backgroundSquares(canvasWidth, canvasHeight): squareSize = 50 buffer = 0.2 base_color = hls_to_rgb(random.random(), 0.5, 1) for x in range(0, canvasWidth, squareSize): for y in range(0, canvasHeight, squareSize): db.fill(base_color[0] + (random.random() * buffer), base_color[1] + (random.random() * buffer), base_color[2] + (random.random() * buffer), 0.3) db.rect(x, y, squareSize, squareSize)
def drawProof(proofSet, postscriptFontName): txt = '\n'.join(proofSet) while txt: newPage(PAGE_FORMAT) fill(0) if fileName == './txt/paragraph.txt': txt = drawTwoColumnsLayout(txt, postscriptFontName) else: txt = drawOneColumnLayout(txt, postscriptFontName) drawHeaderFooter(postscriptFontName, fileName)
def makeTestAnimation(self, numFrames=25, pageWidth=500, pageHeight=500): randomSeed(0) drawBot.newDrawing() for i in range(numFrames): drawBot.newPage(pageWidth, pageHeight) drawBot.frameDuration(1/25) drawBot.fill(1) drawBot.rect(0, 0, pageWidth, pageHeight) drawBot.fill(0) drawBot.rect(random.randint(0, 100), random.randint(0, 100), 400, 400)
def drawDesignFrame(): for e in self.designFrameViewer.elements: glyph, color, type = e if type == 'stroke': db.stroke(*color) db.fill(None) else: db.stroke(None) db.fill(*color) db.drawGlyph(glyph)
def drawPageFrame(self, page, origin): u"""Draw the page frame if the the flag is on and if there ie padding enough to show other meta info. Otherwise the padding is truncated to 0: no use to draw the frame.""" if self.showPageFrame and \ self.pl > self.MIN_PADDING and self.pr > self.MIN_PADDING and \ self.pt > self.MIN_PADDING and self.pb > self.MIN_PADDING: fill(None) stroke(0, 0, 1) strokeWidth(0.5) rect(origin[0], origin[1], page.w, page.h)
import drawBot drawBot.size(200, 200) drawBot.text("hello world", (10, 10)) drawBot.fill(1, 0, 0) drawBot.text("foo bar", (10, 30)) drawBot.fill(1, 0, 1) drawBot.stroke(0, 1, 0) drawBot.strokeWidth(4) drawBot.font("Times", 50) drawBot.text("foo bar", (10, 50)) drawBot.fill(None) drawBot.stroke(0, 1, 0) drawBot.strokeWidth(1) drawBot.line((0, 50), (drawBot.width(), 50)) drawBot.stroke(None) drawBot.fill(0, 1, 1) drawBot.fontSize(20) drawBot.text("foo bar", (drawBot.width()*.5, 100), align="right") drawBot.text("foo bar", (drawBot.width()*.5, 120), align="center") drawBot.text("foo bar", (drawBot.width()*.5, 140), align="left")
import drawBot drawBot.size(200, 200) drawBot.stroke(0) drawBot.strokeWidth(10) drawBot.fill(None) drawBot.line((40, 40), (40, 160)) drawBot.line((100, 40), (160, 160))
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()
import drawBot drawBot.size(200, 200) drawBot.stroke(0, 0, 1) drawBot.strokeWidth(5) with drawBot.savedState(): drawBot.fill(1, 0, 0) drawBot.translate(100, 100) drawBot.rect(0, 0, 100, 100) drawBot.rect(0, 0, 100, 100) with drawBot.savedState(): drawBot.fill(0, 1, 0) drawBot.translate(100, 0) drawBot.rect(0, 0, 100, 100) drawBot.rect(0, 100, 100, 100)
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()
import drawBot drawBot.newDrawing() drawBot.size(200, 100) p = drawBot.BezierPath() p.oval(5, 5, 70, 70) p.rect(25, 25, 70, 70) drawBot.fill(0, 0.3) drawBot.stroke(0) drawBot.drawPath(p) p.removeOverlap() drawBot.translate(100, 0) drawBot.drawPath(p)
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)
import drawBot drawBot.size(200, 200) drawBot.stroke(0) drawBot.strokeWidth(10) drawBot.fill(1, 0.3, 0) drawBot.polygon((40, 40), (40, 160)) drawBot.polygon((60, 40), (60, 160), (130, 160)) drawBot.polygon((100, 40), (160, 160), (160, 40), close=False)
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)
import drawBot drawBot.newDrawing() drawBot.size(200, 200) testData = [ ((25, 25, 50, 50), "rotate", (20,), (25, 25)), ((125, 25, 50, 50), "skew", (10, 10), (175, 25)), ((25, 125, 50, 50), "scale", (1.2, 1.4), (25, 175)), ] for r, op, args, center in testData: drawBot.fill(0) bez = drawBot.BezierPath() bez.rect(*r) drawBot.drawPath(bez) with drawBot.savedState(): drawBot.fill(1, 0, 0, 0.5) bez = drawBot.BezierPath() bez.rect(*r) getattr(bez, op)(*args, center=center) drawBot.drawPath(bez)