def __init__(self, glyphName, font, lineStroke=True, lineWidth=None, textFill=None, textStroke=None, textStrokeWidth=0, pointStroke=None, pointStrokeWidth=0, pointMarkerSize=None, **kwargs): Element.__init__(self, **kwargs) assert isinstance(font, Font) self.font = font # This is a real Font instance self.glyphName = glyphName # As start assume the full height of the element as fontSize self.fontSize = self.h assert textFill is None or isinstance(textFill, Color) assert textStroke is None or isinstance(textStroke, Color) if textFill is None: textFill = self.GLYPH_FILL self.textFill = textFill self.textStroke = textStroke self.textStrokeWidth = textStrokeWidth or 0 # Flag to show horizontal metrics lines. Can be one of (None, True, False, Color) # Default is self.LINE_STROKE color(0, 0, 1) if lineStroke and not isinstance(lineStroke, Color): # In case it is "True" lineStroke = self.LINE_STROKE self.lineStroke = lineStroke self.lineWidth = lineWidth or 0 # Thickness of metrics lines # Create a style for it, so we can draw the glyph(s) as Text. style = dict(font=self.font.path, fontSize=self.fontSize, textFill=textFill or color(0), align=CENTER) self.bs = BabelString(self.glyphName, style=style) tw, th = self.bs.textSize # Get the size of the glyph(s) string to see if it fits. if self.w and tw > self.w: # If width of self is defined and string is wider # Interpolate the fontSize from the measured width to smaller scaled fontSize. self.fontSize *= self.w / tw # Multiply original fontsize by ratio # Make a new string with the fitting fontSize style['fontSize'] = self.fontSize # Adjust the existing style style['fill'] = textFill or color(0) self.bs = BabelString(self.glyphName, style=style)
def page(self, doc): """ >>> from pagebotnano_030.document import Document >>> from pagebotnano_030.themes import BackToTheCity >>> templates = OneColumnTemplates() >>> templates <OneColumnTemplates> >>> theme = BackToTheCity() >>> doc = Document(theme=theme, templates=templates) >>> page = templates.cover(doc) # The "page" template always must be there. >>> page.compose(doc) """ page = self._initialize(doc, True) # Add text element with the main text column of this page e = TextBox('', name=MAIN, x=page.pl, y=page.pb, w=page.pw, h=page.ph) page.addElement(e) leftPageNumberStyle = doc.theme.getStyle('leftPageNumber') centerPageNumberStyle = doc.theme.getStyle('centerPageNumber') rightPageNumberStyle = doc.theme.getStyle('rightPageNumber') if leftPageNumberStyle is not None and page.pn % 2 == 0: # Even page number?: bs = BabelString(str(page.pn), style) e = Text(bs, name=PN_LEFT, x=page.pl, y=page.pb/2) page.addElement(e) if centerPageNumberStyle is not None: e = Text('', name=PN_CENTER, x=page.pl+page.pw, y=page.pb/2) page.addElement(e) if rightPageNumberStyle is not None and page.pn % 2 != 0: # Odd page number?: e = Text('', name=PN_RIGHT, x=page.pl+page.pw, y=page.pb/2) page.addElement(e) return page
def __init__(self, bs, x, y, w=None, h=None, name=None, fill=None, stroke=None, strokeWidth=None): # Call the base element with all standard attributes. Element.__init__(self, x=x, y=y, w=w, h=h, name=name, fill=fill, stroke=stroke, strokeWidth=strokeWidth) if not isinstance(bs, BabelString): bs = BabelString(bs) self.bs = bs # Store the BabelString in self.
def drawContent(self, ox, oy, doc, page, parent): """Draw the content of this single glyph/string fitting, with line indicators of vertical metrics. TODO: Show more font metrics and glyph metrics here. Add labels of values and names. """ labelStyle = dict(font=self.font, fontSize=7, textFill=0, lineHeight=8, aligh=LEFT) style = dict(font=self.font, fontSize=self.fontSizes[0], textFill=0, align=LEFT) bs = BabelString('', style) tw, th = bs.textSize for fontSize in self.fontSizes: labelLine = BabelString(' %d pt' % fontSize, labelStyle) ltw, lth = labelLine.textSize style['fontSize'] = fontSize style['lineHeight'] = fontSize * self.leading sample = self.sample textLine = BabelString(sample, style) stw, sth = textLine.textSize while sample and self.w and stw + ltw > self.w: # If not fitting, shorten the string until it does sample = sample[:-1] textLine = BabelString(sample, style) stw, sth = textLine.textSize if self.h and th + sth > self.h: break # No vertical space left, skip the rest of the fontSizes. bs += BabelString( '\n' + sample, style ) + labelLine # There still is vertical space, add the textLine tw, th = bs.textSize e = Text(bs, x=ox, y=oy + self.h) #page.h = page.pb + page.pt + th ??? page.addElement(e)
def drawContent(self, ox, oy, doc, page, parent): """Draw the content of this single glyph/string fitting, with line indicators of vertical metrics. TODO: Show more font metrics and glyph metrics here. Add labels of values and names. TODO: For large sizes, compensate for the side beatings of straight stems. """ y = self.h for word in self.words: if self.fontChoice: fontName = choice(self.fontChoice) else: fontName = self.font if self.theme is None: textColor = Color(0) else: textColor = self.theme.randomTextColor style = dict(font=fontName, textFill=textColor, align=LEFT) if self.capsOnly: word = word.upper() style[ 'fontSize'] = fontSize = 100 # Start with large guess of fontSize textLine = BabelString(word, style) tlw, tlh = textLine.textSize style['fontSize'] = fontSize = fontSize * self.w / tlw textLine = BabelString(word, style) # Get a new scaled version tlw, tlh = textLine.textSize if tlh > y: # Not fitting this word vertical anymore, try other. continue if self.capsOnly: y -= doc.context.fontCapHeight(self.font, fontSize) else: y -= doc.context.fontAscender(self.font, fontSize) e = Text(textLine, x=ox, y=oy + y) page.addElement(e) if not self.capsOnly: y += doc.context.fontDescender(self.font, fontSize) y -= fontSize * (self.leading - 1) + self.gh
def cover(self, doc): page = self._initialize(doc, True) # Fill the cover page with a theme background color e = Rect(0, 0, page.w, page.h, fill=doc.theme.getColor(1, 4)) # Dark cover color page.addElement(e) # Add title and author, centered on top-half of the cover. try: title = doc.cd.elements[0].bs except (IndexError, AttributeError): title = BabelString('Untitled') e = TextBox(title, name='Title', x=page.pl/2, y=page.h/2, w=page.pw, h=page.ph/2) page.addElement(e) e = Image(x=page.pl, y=page.pb, w=page.pw) page.addElement(e) return page
page.padding = PAD cw = (page.pw-GUTTER_X)/2 e = Stacked([title1] + words1, font=fontName1, x=page.pl, y=page.pt, w=cw, h=page.ph, gh=GUTTER_Y, capsOnly=capsOnly, fill=0.9) page.addElement(e) e = Stacked([title2] + words2, font=fontName2, x=page.pl+cw+GUTTER_X, y=page.pt, w=cw, h=page.ph, gh=GUTTER_Y, capsOnly=capsOnly, fill=0.9) page.addElement(e) footNoteStyle = dict(font=labelFontName, tracking=0.5, fontSize=labelSize, fill=labelColor, align=LEFT) bs = BabelString('TYPETR '+fontName1, footNoteStyle) e = Text(bs, x=page.pl, y=page.pb/2, w=page.pw) page.addElement(e) footNoteStyle = dict(font=labelFontName, tracking=0.5, fontSize=labelSize, fill=labelColor, align=LEFT) bs = BabelString('TYPETR '+fontName1, footNoteStyle) e = Text(bs, x=page.pl, y=page.pb/2, w=page.pw) page.addElement(e) footNoteStyle['align'] = RIGHT bs = BabelString('Generated by PageBotNano', footNoteStyle) e = Text(bs, x=page.pl+page.pw, y=page.pb/2, w=page.pw) page.addElement(e) doc.export('_export/Stacked-%s-%s.jpg' % (title1, title2), multipage=True) # Instagram
def textBox(self, bs, r): # Set the cache from the overflow, we don't have the source anymore overFlow = BabelString(hyphenation=bs.hyphenation) overFlow.fs = drawBot.textBox(self._asFs(bs), r) return overFlow # Return this “incomplete” BabelString.