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 drawPageFrame(w): c.fill(1) c.stroke(0) c.newPath() c.moveTo((PADDING, H - PADDING)) c.lineTo((PADDING + w, H - PADDING)) c.lineTo((PADDING + w, H / 2 + PADDING)) c.curveTo((PADDING + w / 2, H / 2 + PADDING), (PADDING + w / 2, H / 2 + PADDING - M / 2), (PADDING, H / 2 + PADDING - M / 2)) c.closePath() c.drawPath() c.fill(None) c.stroke(0.5) c.strokeWidth(4) leading = 14 for n in range(10): c.line( (PADDING + M, H - 5 * PADDING - n * leading), (PADDING + w - M - LINE_ENDINGS[n], H - 5 * PADDING - n * leading))
def draw(w): u""" Draw 3 lines of text: the boundaries of with the width axis and the interpolated width from the slider value. If the slider goes of the extremes, then the middle line stops at the boundary width. """ d = fitVariableWidth(f, HEADLINE, w, HEADLINE_SIZE, condensedLocation, wideLocation) c.newPage(W, H) c.fill(1) c.rect(0, 0, W, H) c.text(d['condensedFs'], (PADDING, 50)) c.text(d['fs'], (PADDING, 100)) c.text(d['wideFs'], (PADDING, 150)) c.fill(None) c.stroke(0) c.line((PADDING, PADDING), (PADDING, H-PADDING)) c.line((PADDING+d['condensedWidth'], PADDING), (PADDING+d['condensedWidth'], H-PADDING)) c.line((PADDING+d['width'], PADDING), (PADDING+d['width'], H-PADDING)) c.line((PADDING+d['wideWidth'], PADDING), (PADDING+d['wideWidth'], H-PADDING)) c.stroke(None) c.fill(0) c.text('%d %0.2f' % (round(d['condensedWidth']), d['condensedLocation']['wdth']), (PADDING + d['condensedWidth'] + 5, PADDING)) c.text('%d %0.2f' % (round(d['width']), d['location']['wdth']), (PADDING + d['width'] + 5, PADDING)) c.text('%d %0.2f' % (round(d['wideWidth']), d['wideLocation']['wdth']), (PADDING + d['wideWidth'] + 5, PADDING)) c.stroke(1, 0, 0) c.line((PADDING+w, PADDING), (PADDING+w, H-PADDING)) c.stroke(None) c.fill(1, 0, 0) c.text('Column %d' % w, (PADDING+w+5, H-PADDING-5))
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
# Tracking is added after the glyphs, so the measured width of a tracked # string is wider that it looks. # To safely measure the real width of the string, the width of one "track" # needs to be subtracted. from pagebot.contexts import defaultContext as context # Create a new page w, h = 400, 100 context.newPage(w, h) # Draw vertical line in the middle of the page as reference. context.fill(None) context.strokeWeight = 0.5 context.stroke((0, 0, 0.4)) context.line((w / 2, 0), (w / 2, h)) TRACKING = 1 FONT_SIZE = 14 TRACKED_SPACE = FONT_SIZE * TRACKING # New Babel string, probably DrawBot FormattedString flavor. bs = context.newString('TRACKEDSTRING', style=dict(font='Verdana', fontSize=FONT_SIZE, rTracking=TRACKING)) # Call DrawBot textSize to determine the size of the string # including the tracking tw, th = bs.size() context.text(bs, (w / 2 - tw / 2, 70))
def draw(self): # Try to use TYPETR-Bitcount. Only is instsalled in the system. # See samples at https://bitcount.typenetwork.com # Order a license at: https://store.typenetwork.com/foundry/typetr/fonts/bitcount USE_BITCOUNT = True LETTERS = 'ABCEFGHIJKLMNOPQRSTUVWXYZ' Frames = 80 W = H = 500 IMAGE_PATH = '_export/HorizonWorld.gif' if not USE_BITCOUNT or not 'BitcountMonoDouble-RegularCircle' in context.installedFonts( ): fontNames = ['Georgia-Bold', 'Georgia'] else: fontNames = [] for fontName in installedFonts(): if 'BitcountMono' in fontName and not 'Italic' in fontName: fontNames.append(fontName) letters = [] for n in range(10): c = choice(LETTERS) x = 0 y = 15 z = 20 + int(random() * 500) x = 1 / z + random() * 100 - 100 cc = random() * 0.8 + 0.1, random() * 0.1, random() * 0.8 * 0.1 f = choice(fontNames) letters.append((c, f, x, y, z, cc)) for n in range(Frames): context.newPage(W, H) context.fill(0.8) context.rect(0, 0, W, H) for c, f, x, y, z, (r, g, b) in letters: #y = y/z context.fill( (r, g, b) ) # Needs tuple, instead of separate r, g, b as in DrawBot context.font(f) context.stroke(None) fSize = min(200, 40000 / z) context.fontSize(fSize) context.text(c, (x + 250, y + 250 - fSize / 2)) context.fill(None) context.strokeWidth(0.5) context.stroke(0.5) context.line((0, 250), (500, 250)) context.fill( (1, 1, 1, 0.4) ) # Needs tuple, instead of separate r, g, b as in DrawBot context.rect(0, 0, W, H / 2 - 1) for n in range(0, 500, 10): context.fill(None) context.stroke(1) y = W / 2 - 2 - n * 0.4 lineThickness = (random() * 3 + 0.5) * (H / 2 - y) / 10 context.strokeWidth(lineThickness) context.line((0, y - lineThickness / 2), (W, y - lineThickness / 2)) context.saveImage(IMAGE_PATH)
from pagebot.contexts.flatcontext import FlatContext testContexts = ( (DrawBotContext(), '_export/testFlatString.pdf'), # TODO: Get this to work with Flat #(FlatContext(), '_export/testDrawBotString.pdf'), ) for context, path in testContexts: context.newPage(1000, 1000) leading = 24 for n in range(0, 1000, leading): context.stroke(1, 0, 0) context.fill(None) context.line((0, n),(1000,n)) fs1 = context.newString('') fs2 = context.newString('aaa vvv bbbbbb\nss' * 5, style=dict(fontSize=14, lineHeight=24)) appendS(fs1, fs2, 300, 24) bx, by, bw, bh = 50, 50, leading*3, 200#, leading*20 context.stroke(0) context.fill(None) context.rect(bx, by, bw, bh) Y = 100 bx, by, bw, bh = box = (100, Y, 400, 500) baselines = context.textBoxBaseLines(fs, box)
end = 16552 GLYPHS = ('e', 'H', 'O', 'Z') #GLYPHS = ('bullet', 'e','h', 'oe') #GLYPHS = sorted( cjkF.keys())[start:end] for name in GLYPHS: if name.startswith('.'): continue context.newPage(W, H) glyph = cjkF[name] context.save() context.transform((1, 0, 0, 1, 0, 150)) context.fill(None) context.stroke((0, 0, 0), 20) context.drawPath(glyph.path) context.line((0, 0), (1000, 0)) for index, p in enumerate(glyph.points): if p.onCurve: fs = context.newString('index', style=dict(fill=1, stroke=None, font='Verdana', fontSize=18)) tw, th = context.textSize(fs) context.fill(0) context.stroke(0) context.oval(p.x - 10, p.y - 10, 20, 20) context.text(fs, (p.x - tw / 2, p.y - th / 4)) else: bs = context.newString('index', style=dict(fill=(1, 1, 0),
align='left', fontSize=fittingSize, lineHeight=fittingSize)) fs += fittingWord c.newPage(W+G*2, H + G*2) myTextBox = c.TextBox(fs, G, G, W, H) myTextBox.draw() myTextBox._drawFrame() myTextBox._drawBaselines(showIndex=True, showY=True, showLeading=True) for pattern in myTextBox.findPattern('Find'): #print pattern px = pattern.x py = pattern.y print pattern print px, py[1] c.stroke(1, 0, 0) c.fill(None) c.oval(px-10, py[1]-10, 20, 20) # Bitcount measures, pixels are 1/10 of Em for yy in range(-3,10): c.stroke(1, 0, 0) c.fill(None) y = (myTextBox.y + myTextBox.h + yy*fittingSize/10 - myTextBox.baseLines[-1][1]) c.line((myTextBox.x, y), (myTextBox.x + myTextBox.w, y)) c.saveImage('_export/testTextLineTextRun.pdf')
style=dict(lineHeight=1, font=f.installedName, fontSize=12)) # Create DrawBotString, inheriting from BabelString, based on view type. bs = context.newString('Hlxg', style=dict(font=f.installedName, textFill=(1, 0, 0), fontSize=300, leading=320, baselineShift=200)) M = 20 context.fill(0.9) context.rect(M, M, 1000 - 2 * M, 800 - 2 * M) Y = 1000 - M BASE = (f.info.ascender + f.info.descender + f.info.lineGap) / 2 print('%s %s %s %s' % (f.info.familyName, f.info.styleName, 'Ascender + Descender + lineGap =', BASE)) YS = (BASE, ) print YS for y in YS: context.stroke(0) context.strokeWidth(0.5) context.line((0, y), (1000, y)) context.fill(0) context.stroke(None) context.textBox(bs, (M, M, 1000 - 2 * M, 400 - 2 * M))
def draw(w): u""" Draw 3 lines of text: the boundaries of with the width axis and the interpolated width from the slider value. If the slider goes of the extremes, then the middle line stops at the boundary width. """ d = fitVariableWidth(f, HEADLINE, w, HEADLINE_SIZE, condensedLocation, wideLocation) minWidth = d['condensedWidth'] maxWidth = d['wideWidth'] fixedWidth = minWidth + (maxWidth - minWidth) / 2 dFixed = fitVariableWidth(f, HEADLINE, fixedWidth, HEADLINE_SIZE, condensedLocation, wideLocation) c.newPage(W, H) y = 2 * PADDING c.fill(1) c.rect(0, 0, W, H) # Draw calculated fitting instance and the two boundary instances. c.text(d['condensedFs'], (PADDING, y + LEADING)) c.text(d['fs'], (PADDING, y + 2 * LEADING)) c.text(d['wideFs'], (PADDING, y + 3 * LEADING)) # Draw the instance choice of 3 if w < fixedWidth: c.text(d['condensedFs'], (PADDING, y)) elif w < maxWidth: c.text(dFixed['fs'], (PADDING, y)) else: c.text(d['wideFs'], (PADDING, y)) c.fill(0.5) c.fontSize(12) c.text('Variable Font Amstelvar (Maximum width)', (PADDING, y + 3 * LEADING + 40)) c.text('Variable Font Amstelvar (Calculated width)', (PADDING, y + 2 * LEADING + 40)) c.text('Variable Font Amstelvar (Minimum width)', (PADDING, y + LEADING + 40)) c.text('Traditional fixed font styles', (PADDING, y + 40)) # Draw vertical lines, marking the text headline widths and in read the # requested column width. Also draw the values of the column width and # the [wdth] axis value for that fitting location. c.fill(None) c.stroke(0) c.line((PADDING, PADDING), (PADDING, H - PADDING)) c.line((PADDING + d['condensedWidth'], PADDING), (PADDING + d['condensedWidth'], H - PADDING)) c.line((PADDING + d['width'], PADDING), (PADDING + d['width'], H - PADDING)) c.line((PADDING + d['wideWidth'], PADDING), (PADDING + d['wideWidth'], H - PADDING)) c.stroke(None) c.fill(0) c.text( '%d %0.2f' % (round(d['condensedWidth']), d['condensedLocation']['wdth']), (PADDING + d['condensedWidth'] + 5, PADDING)) c.text('%d %0.2f' % (round(d['width']), d['location']['wdth']), (PADDING + d['width'] + 5, PADDING)) c.text('%d %0.2f' % (round(d['wideWidth']), d['wideLocation']['wdth']), (PADDING + d['wideWidth'] + 5, PADDING)) c.stroke(1, 0, 0) c.line((PADDING + w, PADDING), (PADDING + w, H - PADDING)) c.stroke(None) c.fill(1, 0, 0) c.text('w=%d' % w, (PADDING + w + 5, H - PADDING - 5))