def init(): DEBUG = False # Make True to see grid and element frames. FONT_PATH = pagebot.getFontPath() #fontPath = FONT_PATH + 'fontbureau/Decovar-VF-chained3.ttf' #fontPath = FONT_PATH + 'fontbureau/Decovar-VF-2axes.subset.ttf' #fontPath = FONT_PATH + 'fontbureau/Decovar-VF-2axes.ttf' fontPath = FONT_PATH + 'fontbureau/Decovar-VF-chained3.ttf' #fontPath = FONT_PATH + 'fontbureau/AmstelvarAlpha-Variations.ttf' fontPath = FONT_PATH + 'PromiseVar.ttf' #fontPath = FONT_PATH + 'BitcountGridVar.ttf' EXPORT_PATH = '_export/'+ fontPath.split('/')[-1].replace('ttf', 'pdf') varFont = Font(fontPath) varFontName = varFont.install() # Do DrawBot font install. axes = varFont.axes print axes RS = getRootStyle() RS['w'] = W = 600 RS['h'] = H = 600 M = 50
def getVariableFont(fontOrPath, location, install=True, styleName=None, normalize=True): u"""The variablesFontPath refers to the file of the source variable font. The nLocation is dictionary axis locations of the instance with values between (0, 1000), e.g. dict(wght=0, wdth=1000) or values between (0, 1), e.g. dict(wght=0.2, wdth=0.6). Set normalize to False if the values in location already are matching the axis min/max of the font. If there is a [opsz] Optical Size value defined, then store that information in the font.info.opticalSize. The optional *styleName* overwrites the *font.info.styleName* of the *ttFont* or the automatic location name.""" if isinstance(fontOrPath, basestring): varFont = Font(fontOrPath, name=path2FontName(fontOrPath)) else: varFont = fontOrPath fontName, path = generateInstance(varFont.path, location, targetDirectory=getInstancePath(), normalize=normalize) # Answer the generated Variable Font instance. Add [opsz] value if is defined in the location, otherwise None. return Font(path, name=fontName, install=install, opticalSize=location.get('opsz'), location=location, styleName=styleName)
def __init__(self, name, fonts=None, fontPaths=None, fontStyles=None): u"""The Family instance is a container of related Font instances. There are 3 levels of access: file name, style name (either from font.info.styleName or defined in fontStyles attributes) and by DrawBot name if the font is installed. The optional fonts is a list of Font() instances. The optional fontPaths is a list of file paths. The optional fontStyles is a dictionary with format dict(Regular=<fontPath>, Italic=<fontPath>, ...) One or multiple can be defined: fonts=None, fontPaths=None, fontStyles=None >>> familyName = 'Roboto' # We know this exists in the PageBot repository >>> families = guessFamiliesByPatterns(familyName) >>> family = families[familyName] >>> familyName in families.keys() True >>> family = families[familyName] >>> family.name u'Roboto' >>> font = family.findFont(weight='Regular') >>> font.info.styleName u'Regular' """ self.name = name self.fonts = {} # Key is font name. Value is Font instances. self.fontStyles = {} # Key is font.info.styleName. Value is list of fonts (there can be overlapping style names). self.installedFonts = {} # DrawBot name as key. Value is same Font instance. # If any font or font paths given, open the fonts. if fonts is not None: for font in fonts: self.addFont(font) if fontPaths is not None: for fontPath in fontPaths: self.addFont(Font(fontPath)) # Use file name as key if fontStyles is not None: for fontStyle, fontPath in fontStyles.items(): self.addFont(Font(fontPath), fontStyle=fontStyle)
def getFamilies(familyPaths): u"""Construct a dictionary of Family instances from dictionary familyPaths. It is assumed that all paths are valied to font files. Force key in family from dictionary familyPaths, instead of font.info.styleName. What is best practice? Keep as option? Example format of familyPaths dictionary: LIB_PATH = '/Library/Fonts/' SOME_SYSTEM_FONTS = { # Let's try some plain OSX system fonts, while they are still there (not variable yet). 'Georgia': dict(regular=LIB_PATH+'Georgia.ttf', bold=LIB_PATH+'Georgia Bold.ttf', italic=LIB_PATH+'Georgia Italic.ttf', boldItalic=LIB_PATH+'Georgia Bold Italic.ttf'), 'Verdana': dict(regular=LIB_PATH+'Verdana.ttf', bold=LIB_PATH+'Verdana Bold.ttf', italic=LIB_PATH+'Verdana Italic.ttf', boldItalic=LIB_PATH+'Verdana Bold Italic.ttf'), } """ families = {} for familyName, fontPaths in familyPaths.items(): if not familyName in families: families[familyName] = Family(familyName) for styleName, fontPath in fontPaths.items(): font = Font(fontPath, styleName) families[familyName].addFont( font, styleName ) # Force style name from dict, instead of font.info.styleName return families
def buildPages(self, doc): # Get the font varFont = Font(AmstelVarPath) # Build the pages, showing axes, samples, etc. print 'Variable A X E S' for axisName, (minValue, defaultValue, maxValue) in varFont.axes.items(): print axisName, 'minValue', minValue, 'defaultValue', defaultValue, 'maxValue', maxValue locations = self.getLocations(varFont) # Using the first page as cover (to be filled...) coverPage = doc[1] # Fill cover here. coverPage.rect(0, 0, W, H, fill=(1, 0, 0)) #coverPage.text(amstelVarName, x=PADDING, y=H-3*PADDING, style=dict(font=amstelVarName, fontSize=50, textColor=1) ) self.buildVariableMatrixPage(varFont, coverPage, locations, textFill=1) print 'Total amount of locations', len(locations) for n in range(NUM_PAGES): page = doc.newPage() self.buildVariableMatrixPage(varFont, page, locations)
def makeAnimatiom(): vMasterFont = Font(FONT_PATH) axes = vMasterFont.axes for sequence in getProofSequences(): for location in getLocations( axes, sequence): # Expand into a sequence of locations. newPage(W, H) fill(1) rect(0, 0, W, H) save() textColor = 0 for gIndex, glyph in enumerate(TEXT): # Only works by glyph name. drawGlyphPath(vMasterFont.ttFont, glyph, S * 40 + S * gIndex * 6 * 9, S * 22, location=location, s=S * 0.04, fillColor=textColor) # TODO To be extended PageBot #drawGlyphPaths(vMasterFont, TEXT, x=S*40 + S*gIndex*6*9, y=S*22, location=location, fontSize=S*0.04, fillColor=textColor) restore() fill(0) fontSize(24) text('%s %s' % (location['changed1'][0], location['changed2'][0]), (100, 20))
def addFont(self, pathOrFont): self._originFont = None # Reset to force new initialization of the property. if isinstance(pathOrFont, str): # If it is a path, then open a new Font instance. self._fonts[pathOrFont] = Font(pathOrFont) else: # Otherwise we assume it is a font, just add it to the dictionary. self._fonts[pathOrFont.path] = pathOrFont
def _get_parametricAxisFonts(self): """Generate the dictionary with parametric axis fonts. Key is the parametric axis name, value is the font instance (there can only be one font per axis). If the fonts don't exist as cached files, they are created. The font currently under self.defaultFont is used a neutral, for which all delta's are 0.""" origin = self.defaultFont if origin is None: return None # Create directory for the parametric axis fonts, if it does not exist. paFontDir = path2ParentPath(origin.path) + '/_export/@axes' if not os.path.exists(paFontDir): os.makedirs(paFontDir) for axisName in self.PARAMETRIC_AXES: self._parametricAxisFonts[axisName] = [] for extreme in ('_min', '_max'): fileNameParts = path2Name(origin.path).split('.') paFontPath = paFontDir + '/' + '.'.join( fileNameParts[:-1] ) + '@' + axisName + extreme + '.' + fileNameParts[-1] if os.path.exists(paFontPath): os.remove(paFontPath) shutil.copy(origin.path, paFontPath) self._parametricAxisFonts[axisName].append(Font(paFontPath)) self._parametricAxisMetrics[axisName] = origin.analyzer.stems return self._parametricAxisFonts
def makeAnimatiom(): vMasterFont = Font(FONT_PATH) axes = vMasterFont.axes print axes.keys() axisStates = {} for axisName, (minValue, defaultValue, maxValue) in axes.items(): axisStates[axisName] = newAxisState(axisName, minValue, defaultValue, maxValue) c1, c2, c3 = [1, 0.1, 0, 0.7], [0, 1, 0, 0.7], [0, 0, 1, 0.7] for n in range(0, FRAMES, STEP): newPage(W, H) fill(1) rect(0, 0, W, H) textColor = 0 """ for cIndex, c in enumerate((c1, c2, c3)): if cIndex == 0: c[0] = (1.5+openV[cIndex][0]/2)/2 #c[1] = (1+lineV[cIndex][0]/16)/2 #c[2] = (1+wghtV[cIndex][0]/16)/2 elif cIndex == 1: #c[0] = (1+rndoV[cIndex][0]/8)/2 c[1] = (1.2+rndiV[cIndex][0]/2)/2 #c[2] = (1+sqroV[cIndex][0]/8)/2 else: #c[0] = (1+rndoV[cIndex][0]/16)/2 #c[1] = (1+wghtV[cIndex][0]/16)/2 c[2] = (1.5+wghtV[cIndex][0]/2)/2 """ location = getNextLocation(axisStates) for gIndex, glyph in enumerate(TEXT): # Only works by glyph name. drawGlyphPath(vMasterFont.ttFont, glyph, S*40 + S*gIndex*6*9, S*22, location=location, s=S*0.04, fillColor=textColor)
def run(): LINE = 50 # Separator line. # F O N T S T U F F # Get the variable font. decovarPath = getFontPath() + '/fontbureau/Decovar-VF_2017-02-06.ttf' decovar = Font(decovarPath) if 1: # Font info stuff. # Font Info as in RoboFont objects print '-' * LINE print 'Family name:', decovar.info.familyName print 'Style name:', decovar.info.styleName print 'Path:', decovar.path print 'Units per em:', decovar.info.unitsPerEm if 1: # Variable stuff # Show the axes in this font. Key is axis name. Value is (minValue, defaultValue, maxValue) print '-' * LINE axes = decovar.axes # Get dictionary of axes in the font. print 'Axes (%d) in the font {name: (minValue, defaultValue, maxValue), ...}' % len( axes) print '.' * LINE print axes if 1: # Kerning stuff print '-' * LINE print 'Kerning (%d pairs) in %s' % (len( decovar.kerning), decovar.info.familyName) print '.' * LINE print decovar.kerning if 1: # Show the available tables in the TTFont print '-' * LINE print 'Tables in', decovar.info.familyName print '.' * LINE print decovar.ttFont.keys() # G L Y P H S T U F F if 1: g = decovar['A'] # Get the Glyph instance. print '-' * LINE print 'Glyph width of', g.name, g.width # Gets the value of ttFont['htmx'] print '.' * LINE print 'Add 10 to width and print again' g.width += 10 # We can change the value in the "live" font. f.save() print 'New width of', g.name, g.width print 'This give the interesting opportunity to let the page layout program alter values inside the font.' print 'if that is needed for a particular design.' if 1: # Info inside the TTGlyph structure. print '-' * LINE print 'help(g.ttGlyph)' print '.' * LINE help(g.ttGlyph)
def guessFamilies(styleNames): u"""Find the family relation of all fonts in the list. Note that this cannot be a 100% safe guess. Answer a dictionary with Family instances. Key is family name.""" families = {} # Keys is guessed family name. for styleName in styleNames: if styleName.startswith( '.' ): # Filter the system fonts that has a name with initial "." continue path = getFontPathOfFont(styleName) # Could have an extension like .ttf or .otf, by OSX system font don't have an extension. # o we just try to open the plain file and see how that goes. # Try to open the font in font tools, so we have access to a lot of information for our proof. # Create Style instance, as storage within our page composition passes. font = Font(path, styleName) if font.info is None: continue # Could not open the font file. # Skip if there is not a clear family name and style name derived from FontInfo if font.info.familyName and font.info.styleName: # Make a family collection of style names, if not already there. if not font.info.familyName in families: families[font.info.familyName] = Family(font.info.familyName) # Store the style name and path in the family collection. families[font.info.familyName].addFont(font) return families
def getFamilyFonts(familyName): # Collect the DrawBot names of all available fonts for the named family, that are installed in the system. fonts = {} # Dictionary, where key is the DrawBot font name, value is the OS path of the font file. for fontName in context.installedFonts(): # Answers complete list of all installed fonts. if familyName in fontName: # If this is a with with the familyName that we are looking for... fontPath = context.getFontPathOfFont(fontName) if fontPath is not None: fonts[fontName] = Font(fontPath) # Store the name and find the font path name. return fonts # Answer the dictionary. This is empty, if no Bitcount fonts are installed now.
def __init__(self, name, fontPaths=None, fontStyles=None): u"""The Family instance is a container of related Font instances. There are 3 levels of access: file name, style name (either from font.info.styleName or defined in fontStyles attributes) and by DrawBot name if the font is installed. The optional fontPaths is a list of file paths. The optional fontStyles is a dictionary with format dict(Regular=<fontPath>, Italic=<fontPath>, ...) """ assert fontPaths is None or fontStyles is None # If defined, cannot be defined both. self.name = name self.fonts = {} # Key is font name. Value is Font instances. self.fontStyles = {} # Key is font.info.styleName. Value is list of fonts (there can be overlapping style names). self.installedFonts = {} # DrawBot name as key. Value is same Font instance. # If any font paths given, open the fonts. if fontPaths is not None: for fontPath in fontPaths: self.addFont(Font(fontPath)) # Use file name as key elif fontStyles is not None: for fontStyle, fontPath in fontStyles.items(): self.addFont(Font(fontPath), fontStyle=fontStyle)
def makeDocument(fontPath): u"""Make a new document.""" f = Font(fontPath) # Get PageBot Font instance of Variable font. W = H = PageSize # Create a new document, default to the defined page size. doc = Document(w=W, h=H, originTop=False, title='Text Flow', autoPages=1) view = doc.getView() view.padding = 0 # Aboid showing of crop marks, etc. view.showPageCropMarks = True view.showPageRegistrationMarks = True view.showPageFrame = True view.showPagePadding = True view.showElementOrigin = False view.showElementDimensions = False # Get list of pages with equal y, then equal x. #page = doc[0][0] # Get the single page from te document. page = doc.getPage(0) # Get page on pageNumber, first in row (this is only one now). page.name = 'Page 1' page.padding = PagePadding fs = doc.context.newString(f.info.familyName + ' ' + f.info.styleName, style=dict(font=f.name, fontSize=18, textFill=0)) _, th = textSize(fs) title = newTextBox(fs, conditions=[Top2Top(), Fit2Width()], parent=page, h=th*1.2) circle = VariableCircle(f, s=GLYPH_NAME, name='VariableCircleSpeciment', parent=page, padding=4, x=100, fontSize=64, maxW=W-2*PagePadding, minW=100, showAxisName=True, # Conditions make the element move to top-left of the page. # And the condition that there should be no overflow, otherwise the text box # will try to solve it. conditions=[Float2Top(), Fit2Bottom(), Center2Center()], # Position of the origin of the element. Just to show where it is. # Has no effect on the position conditions. yAlign=BOTTOM, xAlign=LEFT, fill=CIRCLE_ELEMENT_FILL, borders=0, ) score = doc.solve() # Try to solve all pages. if score.fails: print score.fails # To avoid circular dependent conditions, we correct the position of the title # on left to that the position of the circle has become. title.pl = circle.x - page.pl return doc # Answer the doc for further doing.
def buildPages(self, doc): # Get the font varFont = Font(AmstelVarPath) # Build the pages, showing axes, samples, etc. print 'Variable A X E S' for axisName, (minValue, defaultValue, maxValue) in varFont.axes.items(): print axisName, 'minValue', minValue, 'defaultValue', defaultValue, 'maxValue', maxValue if SCATTER_SPECIMENS: locations = self.getLocations(varFont) # Using the first page as cover (to be filled...) coverPage = doc[1] # Fill cover here. coverPage.rect(0, 0, W, H, fill=(1, 0, 0)) coverPage.text(amstelVarName, x=PADDING, y=H - 3 * PADDING, style=dict(font=amstelVarName, fontSize=50, textColor=1)) self.buildVariableMatrixPage(varFont, coverPage, locations, textFill=1) print 'Total amount of locations', len(locations) for n in range(NUM_PAGES): page = doc.newPage() self.buildVariableMatrixPage(varFont, page, locations) elif MATRIX_SPECIMENS: # Build axis combinations on pages for axis1, axis2 in self.getAxisCombinations(): page = doc.newPage() wh = W - 2 * PADDING vCube = VariableCube(varFont, w=wh, h=wh, s='A', fontSize=72, dimensions={ axis1: 5, axis2: 5 }) page.place(vCube, 50, 100)
def __init__(self, name, path): u"""Answer a PreVarFamily instance from the defined design space path.""" self.designSpace = ds = DesignSpaceDocument() ds.read(path) self.axes = {} for axis in self.designSpace.axes: self.axes[axis.tag] = axis fonts = {} for source in ds.sources: fonts[source.path] = Font(source.path) Family.__init__(self, name=name, fonts=fonts) self._parametricAxisFonts = {} # Key is parametric axis name self._parametricAxisMetrics = {} # Collection of font metrics and calculated parameters. self._metrics = None # Initialized on property call self._defaultFont = None # Initialized on property call self._glyphNames = None # Set of all unique glyph names in all design space fonts self.baseGlyphName = self.BASE_GLYPH_NAME
def makeDocument(): u"""Make a new document.""" #W = H = 120 # Get the standard a4 width and height in points. W = H = PageSize #W, H = A4 doc = Document(w=W, h=H, originTop=False, autoPages=1) view = doc.getView() view.padding = 40 # Aboid showing of crop marks, etc. view.showPageCropMarks = True view.showPageRegistrationMarks = True view.showPageFrame = True view.showElementOrigin = True view.showElementDimensions = False # Get list of pages with equal y, then equal x. #page = doc[0][0] # Get the single page from te document. page = doc.getPage( 0) # Get page on pageNumber, first in row (this is only one now). page.name = 'This is a demo page for floating child elements' PATH = u"/Library/Fonts/Georgia.ttf" f = Font(PATH, install=False) #pathFilter = None glyphName = 'e' #'cid05405.1' e1 = GlyphPath(f[glyphName], stroke=None, h=600, fill=None, pathFilter=pathFilter, parent=page, font='Verdana', conditions=[Left2Left(), Float2Top()]) score = page.solve() if score.fails: print score.fails e1.y += 100 #e2.y += 100 return doc # Answer the doc for further doing.
def buildPages(self, doc): # Build the pages, showing axes, samples, etc. # Using the first page as cover (to be filled...) coverPage = doc[1] # Fill cover here. varFont = Font(DecovarPath) page = doc.newPage() self.buildVariablePage(varFont, page) if SCATTER_SPECIMENS: locations = self.getLocations(varFont) print 'Total amount of locations', len(locations) for n in range(20): page = doc.newPage() glyphName = choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ') scatter = VariableScatter(varFont, w=500, h=500, s=glyphName, showRecipe=True, sizeX=5, sizeY=5, fontSize=72, locations=locations) page.place(scatter, 50, 100) elif MATRIX_SPECIMENS: # Build axis combinations on pages for axis1, axis2 in self.getAxisCombinations(): page = doc.newPage() vCube = VariableCube(varFont, w=500, h=500, s='A', fontSize=72, dimensions={ axis1: 5, axis2: 5 }) page.place(vCube, 50, 100)
def guessFamiliesByPatterns(patterns): u"""Answer a dictionary family instances, where the fonts are selected to have the exclusive patterns in their file names. Note that this is not a guearantees safe method to combine font files into families, but it is useful of exemple purpose, in caes the available set of fonts on the platform is not known. After the fonts are selected by the pattern, the family name is taken from font.info.familyName. If patterns is single string, it will be included as list. >>> familyName = 'Roboto' # We know this exists in the PageBot repository >>> # For now we assume that this testing works in all contexts on all platforms. >>> families = guessFamiliesByPatterns(familyName) >>> familyName in families.keys() True >>> family = families[familyName] >>> family.name u'Roboto' >>> len(family.fonts) 18 >>> sorted(family.fonts.keys())[0] 'Roboto-Black.ttf' """ if not isinstance(patterns, (list, tuple)): patterns = [patterns] families = {} for fontFileName, fontPath in getFontPaths().items(): found = True for pattern in patterns: if not pattern in fontFileName: found = False break if found: font = Font(fontPath) familyName = font.info.familyName.split(' ')[0].split('-')[0] if not familyName in families: families[familyName] = Family(familyName, fonts=[font]) else: families[familyName].addFont(font) return families
#from pagebot.fonttoolbox.variationbuilder import generateInstance, drawGlyphPath from drawBot import fill, rect, oval, stroke, strokeWidth, installFont, installedFonts, FormattedString, moveTo, lineTo, newPath, drawPath #==================== DEBUG = False # Make True to see grid and element frames. FONT_PATH = pagebot.getFontPath() #fontPath = FONT_PATH + 'fontbureau/Decovar-VF-chained3.ttf' #fontPath = FONT_PATH + 'fontbureau/Decovar-VF-2axes.subset.ttf' #fontPath = FONT_PATH + 'fontbureau/Decovar-VF-2axes.ttf' fontPath = FONT_PATH + 'fontbureau/Decovar-VF-chained3.ttf' #fontPath = FONT_PATH + 'fontbureau/AmstelvarAlpha-Variations.ttf' #fontPath = FONT_PATH + 'PromiseVar.ttf' #fontPath = FONT_PATH + 'BitcountGridVar.ttf' EXPORT_PATH = '_export/' + fontPath.split('/')[-1].replace('ttf', 'pdf') varFont = Font(fontPath) varFontName = varFont.install() # Do DrawBot font install. axes = varFont.axes print axes RS = getRootStyle() RS['w'] = W = 600 RS['h'] = H = 600 M = 50 #==================== def makeAxisName(axisName): if not axisName in ('wght', 'wdth', 'opsz'): return axisName.upper()
import pagebot from pagebot.fonttoolbox.objects.font import Font, AXES from pagebot.fonttoolbox.variablefontbuilder import getVariableFont FONT_PATH = pagebot.getFontPath() fontPath = FONT_PATH + 'fontbureau/AmstelvarAlpha-VF.ttf' def printFontInfo(aFont): print '-' * 80 print 'Family name', aFont.info.familyName print 'Style name', aFont.info.styleName print 'Number of glyphs', len(font) if aFont.axes: print 'Number of axes', len(aFont.axes) for axisTag, axisValues in sorted(aFont.axes.items()): print '\t' + axisTag, axisValues, if axisTag in AXES: print AXES[axisTag]['name'], AXES[axisTag]['description'] else: print 'Unknown axis' else: print 'No Variable axes. This is a non-Variable font or an Variable instance.' # Usage of PageBot Font class. font = Font(fontPath) printFontInfo(font) # Create an instance instance = getVariableFont(font, dict(wdth=500, wght=200)) printFontInfo(instance)
# Demo version of # pagebot.fonttoolbox.variablefontbuilder.fitVariableWidth # to show usage and format of the answered dictionary. # # For real use, import the function as: # from pagebot.fonttoolbox.variablefontbuilder import fitVariableWidth # import copy from pagebot.contexts import defaultContext as context from pagebot import getRootPath from pagebot.fonttoolbox.objects.font import Font from pagebot.fonttoolbox.variablefontbuilder import getVariableFont ROOT_PATH = getRootPath() FONT_PATH = ROOT_PATH + '/Fonts/fontbureau/AmstelvarAlpha-VF.ttf' f = Font(FONT_PATH, install=True) # Get PageBot Font instance of Variable font. 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
#!/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))
# # Supporting usage of DrawBot, www.drawbot.com # Supporting usage of Flat, https://github.com/xxyxyz/flat # ----------------------------------------------------------------------------- # # UseGlyphBeamIntersection.py # # Implements a PageBot font classes to get info from a TTFont. # Show drawing of outline points and intersection beam with flattened path # from pagebot.fonttoolbox.objects.font import Font from pagebot.contexts.platform import getContext from __future__ import print_function newPage(1000, 1000) font = Font('/Library/Fonts/Georgia.ttf') print(font.analyzer ) print(font.analyzer.name ) glyphH = font['ampersand'] gaH = glyphH.analyzer print(gaH) print('H width:', gaH.width, gaH.glyph.width, glyphH.width) print('H bounding box:', gaH.boundingBox) # X position of vertical lines also includes sides of serifs. print('x-position of verticals:', sorted(gaH.verticals.keys())) # Y position of horizontal lines print('y-position of horizontals:', sorted(gaH.horizontals.keys())) c.stroke(0) c.fill(None) print(gaH.glyph.leftMargin)
import pagebot from pagebot.elements.page import Template # For Variable Fonts we can use the plain Font-->TTFont wrapper for all styles. No need to use Family. from pagebot.fonttoolbox.objects.font import Font from pagebot.publications.typespecimen import TypeSpecimen from pagebot.elements.variablefonts.variablecircle import VariableCircle DEBUG = False # Make True to see grid and element frames. OUTPUT_FILE = 'DecovarVariableCircle.pdf' FONT_PATH = pagebot.getFontPath() fontPath = FONT_PATH + 'fontbureau/Decovar-VF_2017-02-06.ttf' decovar = Font(fontPath) decovarName = decovar.install() # Do DrawBot font install. s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789' TERMINALS = ( 'trmA', 'trmB', 'trmC', 'trmD', 'trmE', 'trmF', 'trmG', 'trmH', 'trmF', 'trmG',
def getFont(fontName): u"""Answer the Font instance, so we can get more information about features, etc.""" print fontName return Font(fontNamePaths[fontName])
from pagebot.fonttoolbox.objects.font import Font from pagebot.contributions.adobe.kerndump.getKerningPairsFromOTF import OTFKernReader f = Font(u"/Library/Fonts/Upgrade-Medium.otf") print len(f.kerning) #print OTFKernReader(f.path).kerningPairs okr = OTFKernReader(f.path) okr.getClassPairs() okr.getSinglePairs() print okr.classPairs #print okr.singlePairs #print okr.pairPosList
# from pagebot.fonttoolbox.objects.font import Font from pagebot.fonttoolbox.analyzers.glyphanalyzer import GlyphAnalyzer from pagebot.toolbox.color import color EXPORT_PATH = '_export/testGlyphAnalyzer.pdf' FONT_PATH = '/Library/Fonts/' paths = [ FONT_PATH+'Verdana Bold.ttf', FONT_PATH+'Verdana.ttf', FONT_PATH+'Georgia Bold.ttf', FONT_PATH+'Georgia.ttf', ] for path in paths: font = Font(path) EM = font.info.unitsPerEm gaH = GlyphAnalyzer(font['H']) for gName in ('H', 'O'): newPage(EM, EM) translate(100, -font.info.descender) fontSize(24) text(path, (0, -EM/20)) ga = GlyphAnalyzer(font[gName]) #print(ga.glyph.points) #for contour in ga.glyph.flattenedPathPoints: # print('===Contour') # for p in contour:
import pagebot from pagebot.elements.pbpage import Template # For Variable Fonts we can use the plain Font-->TTFont wrapper for all styles. No need to use Family. from pagebot.fonttoolbox.objects.font import Font from pagebot.publications.typespecimen import TypeSpecimen from pagebot.elements.variablefonts.variablecircle import VariableCircle DEBUG = False # Make True to see grid and element frames. OUTPUT_FILE = 'DecovarVariableCircle.pdf' FONT_PATH = pagebot.getFontPath() fontPath = FONT_PATH + 'fontbureau/Decovar-VF_2017-02-06.ttf' decovar = Font(fontPath) decovarName = decovar.install() #print decovar.designSpace.variables['A'] print decovar.designSpace s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789' TERMINALS = ( 'trmA', 'trmB', 'trmC', 'trmD', 'trmE', 'trmF', 'trmG',
SKELETON_VALUES_S = ['None'] for v in SKELETON_VALUES: SKELETON_VALUES_S.append(str(v)) SKELETONS = ('sklA', 'sklB', 'sklD') BLEND_VALUES = (125, 250, 375, 500, 625, 750, 875, 1000) BLEND_VALUES_S = ['None'] for v in BLEND_VALUES: BLEND_VALUES_S.append(str(v)) BLENDS = ('bldA', 'bldB') WEIGHT_VALUES = (125, 250, 375, 500, 625, 750, 875, 1000) WEIGHT_VALUES_S = [] for v in WEIGHT_VALUES: WEIGHT_VALUES_S.append(str(v)) vMasterFont = Font(FONT_PATH) # ----------------------------------------------------------------- def makeAnimatiom(): axes = vMasterFont.axes print 'Variable A X E S' for axisName, (minValue, defaultValue, maxValue) in vMasterFont.axes.items(): print axisName, 'minValue', minValue, 'defaultValue', defaultValue, 'maxValue', maxValue location = getDefaultLocation(axes) if TERMINAL_VALUES_S[TerminalValue] != 'None': location[TERMINALS[TerminalShape]] = TERMINAL_VALUES[TerminalValue] if SKELETON_VALUES[SkeletonValue] != 'None': location[SKELETONS[SkeletonShape]] = SKELETON_VALUES[SkeletonValue]