def _extractColor(self, layer): fillColor = noColor if layer.style.fills: fill = layer.style.fills[0] if fill.isEnabled: # In Sketch colors can be defined, and still be disabled. sketchColor = fill.color fillColor = color(r=sketchColor.red, g=sketchColor.green, b=sketchColor.blue, a=sketchColor.alpha) strokeColor = noColor strokeWidth = 0 sketchBorders = layer.style.borders if sketchBorders: # TODO: Extract element border info here too sketchBorder = sketchBorders[0] if sketchBorder.isEnabled: # In Sketch colors can be defined, and still be disabled. sketchColor = sketchBorder.color strokeColor = color(r=sketchColor.red, g=sketchColor.green, b=sketchColor.blue, a=sketchColor.alpha) strokeWidth = pt(sketchBorder.thickness) return fillColor, strokeColor, strokeWidth
def fill(self, c): """Sets the global fill color. >>> from pagebot.toolbox.color import color >>> from pagebot.contexts.drawbotcontext import DrawBotContext >>> context = DrawBotContext() >>> context.fill(color(0.5)) # Same as setFillColor >>> context.fill(color('red')) >>> context.fill(inheritColor) >>> context.fill(noColor) >>> context.fill(0.5) """ if c is None: c = noColor elif isinstance(c, (tuple, list)): c = color(*c) elif isinstance(c, (int, float)): c = color(c) msg = 'InDesignContext.fill: %s should be of type Color' assert isinstance(c, Color), (msg % c) if c is inheritColor: # Keep color setting as it is. pass elif c is noColor: self.b.fill(None) # Set color to no-color elif c.isCmyk: cyan, magenta, yellow, key = to100(color.cmyk) self.b.cmykFill(cyan, magenta, yellow, key, alpha=color.a) else: r, g, b = to255(c.rgb) self.b.fill(r, g, b, alpha=c.a)
def gradient(self, gradient, origin, w, h): """Define the gradient call to match the size of element e., Gradient position is from the origin of the page, so we need the current origin of e.""" b = self.b start = origin[0] + gradient.start[0] * w, origin[1] + gradient.start[1] * h end = origin[0] + gradient.end[0] * w, origin[1] + gradient.end[1] * h if gradient.linear: if (gradient.colors[0]).isCmyk: colors = [color(c).cmyk for c in gradient.colors] b.cmykLinearGradient(startPoint=upt(start), endPoint=upt(end), colors=colors, locations=gradient.locations) else: colors = [color(c).rgb for c in gradient.colors] b.linearGradient(startPoint=upt(start), endPoint=upt(end), colors=colors, locations=gradient.locations) else: # Gradient must be radial. if color(gradient.colors[0]).isCmyk: colors = [color(c).cmyk for c in gradient.colors] b.cmykRadialGradient(startPoint=upt(start), endPoint=upt(end), colors=colors, locations=gradient.locations, startRadius=gradient.startRadius, endRadius=gradient.endRadius) else: colors = [color(c).rgb for c in gradient.colors] b.radialGradient(startPoint=upt(start), endPoint=upt(end), colors=colors, locations=gradient.locations, startRadius=gradient.startRadius, endRadius=gradient.endRadius)
def run(): # Make BabelString, bs = context.newString('Book Cover', style=dict(font='Georgia', fontSize=pt(50))) print('Text size book cover: (%f, %f)' % context.textSize(bs)) # Empty string. bs = context.newString('') # Contains a DrawBot FormattedString. aa = bs.s print(type(aa)) aa.append("123", font="Helvetica", fontSize=100, fill=color(1, 0, 0)) aa.fontSize(80) aa.append("Book Cover", font="Georgia", fill=color(0, 1, 0)) print(aa) print('Text size: (%f, %f)' % textSize(aa)) print('Ascender: %f' % aa.fontAscender()) print('Descender: %f' % aa.fontDescender()) print('Difference: %f' % (aa.fontAscender() - aa.fontDescender())) context.stroke(blackColor) context.fill(noColor) w, h = textSize(aa) context.rect(pt(100), pt(100), pt(w), pt(h)) context.fill(blackColor) context.fontSize(pt(80)) context.text(bs, (100, 100))
def pathFilter(e, glyph, view): r = pt(24) grid = 30 path = context.getGlyphPath(glyph) for x in range(0, int(e.w) * 4, grid): for y in range(0, int(e.h) * 2, grid): # Use the glyph to query for color at this position. if e.glyph is not None: if context.onBlack((x, y), path): context.fill( color(random(), random(), random())) # Color as one tuple, in context API context.oval(pt(x - r / 4), pt(y - r / 4), r / 2, r / 2) else: context.fill(color( 0, 1, 0)) # Color as one tuple, in context API context.oval(pt(x - r / 8), pt(y - r / 8), r / 4, r / 4) if context.onBlack((x, y), path) and (not context.onBlack( (x + grid, y), path) or not context.onBlack( (x + grid, y - grid), path)): context.fill(0) context.oval(pt(x - r / 2), pt(y - r / 2), r, r) context.stroke((1, 0, 0)) context.fill(noColor) context.drawPath(path) context.stroke((0, 1, 0), 5) context.rect(e.x, e.y, e.w, e.h)
def useBabelStrings(): for contextId, context in ( ('DrawBot', DrawBotContext()), ('Flat', FlatContext())): W, H = pt(1000, 300) M = pt(100) EXPORT_PATH = '_export/UseBabelStrings-%s.pdf' % contextId # Create a page and set y on top margin. context.newPage(W, H) y = H - M cs = context.newString('Context: %s' % contextId, style={'textFill': color(0, 0, 1), 'fontSize': 36}) context.text(cs, (100, y)) y -= 20 # Create formatted string, with default settings of font, fontSize and textFill color bs = context.newString('This is a formatted BabelString') print(bs.__class__.__name__) context.text(bs, (100, y)) # FIXME: solve for Flat. # Add string with formatting style dict bs += context.newString('\nAdd an other string with color/size format', style=dict(textFill=color(1, 0, 0), fontSize=20, leading=em(1.4))) print(bs) y -= 50 context.text(bs, (100, y)) context.saveImage(EXPORT_PATH)
class FantasyTheme(BaseTheme): NAME = 'Fantasy Red' BASE_COLORS = dict( base2=color(1, 0, 0.2), # Filling 2 base colors as source for range. dark3=color(1, 0, 0.5), # Overwriting single slot in the matrix. logo=color(spot=300) )
def _extractFill(self, layer): if hasattr(layer, 'style') and hasattr(layer.style, 'fills') and layer.style.fills: sketchColor = layer.style.fills[0].color return color(r=sketchColor.red, g=sketchColor.green, b=sketchColor.blue) return color(0.5)
def textBox(self, sOrBs, r): """Draw the sOrBs text string, can be a str or BabelString, including a DrawBot FormattedString in rectangle r.""" if not isinstance(sOrBs, str): sOrBs = sOrBs.s # Assume here is's a BabelString with a FormattedString inside. x, y, w, h = r t = self._drawing.text(sOrBs, insert=point2D(upt(x, y)), stroke=color(self._stroke).css, stroke_width=upt(self._strokeWidth), fill=color(self._fill).css, font_size=upt(self._fontSize), font_family=self._font) self._drawing.add(t)
def setShadow(self, eShadow): """Set the DrawBot graphics state for shadow if all parameters are set.""" if eShadow is not None and eShadow.offset is not None: if eShadow.color.isCmyk: self.b.shadow( upt(eShadow.offset), # Convert units to values blur=upt(eShadow.blur), color=color(eShadow.color).cmyk) else: self.b.shadow(upt(eShadow.offset), blur=upt(eShadow.blur), color=color(eShadow.color).rgb)
def scaleImage(self, path, w, h, index=None, showImageLoresMarker=False, exportExtension=None, force=False): """Scales the image at the path into a new cached image file. Ignore if the cache file is already there. First create the new file name, depending on the resolution of the scaled image. Note that in DrawBot this scaling and saving should be done before any real document/page drawing started, since this proces is using DrawBot canvas pages to execute. In case the source contains indexed pages, use index to select the page. If omitted, the default index is 0 (in DrawBot this also works on non-PDF files). >>> from pagebot import getResourcesPath >>> context = DrawBotContext() >>> path = getResourcesPath() + '/images/peppertom_lowres_398x530.png' >>> scaledImagePath = context.scaleImage(path, 300, 400) >>> os.path.exists(scaledImagePath) True >>> scaledImagePath = context.scaleImage(path, 3, 4) # Reall small >>> os.path.exists(scaledImagePath) True """ # If default _scaled directory does not exist, then create it. cachePath, fileName = self.path2ScaledImagePath( path, w, h, index, exportExtension) if not os.path.exists(cachePath): os.makedirs(cachePath) cachedFilePath = cachePath + fileName if force or not os.path.exists(cachedFilePath): self.newDrawing() # Clean the drawing stack. self.newPage(w=w, h=h) self.image(path, (0, 0), w=w, h=h, pageNumber=index or 0) if showImageLoresMarker: bs = self.newString('LO-RES', style=dict(font=DEFAULT_FALLBACK_FONT_PATH, fontSize=pt(64), fill=color(0, 1, 1), textFill=color(1, 0, 0))) tw, th = bs.size self.text(bs, (w / 2 - tw / 2, h / 2 - th / 4)) self.saveImage(cachedFilePath) self.newDrawing() # Clean the drawing stack. return cachedFilePath
def build(self, view, origin, drawElements=True, **kwargs): """Draw the text on position (x, y). Draw background rectangle and/or frame if fill and/or stroke are defined.""" context = view.context # Get current context b = context.b # Get the page position, depending on the floated origin of the element. p = pointOffset(self.origin, origin) p = self._applyScale(view, p) px, py, _ = p = self._applyAlignment(p) # Ignore z-axis for now. # Use the standard frame drawing of Element, using the border settings of self. self.buildFrame(view, p) # Draw optional frame or borders. # Calculate the scaled width for self.glyph, depending on the em-square # of fonts. width = self.glyph.width / f.info.unitsPerEm * SQSIZE # Draw the vertical width line. Not dashed for now. context.fill(None) context.stroke(color(1, 0, 0), w=0.5) context.line((px + width, py), (px + width, py + SQSIZE)) # Calculate the position of the baseline of the glyph in the square, # using font.info.descender from bottom of the square. baseline = py - f.info.descender / f.info.unitsPerEm * SQSIZE # Create the string in size SQSIZE showing the glyph. t = context.newString(chr(self.uCode), style=glyphStyle) # Set stroke color and stroke width for baseline and draw it. context.stroke(color(0, 0, 0.5), w=0.5) context.line((px, baseline), (px + SQSIZE, baseline)) # Draw the glyph. context.text(t, (px, baseline)) # Construct the label from the original glyph, unicode and glyph name # (if available) label = context.newString( '%s (%d) %s' % (chr(self.uCode), self.uCode, self.glyph.name), style=labelStyle) # Get the size of the generated formatted string to center it. # Draw the label. tw, th = label.size context.text(label, (px + SQSIZE / 2 - tw / 2, py - pt(7))) # Construct the rotated width string on left and right side. widthLabel = context.newString('Width: %d' % self.glyph.width, style=labelStyle) leftLabel = context.newString('Offset: %d' % self.glyph.leftMargin, style=labelStyle) context.save() # Save the graphics state # Translate the origin to the current position of self, so we can rotate. context.translate(px, py) context.rotate(90) # Rotate clockwise vertical context.text(widthLabel, (0, -SQSIZE - pt(7))) # Draw labels on these positions context.text(leftLabel, (0, pt(3))) context.restore() # Restore the graphics state self._restoreScale(view)
def stroke(self, c, w=None): u"""Set global stroke color or the color of the formatted string.""" if c is None: c = noColor elif isinstance(c, (tuple, list)): c = color(*c) elif isinstance(c, (int, float)): c = color(c) msg = 'FlatContext.stroke: Color "%s" is not Color instance' assert isinstance(c, Color), (msg % c) self._stroke = c self.strokeWidth(w)
def fill(self, c): u"""Set the color for global or the color of the formatted string. See: http://xxyxyz.org/flat, color.py. """ if c is None: c = noColor elif isinstance(c, (tuple, list)): c = color(*c) elif isinstance(c, (int, float)): c = color(c) msg = 'FlatContext.fill: Color "%s" is not Color instance' assert isinstance(c, Color), (msg % str(c)) self._fill = c
def build_html(self, view, path, **kwargs): """Build the HTML representation of the element. >>> from pagebot.contexts import getContext >>> from pagebot.document import Document >>> context = getContext('Html') >>> doc = Document(viewId='Mamp', context=context) >>> doc.view <MampView "Mamp" w=1000pt h=1000pt> >>> page = doc[1] >>> e = NanoElement(fill=color(rgb=0xFCCBB8), parent=page) """ b = self.context.b b.comment('Start %s.%s\n' % (self.cssId, self.cssClass)) # In case there is a background color define, then overwrite CSS class if self.fill in (None, noColor): style = None else: style = 'background-color:%s;' % color(self.fill).css b.div(cssId=self.cssId, cssClass='%s clearfix' % self.cssClass, style=style) self.showCssIdClass(view) for e in self.elements: e.build_html(view, path, **kwargs) b._div() b.comment('End %s.%s\n' % (self.cssId, self.cssClass))
def makeTemplate(w, h, french=False): """Make template for the main page (flag), for the given (w, h) size. The optional **french** flag creates a French flag, otherwise Italian.""" # Creat enew Template instance for the given size. template = Template(w=w, h=h) # Create template. # Add named text box to template for main specimen text. if french: rightColor = 0, 0, 0.5 # r, g, b Make French flag else: rightColor = 0, 0.5, 0 # r, g, b Make Italian flag. # Make 2 formatted strings with white text, fsLeft = context.newString('Template box left', style=dict(textFill=whiteColor)) fsRight = context.newString('Template box right', style=dict(textFill=whiteColor)) newTextBox(fsLeft, w=w / 3, fill=color(1, 0, 0), padding=10, parent=template, conditions=[Left2Left(), Top2Top(), Fit2Height()]) newTextBox(fsRight, w=w / 3, fill=rightColor, padding=10, parent=template, conditions=[Right2Right(), Top2Top(), Fit2Height()]) return template
def _get_textFill(self): if self._fill is None: self._fill = color(r=self.nsColor.redComponent(), g=self.nsColor.greenComponent(), b=self.nsColor.blueComponent(), a=self.nsColor.alphaComponent()) return self._fill
def drawBackground1(keyFrame, frame): bs = c.newString('8 weight fonts\nTotal 400k', style=dict(font=LABEL_FONT.path, leading=em(1.2), fontSize=18, fill=color(1, 0, 0))) c.textBox(bs, (50, H-60, 200, 50))
def drawElementOrigin(self, e, origin): if not (self.showOrigin or e.showOrigin): return context = self.context px, py, _ = pointOffset(e.origin, origin) S = e.css('viewInfoOriginMarkerSize', pt(5)) # Draw origin of the element fill = e.css('viewInfoOriginMarkerFill', noColor) stroke = e.css('viewInfoOriginMarkerStroke', blackColor) width = e.css('viewInfoOriginMarkerStrokeWidth', pt(0.25)) context.fill( fill ) # Transparant fill, so we can see the marker on dark backgrounds. context.stroke(stroke, width) context.oval(px - S, py - S, 2 * S, 2 * S) context.line((px - S, py), (px + S, py)) context.line((px, py - S), (px, py + S)) if (self.showDimensions and e.isPage) or e.showDimensions: bs = context.newString(e.xy, style=dict( font=self.css('viewInfoFont'), fontSize=self.css('viewInfoFontSize'), leading=self.css('viewInfoLeading'), textFill=color(0.1))) w, h = bs.size context.text(bs, (px - w / 2, py + S * 1.5))
def drawPadding(self, e, origin): """Draw the page frame of its current padding. >>> from pagebot.contexts.platform import getContext >>> context = getContext() >>> from pagebot.elements.element import Element >>> from pagebot.style import getRootStyle >>> style = getRootStyle() # Get default values >>> e = Element(style=style) # Works on generic elements as well as pages. >>> view = PageView(context=context, style=style) >>> view.showFrame = True >>> view.drawFrame(e, (0, 0)) """ pt, pr, pb, pl = e.padding if ((self.showPadding and e.isPage) or e.showPadding) and (pt or pr or pb or pl): context = self.context p = pointOffset(e.origin, origin) p = e._applyScale(self, p) px, py, _ = e._applyAlignment(p) # Ignore z-axis for now. context.fill(noColor) context.stroke(self.css('viewPaddingStroke', color(0.2, 0.2, 1)), self.css('viewPaddingStrokeWidth', 0.5)) if e.originTop: context.rect(px + pl, py + pb, e.w - pl - pr, e.h - pt - pb) #context.rect(px+pl, py+page.h-pb, page.w-pl-pr, page.h-pt-pb) else: context.rect(px + pl, py + pb, e.w - pl - pr, e.h - pt - pb) e._restoreScale(self)
def makeDocument(): # Creates the publication/document that holds the pages. doc = Document(w=W, h=H, originTop=False, autoPages=1) # Gets page by pageNumber, first in row (at this point there is only one in # this row). page = doc[1] page.padding = 28 page.showPadding = True conditions = [Right2Right(), Float2Top(), Float2Left()] #, Float2Top()]#, Float2Left()] # TODO: Solve this bug, does not mirror. #conditions = [Left2Left(), Float2Top(), Float2Right()] numberOfSquares = 88 ratio = 1 / numberOfSquares for n in range(numberOfSquares): newRect(w=40, h=40, parent=page, fill=color(1 - n * ratio, 0, 0.5), conditions=conditions, margin=0) # Recursively solve the conditions in all pages. # If there are failing conditions, then the status # is returned in the Score instance. score = doc.solve() doc.build()
def drawFrame(self, e, origin): """Draws the page frame if the the flag is on and if there is enough padding to show other meta info. Otherwise the padding is truncated to 0: no use to draw the frame. >>> from pagebot import getContext >>> context = getContext() >>> from pagebot.elements.element import Element >>> from pagebot.style import getRootStyle >>> from pagebot.elements.views.pageview import PageView >>> # Get default values. >>> style = getRootStyle() >>> # Works on generic elements as well as pages. >>> e = Element(style=style) >>> view = PageView(context=context, style=style) >>> view.showFrame = True >>> view.drawFrame(e, (0, 0)) """ if ((self.showFrame and e.isPage) or e.showFrame) and \ self.pl >= self.viewMinInfoPadding and self.pr >= self.viewMinInfoPadding and \ self.pt >= self.viewMinInfoPadding and self.pb >= self.viewMinInfoPadding: self.context.fill(noColor) self.context.stroke(color(0, 0, 1), pt(0.5)) self.context.rect(origin[0], origin[1], e.w, e.h)
def drawRegistrationMark(context, origin, cmSize, cmStrokeWidth, vertical): """Draw registration mark as position x, y. >>> from pagebot.toolbox.units import pt >>> from pagebot import getContext >>> context = getContext('Flat') >>> context.newPage(pt(100), pt(100)) >>> drawRegistrationMark(context, pt(0,0), pt(20), pt(1), True) """ x, y = origin if vertical: dx = cmSize / 2 dy = cmSize else: dx = cmSize dy = cmSize / 2 context.fill(noColor) context.stroke(color(c=1, m=1, y=1, k=1), w=cmStrokeWidth) context.newPath() # Registration circle context.oval(x - cmSize / 4, y - cmSize / 4, cmSize / 2, cmSize / 2) # Registration cross, in length of direction. context.moveTo((x - dx, y)) # Horizontal line. context.lineTo((x + dx, y)) context.moveTo((x, y + dy)) # Vertical line. context.lineTo((x, y - dy)) context.drawPath()
def stroke(self, c, w=None): u"""Set the color for global or the color of the formatted string. >>> from pagebot.toolbox.color import color >>> context = DrawBotContext() >>> context.stroke(color(0.5)) # Same as setStrokeColor >>> context.stroke(color('red')) >>> context.stroke(inheritColor) >>> context.stroke(noColor) >>> context.stroke(0.5) """ if c is None: c = noColor elif isinstance(c, (tuple, list, int, float)): c = color(c) assert isinstance( c, Color), ('DrawBotContext.stroke: %s should be of type Color' % c) if c is inheritColor: # Keep color setting as it is. pass if c is noColor: self.b.stroke(None) # Set color to no-color elif c.isCmyk: cc, cm, cy, ck = c.cmyk # DrawBot.stroke has slight API difference with FormattedString.stroke self.b.cmykStroke(cc, cm, cy, ck, alpha=c.a) else: r, g, b = c.rgb # DrawBot.stroke has slight API difference with FormattedString.stroke self.b.stroke(r, g, b, alpha=c.a) if w is not None: self.strokeWidth(w)
def fill(self, c): u"""Set the color for global or the color of the formatted string. >>> from pagebot.toolbox.color import color >>> context = DrawBotContext() >>> context.fill(color(0.5)) # Same as setFillColor >>> context.fill(color('red')) >>> context.fill(inheritColor) >>> context.fill(noColor) >>> context.fill(0.5) """ if c is None: c = noColor elif isinstance(c, (tuple, list, int, float)): c = color(c) assert isinstance( c, Color), ('DrawBotContext.fill: %s should be of type Color' % c) if c is inheritColor: # Keep color setting as it is. pass elif c is noColor: self.b.fill(None) # Set color to no-color elif c.isCmyk: c, m, y, k = c.cmyk # DrawBot.fill has slight API difference with FormattedString.fill self.b.cmykFill(c, m, y, k, alpha=c.a) else: r, g, b = c.rgb # DrawBot.fill has slight API difference with FormattedString.fill self.b.fill( r, g, b, alpha=c.a) # Convert to rgb, whatever the type of color
def makeDocument(): # Creates the publication/document that holds the pages. doc = Document(w=W, h=H, originTop=False, autoPages=1) # Gets page by pageNumber, first in row (at this point there is only one in # this row). page = doc[1] page.padding = PADDING page.showPadding = True conditions = [Right2Right(), Float2Top(), Float2Left()] # TODO: Solve this bug, does not mirror. conditions = (Left2Left(), Float2Top(), Float2Right()) numberOfSquares = 88 ratio = 1 / numberOfSquares for n in range(numberOfSquares): newRect(w=RW, h=RH, parent=page, fill=color(1 - n * ratio, 0, 0.5), conditions=conditions, margin=0) # Recursively solve the conditions in all page child elements.. # If there are failing conditions, then the status # is returned in the Score instance. score = doc.solve() # Export to various export formats for exportPath in EXPORT_PATHS: doc.export(exportPath)
def fill(self, c): c = color(c) if c is noColor: self._fill = 'none' else: r, g, b = c.rgb self._fill = self.b.rgb(100*r, 100*g, 100*b, '%')
def makePage(doc, page, conditions): # Gets page by pageNumber, first in row (at this point there is only one in # this row). page.padding = 1 page.showPadding = True numberOfSquares = 8 ratio = 1 / numberOfSquares rects = [] for n in range(numberOfSquares): r = newRect(w=40, h=42, mr=4, mt=4, parent=page, fill=color(1 - n * ratio, 0, 0.5), conditions=conditions, margin=0) rects.append(r) rectSets.append(rects) score = doc.solve() doc.build()
def testContext(context, path): doc = Document(w=W, h=H, context=context) page = doc[1] #print('Current page: %s' % page) nextPage = page.next #print('Next page: %s' % nextPage) #print(type(page)) #print('Units: %s' % context.units) #print('# Testing document in %s' % context) conditions = [Right2Right(), Float2Top(), Float2Left()] for n in range(10): newLine(x=100, y=n * 100, parent=page, stroke=0) for n in range(10): newRect(w=40, h=42, mr=4, mt=4, parent=nextPage, fill=color(random() * 0.5 + 0.5, 0, 0.5), conditions=conditions) score = nextPage.solve() #print(score) doc.build() # Export?
class DDSTheme(BaseTheme): NAME = 'DesignDesign.Space' BASE_COLORS = dict( base2=color('#ACACB8'), base3=DDS_LOGO, logo=DDS_LOGO, )