def getFittingString(t, fontName): # Make formatted string of large type. # Then see if it fits and calculate the fitting size. # First guess, to see if constructed formatted string fits. initialFontSize = 500 if color: r = 0.5 + random() * 0.5 g = 0.5 + random() * 0.5 b = 0.5 + 0.5 * random() else: r = g = b = random() * 0.8 opacity = 0.4 + 0.6 * random() # Not totally opaque. # Calculate the size for the given string for the selected font/spacing. # Then use the resulting with as source to calculate the fitting fontSize. bs = context.newString(t, style=dict(font=fontName, fontSize=initialFontSize)) fsWidth, fsHeight = bs.size() fontSize = initialFontSize * (W - 3 * padding) / fsWidth # Make new formatted string in fitting fontSize bs = context.newString(t, style=dict(font=fontName, fontSize=fontSize, textFill=(r, g, b, opacity))) return bs
def run(): aa = context.newString('Book Cover', style=dict(font='Georgia', fontSize=40)) print textSize(aa) aa = context.newString('') aa.font('Georgia') aa.fontSize(14) aa += '123' aa.fontSize(40) aa.lineHeight(1.3) aa += ('Book Cover') print textSize(aa) aa = context.newString('') aa.font('Georgia') aa.fontSize(40) aa += 'Book Cover' print textSize(aa) print aa.fontAscender() print aa.fontDescender() print aa.fontAscender() - aa.fontDescender() stroke(0) fill(None) rect(100, 100, 200, 200) text(aa, (100, 100))
def makeTemplate(w, h, french=False): u"""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=1)) fsRight = context.newString('Template box right', style=dict(textFill=1)) newTextBox(fsLeft, w=w / 3, fill=(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 makeCoverTemplate(imagePath, w, h): bleed = 0 textColor = 1 # Make styles # TODO: Make this fit, using size/wdth axis combination of Amstelvar coverTitleSize = 160 # Not optical size yet. Play more with the axes coverTitleFont = getVariableFont(FONT_PATH, dict(wght=0.9, wdth=0.02))#, opsz=coverTitleSize)) coverTitleStyle = dict(font=coverTitleFont.installedName, fontSize=coverTitleSize, textShadow=shadow, textFill=textColor, tracking=-3) coverSubTitleSize = 80 # Not optical size yet. Play more with the axes coverSubTitleFont = getVariableFont(FONT_PATH, dict(wght=0.6, wdth=0.02)) #opsz=coverSubTitleSize)) coverSubTitleStyle = dict(font=coverSubTitleFont.installedName, fontSize=coverSubTitleSize, textFill=(1, 1, 1, 0.3), tracking=0) # Cover coverTemplate = Template(w=w, h=h, padding=PADDING) # Cover template of the magazine. newImage(imagePath, parent=coverTemplate, conditions=[Fit2WidthSides(), Bottom2BottomSide()]) # Title of the magazine cover. coverTitle = context.newString('Fashion', style=coverTitleStyle) # Calculate width if single "F" for now, to align "Slow" # TODO: Change in example to go through the coverTitle to get positions and widths. FWidth, _ = textSize(context.newString('F', style=coverTitleStyle)) coversubTitle = context.newString('Slow', style=coverSubTitleStyle) newTextBox(coversubTitle, parent=coverTemplate, pl=FWidth*0.5, conditions=[Left2Left(), Fit2Width(), Top2TopSide()]) tw, th = textSize(coverTitle) newText(coverTitle, parent=coverTemplate, z=20, h=th*0.4, textShadow=shadow, conditions=[Fit2Width(), Top2TopSide()]) # Make actual date in top-right with magazine title. Draw a bit transparant on background photo. dt = datetime.now() d = dt.strftime("%B %Y") fs = context.newString(d, style=dict(font=MEDIUM.installedName, fontSize=17, textFill=(1, 1, 1, 0.6), tracking=0.5)) # TODO: padding righ could come from right stem of the "n" newTextBox(fs, parent=coverTemplate, xTextAlign=RIGHT, pr=10, pt=6, conditions=[Top2Top(), Right2Right()]) # Titles could come automatic from chapters in the magazine. fs = context.newString('$6.95', style=dict(font=BOOK.installedName, fontSize=12, textFill=textColor, tracking=1, leading=12)) newText(fs, parent=coverTemplate, mt=8, conditions=[Top2Bottom(), Right2Right()]) makeCoverTitles(coverTemplate) return coverTemplate
def getFittingString(t, fontName, layerIndex, fontSize): # Make formatted string of large type. # Then see if it fits and calculate the fitting size. # First guess, to see if constructed formatted string fits. initialFontSize = 500 c1 = (0x30 / 256.0, 0xf1 / 256.0, 0xba / 256.0) c2 = (0xff / 256.0, 0x00 / 256.0, 0x99 / 256.0) if Gray_Scale: r = g = b = 0.5 + 0.5 * random() opacity = 0.7 + 0.3 * random() # Not totally opaque. else: if layerIndex == 0: # Never black as first or single layer c = choice((c1, c2, (1, 1, 1))) else: c = choice((c1, c2, (0, 0, 0), (1, 1, 1))) r, g, b = c opacity = 1 #opacity = 0.4+0.6*random() # Not totally opaque. # Contrast pixel behavior depends on Single or Mono features = dict(zero=Slashed_Zero, smcp=Smallcaps, c2sc=Caps_As_Smallcaps, ss08=Italic_Shapes, ss07=Condensed, ss01=Extended_Ascenders, ss02=Extended_Capitals, ss03=Extended_Descenders, ss04=Contrast_Pixel, ss05=not Contrast_Pixel, ss09=Alternative_g, onum=LC_Figures) rTracking = int(Tracking - 2) * 0.1 if layerIndex == 0: # Calculate the size for the given string for the selected font/spacing. # Then use the resulting with as source to calculate the fitting fontSize. fs = context.newString(Sample_Text, style=dict(font=fontName, rTracking=rTracking, fontSize=initialFontSize, openTypeFeatures=features)) fsWidth, fsHeight = fs.size() fontSize = int(round(initialFontSize * (W - ML - MR) / fsWidth)) # Make new formatted string in fitting fontSize fs = context.newString(Sample_Text, style=dict(font=fontName, rTracking=rTracking, fontSize=fontSize, textFill=(r, g, b, opacity), openTypeFeatures=features)) return fontSize, fs
def run(): s = u"""글자가 일상이 된다 산돌커뮤니케이션 ABCD123 Latin すべての文化集団は,独自の言語,文字,書記システムを持つ.それゆえ,個々の書記システムをサイバースペースに移転することは. ABCD123 Latin included""" c.newPage(W, H) fsr = c.newString(s, style=dict(font='Generic-Regular', fontSize=FontSize)) fsb = c.newString(s, style=dict(font='Generic-Regular_Bold', fontSize=FontSize)) fsbRed = c.newString(s, style=dict(font='Generic-Regular_Bold', fill=(1, 0, 0), fontSize=FontSize)) c.textBox(fsr, (100, 600, 820, 350)) c.textBox(fsb, (100, 300, 820, 350)) c.textBox(fsbRed, (100, 0, 820, 350)) c.textBox(fsr, (100, 0, 820, 350))
def _drawGlyphMarker(self, axisName, mx, my, glyphName, fontSize, location, strokeW=2): # Middle circle context.fill(1) context.stroke(0.7) context.strokeWidth(strokeW) context.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 = context.newString(axisName, style=dict(font=variableFont.installedName, fontSize=fontSize / 4, textFill=0)) tw, th = context.textSize(fs) context.text( fs, (mx - tw / 2, my - fontSize / 2 * self.R - th * 2 / 3)) glyphPathScale = fontSize / self.font.info.unitsPerEm context.drawGlyphPath(variableFont, glyphName, mx, my - fontSize / 3, s=glyphPathScale, fillColor=0)
def drawBackground1(keyFrame, frame): fs = context.newString('8 weight fonts\nTotal 400k', style=dict(font=LABEL_FONT.installedName, rLeading=1.2, fontSize=18, textFill=(1, 0, 0))) textBox(fs, (50, H - 60, 200, 50))
def _drawSpreadSheet(self, p, view): px, py, _ = p leading = self.css('fontSize') * self.css('rLeading') c = self.css('fill') colRowFill = c + (1 - c) / 2 fill(colRowFill) stroke(None) rect(px, py, self.CW, self.h) fill(None) stroke(c / 2) strokeWidth(0.5) # Draw horizontal lines for iy in range(int(self.h / leading) + 1): y = py + iy * leading line((px, y), (px + self.w, y)) fs = context.newString(str(iy), style=dict(font='Verdana', fontSize=6, textFill=(1, 0, 0))) tw, th = textSize(fs) #print (y, leading, leading/2, th, th/2) text(fs, (px + self.CW - 4 - tw, y + th / 2)) # Draw vertical lines for ix in range(int(self.w / self.CW) + 1): x = px + ix * self.CW line((x, py), (x, py + self.h))
def getFittingString(t, fontName, c): # Make formatted string of large type. # Then see if it fits and calculate the fitting size. # First guess, to see if constructed formatted string fits. # Calculate the size for the given string for the selected font/spacing. # Then use the resulting with as source to calculate the fitting fontSize. initialFontSize = 500 fs = context.newString(t, style=dict(font=fontName, fontSize=initialFontSize)) fsWidth, fsHeight = fs.size() fontSize = initialFontSize * (W-3*padding) / fsWidth # Make new formatted string in fitting fontSize fs = context.newString(t, style=dict(font=fontName, fontSize=fontSize, textFill=c)) return fs
def drawBackground3(keyFrame, frame): drawBackground1(keyFrame, frame) varFontIcon = id2FontIcon['VarFont'] fs = context.newString('%d weights\nTotal 100k' % ((2**15) + 1), style=dict(font=LABEL_FONT.installedName, rLeading=1.2, fontSize=18, textFill=(1, 0, 0))) textBox(fs, (varFontIcon.x, H - 60, 200, 50))
def drawBackground2(keyFrame, frame): drawBackground1(keyFrame, frame) varFontIcon = id2FontIcon['VarFont'] fs = c.newString('1 axis\nTotal 100k', style=dict(font=LABEL_FONT.installedName, rLeading=1.2, fontSize=18, textFill=(1, 0, 0))) c.textBox(fs, (varFontIcon.x, H - 60, 200, 50))
def getFittingString(t, fontName, layerIndex, fontSize=None): # Make formatted string of large type. # Then see if it fits and calculate the fitting size. # First guess, to see if constructed formatted string fits. initialFontSize = 500 if Gray_Scale: r = g = b = 0.5 + 0.5 * random() opacity = 0.7 + 0.3 * random() # Not totally opaque. else: r = random() g = random() b = random() opacity = 0.4 + 0.6 * random() # Not totally opaque. features = dict(zero=Slashed_Zero, smcp=Smallcaps, c2sc=Caps_As_Smallcaps, ss08=Italic_Shapes, ss07=Condensed, ss01=Extended_Ascenders, ss02=Extended_Capitals, ss03=Extended_Descenders, ss04=Contrast_Pixel, ss09=Alternative_g, onum=LC_Figures) if fontSize is None: # Calculate the size for the given string for the selected font/spacing. # Then use the resulting with as source to calculate the fitting fontSize. bs = context.newString(Sample_Text, style=dict(font=fontName, fontSize=initialFontSize, openTypeFeatures=features)) fsWidth, fsHeight = bs.size() fontSize = int(round(initialFontSize * (W - 2 * M) / fsWidth)) # Make new formatted string in fitting fontSize bs = context.newString(Sample_Text, style=dict(font=fontName, fontSize=fontSize, textFill=(r, g, b, opacity), openTypeFeatures=features)) return fontSize, bs
def buildBusinessCard1(w, h): M = 4 # Margin # Page 66 context.newPage(w, h) y = h context.image('docs/images/IMG_2381-50.jpg', (0, 0), w=w) # Title of cover, make it fit in with and add shadow style = dict(font='Upgrade-Regular', fontSize=14, textFill=1, xTextAlign=CENTER) styleTitle = dict(font='Upgrade-Italic', fontSize=10, textFill=1, xTextAlign=CENTER) styleEmail = dict(font='Upgrade-Light', fontSize=8, textFill=1, xTextAlign=CENTER, leading=10, rTracking=0.02) bs = context.newString('Petr van Blokland\n', style=style) bs += context.newString('Designer | Educator | Founder\n', style=styleTitle) bs += context.newString('[email protected] | @petrvanblokland', style=styleEmail) tw, th = bs.size() context.text(bs, (w / 2 - tw / 2, h * 0.55)) logoStyle = dict(font='Upgrade-Black', fontSize=22, textFill=1, rTracking=1.4) bs = context.newString(u'.TYPETR', style=logoStyle) tw, th = bs.size() context.text(bs, (w / 2 - tw / 2 - 3, 2 * M))
def buildBusinessCard(w, h): for imageIndex in range(1, 5): context.newPage(w, h) y = h # Start vertical position on top of the page. # Draw one of the 4 Bitcount background images, filename indexed by imageIndex # The TYPETR Bitcount license can be purchased at: # https://store.typenetwork.com/foundry/typetr/fonts/bitcount imagePath = ROOT_PATH + '/Examples/Portfolios/images/BitcountRender%d.png' % imageIndex context.image(imagePath, (0, 0), w=w) # Set to full page width at origin # Define some style. Note thate TYPETR Upgrade is the identity typeface, which may not be installed. # Another font is selected in case TYPETR Upgrade is not available. # View more here: https://upgrade.typenetwork.com # A license can be purchased at: # https://store.typenetwork.com/foundry/typetr/fonts/upgrade style = dict(font='Upgrade-Regular', fontSize=14, textFill=1, xTextAlign=CENTER) styleTitle = dict(font='Upgrade-Italic', fontSize=10, textFill=1, xTextAlign=CENTER) styleEmail = dict(font='Upgrade-Light', fontSize=8, textFill=1, xTextAlign=CENTER, leading=10, rTracking=0.02) # Create styled BabelString for the name lines bs = context.newString('Petr van Blokland\n', style=style) bs += context.newString('Designer | Educator | Founder\n', style=styleTitle) bs += context.newString('[email protected] | @petrvanblokland', style=styleEmail) # Get the size of the text block, to position it centered tw, th = context.textSize(bs) # Draw a textbox in the contextf canvas. context.text(bs, (w/2-tw/2, h*0.55)) # Create a style for the logo. The size and tracking is hardcoded to fit the business card width. logoStyle = dict(font='Upgrade-Black', fontSize=22, textFill=1, rTracking=1.4) # Create the BabelString, containing the fitting logo with tracking. bs = context.newString(u'.TYPETR', style=logoStyle) # Get the size of the text block, to position it centered tw, th = bs.size() # Draw a textbox in the contextf canvas. context.text(bs, (w/2-tw/2-3, 2*M))
def getFittingString(t, fontName, layerIndex, fontSize=None): # Make formatted string of large type. # Then see if it fits and calculate the fitting size. # First guess, to see if constructed formatted string fits. initialFontSize = 500 glb = globals() colorLabel = 'Layer_Color_%d' % layerIndex layerColor = getColor(layerIndex) if glb.get(colorLabel) is None: glb[colorLabel] = NSColor.whiteColor() try: r, g, b, opacity = layerColor.getRed_green_blue_alpha_( None, None, None, None) except ValueError: r = random() g = random() b = random() opacity = 0.4 + 0.6 * random() # Not totally opaque. glb[colorLabel] = NSColor.colorWithCalibratedRed_green_blue_alpha_( r, g, b, opacity) if not color: r = g = b = random() * 0.8 if fontSize is None: # Calculate the size for the given string for the selected font/spacing. # Then use the resulting with as source to calculate the fitting fontSize. fs = context.newString(Sample_Text, style=dict(font=fontName, fontSize=initialFontSize)) fsWidth, fsHeight = fs.size() fontSize = initialFontSize * (W - 2 * M) / fsWidth # Make new formatted string in fitting fontSize fs = context.newString(t, style=dict(font=fontName, fontSize=fontSize, textFill=(r, g, b, opacity))) return fontSize, fs
def buildBusinessCard2(w, h): M = 4 # Margin # Page 66 context.newPage(w, h) y = h context.image('docs/images/IMG_2379-50.jpg', (0, 0), w=w * 1.3) # Title of cover, make it fit in with and add shadow style = dict(font='Upgrade-Regular', fontSize=14, textFill=1, xTextAlign=CENTER) styleTitle = dict(font='Upgrade-Italic', fontSize=10, textFill=(0xEC / 255, 0x3E / 255, 0x2B / 255), xTextAlign=CENTER) styleEmail = dict(font='Upgrade-Light', fontSize=8, textFill=1, xTextAlign=CENTER, leading=10, rTracking=0.02) bs = context.newString('Claudia Mens\n', style=style) bs += context.newString('Designer | Educator | Founder\n', style=styleTitle) bs += context.newString('[email protected] ', style=styleEmail) tw, th = bs.size() context.textBox(bs, (w / 2 - tw / 2, h / 2 - th / 2, tw, th)) styleLogo = dict(font='Upgrade-Thin', fontSize=14, textFill=1, openTypeFeatures=dict(case=True))
def drawFigures(): W, H = 860, 451 newPage(W, H) LEADING = 0.9 fs = c.newString('ABC0123456789\n', style=dict(textFill=0, rLeading=1, font='BitcountPropSingle-RegularCircle', fontSize=90)) fs += c.newString('abc0123456789\n', style=dict(textFill=0, font='BitcountPropSingle-RegularCircle', rLeading=LEADING, fontSize=90, openTypeFeatures=dict(smcp=True))) fs += c.newString('ABCabc0123456789\n', style=dict(textFill=0, font='BitcountPropSingle-RegularCircle', rLeading=LEADING, fontSize=90, openTypeFeatures=dict(onum=True, ss07=True))) fs += c.newString('ABCabc0123456789\n', style=dict(textFill=0, font='BitcountPropSingle-RegularCircle', rLeading=LEADING, fontSize=90, openTypeFeatures=dict(ss07=True))) fs += c.newString('Fraction 1/2 12345/67890\n', style=dict(textFill=0, font='BitcountPropSingle-RegularCircle', rLeading=LEADING, fontSize=90, openTypeFeatures=dict(frac=True))) M = 30 c.textBox(fs, (M+10, -10, W-2*M, H)) c.saveImage('_export/figures.png') # Save the sample as file or animated gif.
def _drawBaselines(self, showIndex=False, showY=False, showLeading=False): # Let's see if we can draw over them in exactly the same position. fontSize = 8 if showY: c.text(c.newString('0', style=dict(align='left', font='Verdana', fontSize=8, fill=(0, 0, 1))), (self.x + self.w + 3, self.y + self.h - fontSize/4)) prevY = 0 for index in range(len(self)): _, y, _ = self.baseLines[index] c.line((self.x, self.y + self.h - y), (self.x + self.w, self.y + self.h - y)) if showIndex: c.text(c.newString('index', style=dict(align='right', font='Verdana', fontSize=fontSize, fill=(0, 0, 1))), (self.x-8, self.y + self.h - y - fontSize/3)) if showY: c.text(c.newString('%d' % round(y), style=dict(align='left', font='Verdana', fontSize=fontSize, fill=(0, 0, 1))), (self.x + self.w + 3, self.y + self.h - y - fontSize/4)) if showLeading: leading = round(abs(y - prevY)) c.text(c.newString('%d' % leading, style=dict(align='left', font='Verdana', fontSize=fontSize, fill=(1, 0, 0))), (self.x + self.w + 3, self.y + self.h - prevY - leading/2 - fontSize/4)) prevY = y
def buildSpecimenPages(doc, fontNames): for index, fontName in enumerate(sorted(fontNames)): font = getFontByName(fontName) page = doc[index] pageTitle = font.info.familyName + ' ' + font.info.styleName # Add filling rectangle for background color of the old paper book. newRect(z=-1, parent=page, conditions=[Bleed2Sides()], fill=PAPER_COLOR) # Centered title: family name and style name of the current font. titleBs = context.newString(pageTitle, style=dict(font=fontName, fontSize=24, textFill=0)) newText(titleBs, x=50, y=100, parent=page, w=400)
def run(): W, H = 1000, 400 c.newPage(W, H) txt = "Hello World" x, y = 10, 100 fs = c.newString(txt, style=dict(fontSize=300, font="Verdana")) # draw the text c.text(fs, (x, y)) # calculate the size of the text textWidth, textHeight = c.textSize(txt) # set a red stroke color c.stroke(1, 0, 0) # loop over all font metrics for metric in (0, fs.fontDescender(), fs.fontAscender(), fs.fontXHeight(), fs.fontCapHeight()): # draw a red line with the size of the drawn text c.line((x, y + metric), (W - 2 * x, y + metric))
def buildDesignPages(w, h): cw = w - ML - MR # Page 66 context.newPage(w, h) bs = context.newText(t) R = (ML, MB, w - ML - MR, h - MB - MT) overFill = context.textOverflow(bs, R) context.textBox(bs, R) pn = context.newString(66, style=pageNumberStyle) context.text(pn, (w / 2 - pn.w / 2, M / 2)) pt = context.newString(bookTitle, style=pageTitleStyle) context.textBox(pt, (ML, h - MT * 0.75, cw, pt.h)) # Page 67 context.newPage(w, h) # Assume that we have a footnote on this page, calc it's space. fnMark = context.newString(footNoteRef, style=footNoteRefStyle) fn = fnMark + ' ' + context.newString(footNoteText, style=footNoteStyle) fnw, fnh = fn.textSize(cw) cfnh = fnh + bodyStyle['fontSize'] * bodyStyle['rLeading'] ch = h - MB - MT - cfnh R = (ML, MB + cfnh, cw, ch) context.textBox(overFill, R) context.textBox(fn, (ML, MB, cw, fnh)) pt = context.newString(chapterTitle, style=pageChapterStyle) context.textBox(pt, (ML, h - MT * 0.75, cw, pt.h)) pn = context.newString(67, style=pageNumberStyle) context.text(pn, (w / 2 - pn.w / 2, M / 2))
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.""" c.fill(0.9) c.stroke(None) mx = x + self.w / 2 my = y + self.h / 2 # Gray circle that defines the area of c.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 c.fill(0) c.text( c.newString(self.font.info.familyName, style=dict(font=self.style['labelFont'], fontSize=self.style['axisNameFontSize'])), (x - fontSize / 2, y + self.h + fontSize / 2)) # Draw spokes c.fill(None) c.stroke(0) c.strokeWidth(1) c.newPath() for axisName, angle in self.angles.items(): markerX, markerY = self._angle2XY(angle, self.w / 2) c.moveTo((mx, my)) c.lineTo((mx + markerX, my + markerY)) c.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 = c.newString( makeAxisName(axisName), style=dict(font=self.style.get('labelFont', 'Verdana'), fontSize=axisNameFontSize, fill=self.style.get('axisNameColor', 0))) tw, th = c.textSize(fs) c.fill(0.7, 0.7, 0.7, 0.6) c.stroke(None) c.rect(mx + markerX - tw / 2 - 4, my + markerY - axisNameFontSize / 2 - th * 1.5 - 4, tw + 8, th) c.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 = c.newString( sMaxValue, style=dict(font=self.style.get('labelFont', 'Verdana'), fontSize=valueFontSize, fill=self.style.get('axisValueColor', 0))) tw, th = c.textSize(fs) c.fill(0.7, 0.7, 0.7, 0.6) c.stroke(None) c.rect(mx + markerX - tw / 2 - 4, my + markerY + valueFontSize / 2 + th * 1.5 - 4, tw + 8, th) c.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 = c.newString( sValue, style=dict(font=self.style.get('labelFont', 'Verdana'), fontSize=valueFontSize, fill=self.style.get('axisValueColor', 0))) tw, th = c.textSize(fs) c.fill(0.7, 0.7, 0.7, 0.6) c.stroke(None) c.rect( mx + markerX * INTERPOLATION - tw / 2 - 4, my + markerY * INTERPOLATION + valueFontSize / 2 + th * 1.5 - 4, tw + 8, th) c.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 = c.newString( sValue, style=dict(font=self.style.get('labelFont', 'Verdana'), fontSize=valueFontSize, fill=self.style.get('axisValueColor', 0))) tw, th = c.textSize(fs) c.fill(0.7, 0.7, 0.7, 0.6) c.stroke(None) minM = 0.2 c.rect(mx + markerX * minM - tw / 2 - 4, my + markerY * minM + th * 0.5 - 4, tw + 8, th) c.text(fs, (mx + markerX * minM - tw / 2, my + markerY * minM + th * 0.5))
def buildSpecimenPages(doc, family, pn): for font in family.getFonts(): page = doc[pn] page.padding = PADDING page.gridX = GRID_X pageTitle = path2FontName(font.path) # Add filling rectangle for background color of the old paper book. # Set z-azis != 0, to make floating elements not get stuck at the background newRect(z=-10, w=W, h=H, parent=page, fill=PAPER_COLOR) # During development, draw the template scan as background # Set z-azis != 0, to make floating elements not get stuck at the background if SHOW_TEMPLATE: newImage(ATF_PATH, x=0, y=0, z=-10, w=W, parent=page) # Centered title: family name and style name of the current font. titleBs = context.newString(pageTitle, style=dict(font=font.path, xTextAlign=CENTER, textFill=0)) titleBox = newTextBox(titleBs, parent=page, h=2*L, conditions=[Top2Top(), Fit2Width()], fill=DEBUG_COLOR0) titleBox.solve() largeSampleBox = newTextBox('', parent=page, w=C1+G/2, conditions=[Float2Top(), Left2Left(), Fit2Bottom()], fill=DEBUG_COLOR1) largeSampleBox.solve() # In order to fit different words in the fixed space, they will vary in size. # But as the variation in sizes is larger than the variation in size, we'll calculate the strings # first for the various word lengths and then sort them by size. largeSampleSizes = {} for n in (4, 5, 6, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10): word = getCapitalizedWord(n) if word is None: continue if len(largeSampleSizes) > 10: break sample = context.newString(word+'\n', style=dict(font=font.path, rLeading=1), w=C1, pixelFit=False) sampleFontSize = int(round(sample.fontSize)) if not sampleFontSize in largeSampleSizes: largeSampleSizes[sampleFontSize] = sample print sorted(largeSampleSizes.keys()) largeSample = context.newString('') for sampleFontSize, sample in sorted(largeSampleSizes.items(), reverse=True): label = context.newString('%d Points\n' % round(sampleFontSize), style=labelStyle) #if largeSample.h + sample.h > largeSampleBox.h: # break largeSample += label + sample largeSampleBox.setText(largeSample) for fontSize, numChars in ((12, 8), (10, 13), (8, 16)): smallSamples = context.newString(getCapWord(numChars), style=dict(font=font.path), w=C2) label = context.newString('%d Points\n' % round(smallSamples.fontSize), style=labelStyle) shortWordsSample = context.newString(getShortWordText(), style=dict(font=font.path, fontSize=smallSamples.fontSize, rLeading=1)) newTextBox(label + smallSamples + ' ' + shortWordsSample, parent=page, w=C2+G/2, h=80, ml=G/2, mb=L, conditions=[Right2Right(), Float2Top(), Float2Left()], fill=DEBUG_COLOR1) label = context.newString('%d Points\n' % fontSize, style=labelStyle) smallSamples = context.newString(blurb.getBlurb('article', noTags=True), style=dict(font=font.path, fontSize=fontSize)) newTextBox(label + smallSamples, parent=page, w=C2-2, h=80, mb=L, ml=G/2, conditions=[Right2Right(), Float2Top()], fill=DEBUG_COLOR1) glyphSetFrame = newRect(parent=page, mb=L, ml=G/2, padding=L, borders=dict(line=INLINE, stroke=0, strokeWidth=0.5), conditions=[Right2Right(), Float2Top(), Float2Left(), Fit2Right(), Fit2Bottom()], fill=DEBUG_COLOR2) glyphSet = context.newString('Subset of characters in Complete Font\n', style=dict(font=font.path, fontSize=8, xTextAlign=CENTER, rParagraphTopSpacing=0.25, rParagraphBottomSpacing=0.5)) glyphSet += context.newString(GLYPH_SET, style=dict(font=font.path, fontSize=23, xTextAlign=CENTER, leading=32)) newTextBox(glyphSet, parent=glyphSetFrame, padding=(1.5*L, L, L, L), borders=dict(line=INLINE, stroke=0, strokeWidth=0.25), conditions=[Left2Left(), Fit2Right(), Top2Top(), Fit2Bottom() ], fill=DEBUG_COLOR3) pn += 1 return pn
def drawFontLabel(p, varFamily, f, fIndex=None, fAxis=None): x, y = p print f.info.styleName, f.info.weightClass, f.info.widthClass glyphH = f[GLYPH] if not glyphH.width: print glyphH, 'No width' return s = 0.05 * 1000 / f.info.unitsPerEm leading = 2048 / f.info.unitsPerEm stroke(None) fill(0) save() translate(x - glyphH.width / 2 * s, y - leading - 50) scale(s) drawPath(glyphH.path) restore() y -= leading + 50 save() pathLabel = '-'.join(path2Name(f.path).split('-')[1:]) #label = path2Name(f.path) if fAxis is not None: label = '@' + fAxis elif fIndex is None: label = '' else: label = '#%d ' % fIndex label += '%s\n(%s)\n%d' % (pathLabel.replace('.ttf', '').replace( '_', '\n').replace('-', '\n'), f.info.styleName, f.info.weightClass) fs = FormattedString(label, fontSize=10, align='center') tw, th = textSize(fs) text(fs, (x - tw / 2, y - 14)) restore() y -= leading + th - 22 # Draw marker on actual position of H.stem and H.weight as green dot stemValues = f.analyzer.stems.keys() if stemValues: # Cannot find H-stem, skip this marker stem = min(stemValues) # XOPQ (counter) + H.stem == H.width - H.stem - H.lsb - H.rsb width = glyphH.width - stem - glyphH.leftMargin - glyphH.rightMargin c.fill((0, 0.5, 0)) c.stroke(None) R = 16 weightLoc, widthLoc = stem, width / 2 c.oval(weightLoc - R / 2, widthLoc - R / 2, R, R) if fAxis is not None: label = '@' + fAxis elif fIndex is None: label = '' else: label = '#%d\n' % fIndex bs = c.newString(label + ('S:%d\nW:%d\n%d' % (weightLoc, widthLoc, f.info.weightClass)), style=dict(fontSize=10, xTextAlign='center', textFill=0)) tw, th = c.textSize(bs) c.text(bs, (weightLoc - tw / 2, widthLoc - 24)) if varFamily.originFont is f: # If one of these is the guessed origin font, then draw marker c.fill(None) c.stroke((0, 0.5, 0), 2) # Stroke color and width R = 23 c.oval(weightLoc - R / 2, widthLoc - R / 2, R, R) else: pass
def fitVariableWidth(varFont, s, w, fontSize, condensedLocation, wideLocation, fixedSize=False, tracking=None, rTracking=None): u""" Answer the font instance that makes string s width on the given width *w* for the given *fontSize*. The *condensedLocation* dictionary defines the most condensed font instance (optionally including the opsz) and the *wideLocation* dictionary defines the most wide font instance (optionally including the opsz). The string width for s is calculated with both locations and then the [wdth] value is interpolated and iterated until the location is found where the string *s* fits width *w). Note that interpolation may not be enough, as the width axis may contain non-linear masters. If the requested w outside of what is possible with two locations, then interations are performed to change the size. Again this cannot be done by simple interpolation, as the [opsz] also changes the width. It one of the axes does not exist in the font, then use the default setting of the font. """ condFont = getVariableFont(varFont, condensedLocation) condensedFs = context.newString(s, style=dict(font=condFont.installedName, fontSize=fontSize, tracking=tracking, rTracking=rTracking, textFill=0)) condWidth, _ = textSize(condensedFs) wideFont = getVariableFont(varFont, wideLocation) wideFs = context.newString(s, style=dict(font=wideFont.installedName, fontSize=fontSize, tracking=tracking, rTracking=rTracking, textFill=0)) wideWidth, _ = textSize(wideFs) # Check if the requested with is inside the boundaries of the font width axis if w < condensedWidth: font = condFont fs = condensedFs location = condensedLocation elif w > wideWidth: font = wideFont fs = wideFs location = wideLocation else: # Now interpolation the fitting location widthRange = wideLocation['wdth'] - condensedLocation['wdth'] location = copy.copy(condensedLocation) location['wdth'] += widthRange * (w - condWidth) / (wideWidth - condWidth) font = getVariableFont(varFont, location) fs = context.newString(s, style=dict(font=font.installedName, fontSize=fontSize, tracking=tracking, rTracking=rTracking, textFill=0)) return dict(condensendFont=condFont, condensedFs=condensedFs, condWidth=condWidth, condensedLocation=condensedLocation, wideFont=wideFont, wideFs=wideFs, wideWidth=wideWidth, wideLocation=wideLocation, font=font, fs=fs, width=textSize(fs)[0], location=location)
#!/usr/bin/env python # ----------------------------------------------------------------------------- # # P A G E B O T # # Copyright (c) 2016+ Buro Petr van Blokland + Claudia Mens & Font Bureau # www.pagebot.io # from https://github.com/fonttools/fonttools/blob/master/Lib/fontTools/varLib/mutator.py # Licensed under MIT conditions # # Supporting usage of DrawBot, www.drawbot.com # Supporting usage of Flat, https://github.com/xxyxyz/flat # ----------------------------------------------------------------------------- from pagebot.contexts import defaultContext as context from pagebot.fonttoolbox.objects.font import Font f = Font("fonts/_instances/AmstelvarAlpha-Default.ttf") fs = context.newString(u'Ae', style=dict(font=f.installedName, fontSize=500)) context.textBox(fs, (20, -10, 900, 900))
scriptGlobals.s4 = blurb.getBlurb('article_content', noTags=True) scriptGlobals.s5 = blurb.getBlurb('article_content', noTags=True) F = 50 R = 10 x = y = 20 rLeading = 0.6 for angle in range(0, 360, 10): context.newPage(1000, 1000) dx = sin(angle/360*2*pi) * R dy = cos(angle/360*2*pi) * R fs = context.newString(scriptGlobals.s1, style=dict(font='BitpathGridDouble-RegularLineSquare', fontSize=F, textFill=(1, 0, 0), rLeading=rLeading)) context.textBox(fs, (x, y, 1000, 900)) fs = context.newString(scriptGlobals.s2, style=dict(font='BitpathGridDouble-RegularLineSquare', fontSize=F, textFill=(0, 1, 0), rLeading=rLeading)) context.textBox(fs, (x+7, y+7, 1000, 900)) fs = context.newString(scriptGlobals.s3, style=dict(font='BitpathGridDouble-RegularLineSquare', fontSize=F, textFill=(0, 1, 1),
from pagebot.contexts import defaultContext as context W = 600 H = 300 HEAD_LINE = """When fonts started a new world""" TEXT = """The advent of variable fonts means doing nothing, or everything, or something in between for font users and type designers. """ newPage(W, H) bs = context.newString(HEAD_LINE + '\n', style=dict(font='Verdana', fontSize=24, textFill=0)) bs += context.newString(TEXT, style=dict(font='Verdana', fontSize=12, textFill=0)) tw, th = context.textSize(bs, w=200) print tw, th context.textBox(bs, (100, -th + H, 200, th))
# ----------------------------------------------------------------------------- # # P A G E B O T # # Copyright (c) 2016+ Buro Petr van Blokland + Claudia Mens & Font Bureau # www.pagebot.io # Licensed under MIT conditions # # Supporting usage of DrawBot, www.drawbot.com # Supporting usage of Flat, https://github.com/xxyxyz/flat # ----------------------------------------------------------------------------- # from pagebot.contexts import defaultContext as c c.newPage(1000, 1000) fs = c.newString("b", style=dict(lineHeight=74, font="Times", fontSize=38)) fs += c.newString("hello world ", style=dict(font="Helvetica", fontSize=10, lineHeight=12)) fs += c.newString("hi agian " * 10) r = (10, 10, 200, 200) c.textBox(fs, r) c.fill(None) c.stroke(1, 0, 0) c.rect(*r) positions = c.textBoxBaseLines(fs, r) s = 2 for x, y in positions: