def generateTTFs(self): """Build TTF for each font generated since last call to generateTTFs.""" fonts = [OpenFont(ufo) for ufo in self.generatedFonts] self.generatedFonts = [] log(">> Converting curves to quadratic") # using a slightly higher max error (e.g. 0.0025 em), dots will have # fewer control points and look noticeably different max_err = 0.002 if self.compatible: fonts_to_quadratic(fonts, max_err_em=max_err, dump_stats=True) else: for font in fonts: fonts_to_quadratic([font], max_err_em=max_err, dump_stats=True) log(">> Generating TTF files") for font in fonts: ttfName = self.generateOutputPath(font, "ttf") log(os.path.basename(ttfName)) for glyph in font: for contour in glyph: contour.reverseContour() saveOTF(font, ttfName, truetype=True)
def getLayer(nakedFont, message): numberOfLayers = nakedFont[0].layers_number - 1 layers = [] while numberOfLayers >= 0: layers.append(numberOfLayers) numberOfLayers = numberOfLayers - 1 whichLayer = OneList(layers, message) return int(whichLayer) fontToChange = CurrentFont() if not hasMM(fontToChange.naked()): Message('Font needs to be MM') else: orignalMetricsFont = OpenFont(None, "Which font's sidebearings do you want?") orignalMetrics = {} tickCount = len(orignalMetricsFont) bar = ProgressBar('Getting metrics', tickCount) tick = 0 if hasMM(orignalMetricsFont.naked()): layer = getLayer(orignalMetricsFont.naked(), 'Which layer do you want?') for glyph in orignalMetricsFont: advanceWidth = int(glyph.naked().GetMetrics(layer).x) glyphWidth = int(glyph.naked().GetBoundingRect(layer).width) glyphLeft = int(glyph.naked().GetBoundingRect(layer).x) glyphRight = advanceWidth - (glyphWidth + glyphLeft) orignalMetrics[glyph.name] = [glyphLeft, glyphRight] bar.tick(tick)
# robofab manual # Usepens howto # DigestPointStructurePen examples from robofab.world import OpenFont from robofab.pens.digestPen import DigestPointStructurePen f = OpenFont() myPen = DigestPointStructurePen() f['period'].drawPoints(myPen) print myPen.getDigest()
f[item["glyphName"]].draw(c) c.path.fill() #drawPath(c.path) restore() overprintImage.unlockFocus() # get drawbot to draw the image. image(overprintImage, (0,0)) ufoPath = u"wood/TypeMedia1314-WoodType.ufo" ufoPath = os.path.join(os.path.dirname(os.getcwd()), ufoPath) print os.path.exists(ufoPath) f = OpenFont(ufoPath) #names = f.keys() names = [ "D", "F", "H", "N", "S", "Z", "five", "eight", "Gcounter", "one_unit", "Acounter", "Ocounter", "ecounter", "half_unit", "Xcounter", "Ccounter"] names = [ "D", "F"] print names print f cm = 28.3464567 # points in 1 centimeter #a6width = 14.8*cm #a6height = 10.5*cm #size(a6width, a6height) size(3000,1000) fontSize = 100
def setup_fonts_to_quadratic_robofab(): return [[OpenFont(os.path.join(DATADIR, 'RobotoSubset-Regular.ufo'))], MAX_ERR_EM]
#FLM: RoboFab Intro, Interpolating two fonts # Basic interpolation of two fonts. This is clean # non-FontLab specific implementation of # interpolating. This interpolation is strict: it # adds no points to contours, it does not alter # the outlines of the extremes in any possible # way. Note that this works in FontLab as well as # NoneLab. # # In fontlab: select two .vfb files, the result will be a new .vfb # In NoneLab: select two .ufo files, the result will be a new .ufo from robofab.world import OpenFont, RFont, RGlyph from robofab.pens.pointPen import AbstractPointPen from robofab.interface.all.dialogs import GetFolder f = OpenFont(None, "First master") g = OpenFont(None, "Second master") factor = .5 d = RFont() d.interpolate(factor, f, g) path = GetFolder("Select a place to save this UFO") if path: d.save(path) print 'done'
# Description: # Compare Lowercase Proportions to other fonts # Credits: # Pablo Impallari # http://www.impallari.com from robofab.world import OpenFont, CurrentFont from robofab.interface.all.dialogs import Message # La fuente seleccionada es la que se va a modificar myfont = CurrentFont() # Pregunta de que fuente quiero copiar las proporciones orignalFont = OpenFont(None, "Which font's Proportions do you want?") original = {} # Rango de Glyphs que voy a medir uppercase = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] # Leo las n y obtengo el Ratio original_n = orignalFont['n'].width myfont_n = myfont['n'].width # Leo la fuente de origen for item in uppercase: if myfont.has_key(item): # Calculo Anchos ancho_original = orignalFont[item].width
def generateFont(self, mix, names, italic=False, swapSuffixes=None, stemWidth=185, italicMeanYCenter=-825, italicNarrowAmount=1): n = names.split("/") log("---------------------\n%s %s\n----------------------" % (n[0], n[1])) log(">> Mixing masters") if isinstance(mix, Mix): f = mix.generateFont(self.basefont) else: f = mix.copy() if italic == True: log(">> Italicizing") i = 0 for g in f: i += 1 if i % 10 == 0: print g.name if g.name == "uniFFFD": continue decomposeGlyph(f, g) removeGlyphOverlap(g) if g.name in self.lessItalic: italicizeGlyph(f, g, 9, stemWidth=stemWidth, meanYCenter=italicMeanYCenter, narrowAmount=italicNarrowAmount) elif g.name not in self.noItalic: italicizeGlyph(f, g, 10, stemWidth=stemWidth, meanYCenter=italicMeanYCenter, narrowAmount=italicNarrowAmount) if g.width != 0: g.width += 10 # set the oblique flag in fsSelection f.info.openTypeOS2Selection.append(9) if swapSuffixes != None: for swap in swapSuffixes: swapList = [g.name for g in f if g.name.endswith(swap)] for gname in swapList: print gname swapContours(f, gname.replace(swap, ""), gname) for gname in self.predecompose: if f.has_key(gname): decomposeGlyph(f, f[gname]) log(">> Generating glyphs") generateGlyphs(f, self.diacriticList, self.adobeGlyphList) log(">> Copying features") readFeatureFile(f, self.basefont.features.text) log(">> Decomposing") for g in f: if len(g.components) > 0: decomposeGlyph(f, g) # for gname in self.decompose: # if f.has_key(gname): # decomposeGlyph(f, f[gname]) copyrightHolderName = '' if self.config.has_option('main', 'copyrightHolderName'): copyrightHolderName = self.config.get('main', 'copyrightHolderName') def getcfg(name, fallback=''): if self.config.has_option('main', name): return self.config.get('main', name) else: return fallback setInfoRF( f, n, { 'foundry': getcfg('foundry'), 'foundryURL': getcfg('foundryURL'), 'designer': getcfg('designer'), 'copyrightHolderName': getcfg('copyrightHolderName'), 'build': self.buildTag, 'version': getcfg('version'), 'license': getcfg('license'), 'licenseURL': getcfg('licenseURL'), }) if not self.compatible: cleanCurves(f) deleteGlyphs(f, self.deleteList) log(">> Generating font files") ufoName = self.generateOutputPath(f, "ufo") f.save(ufoName) self.generatedFonts.append(ufoName) if self.buildOTF: log(">> Generating OTF file") newFont = OpenFont(ufoName) otfName = self.generateOutputPath(f, "otf") saveOTF(newFont, otfName, self.glyphOrder)
#!/usr/bin/python from ufo2ft import compileTTF from robofab.world import OpenFont family = "Tonnelier" weights = ["Regular", "Thin", "ThinItalic", "Light", "LightItalic", "Book", "BookItalic", "Medium", "MediumItalic", "Semibold", "SemiboldItalic", "Bold", "BoldItalic", "Heavy", "HeavyItalic"] for w in weights: ufo = OpenFont("source/{}-{}.ufo".format(family, w)) ttf = compileTTF(ufo, preProcessorClass=<class 'ufo2ft.preProcessor.TTFPreProcessor'>, outlineCompilerClass=<class 'ufo2ft.outlineCompiler.OutlineTTFCompiler'>, featureCompilerClass=<class 'ufo2ft.featureCompiler.FeatureCompiler'>, kernWriterClass=None, markWriterClass=None, featureWriters=None, glyphOrder=None, useProductionNames=None, convertCubics=True, cubicConversionError=None, reverseDirection=True, removeOverlaps=False, inplace=False), print ("Building " + "builds/{}-{}.ttf".format(family, w) + " from source file " + "source/{}-{}.ufo".format(family, w) + "...") ttf.save("builds/{}-{}.ttf".format(family, w)) print ("Done.")
def getGlyphOrder(fonts): gO_lengths = [] gO = [] for aFont in fonts: glyphOrder = [] if hasattr(aFont, 'glyphOrder'): glyphOrder = aFont.glyphOrder elif aFont.lib.has_key('public.glyphOrder'): glyphOrder = aFont.lib.get('public.glyphOrder') gO.append(glyphOrder) gO_lengths.append(len(glyphOrder)) index = gO_lengths.index(max(gO_lengths)) return gO[index] fonts = [OpenFont(ufoPath) for ufoPath in pathsToFonts] glyphOrder = getGlyphOrder(fonts) pageWidth = 595.276 pageHeight = 841.89 showMetrics = True showName = True showFrame = False showCell = False showGlyphBox = False infoFontName = '' #userGlyphKeys = ['a','b','c'] userGlyphKeys = [] frameBackgroundColor = (.1, .3, .5, .25) frameBorderColor = (0, 0, 0, .75)
def generateFont(self, mix, names, italic=False, swapSuffixes=None, stemWidth=185, kern=True): n = names.split("/") log("---------------------\n%s %s\n----------------------" % (n[0], n[1])) log(">> Mixing masters") if isinstance(mix, Mix): f = mix.generateFont(self.basefont) else: f = mix.copy() if italic == True: log(">> Italicizing") tweakAmmount = .085 narrowAmmount = .93 if names.find("Thin") != -1: tweakAmmount = .05 if names.find("Condensed") != -1: narrowAmmount = .96 i = 0 for g in f: i += 1 if i % 10 == 0: print g.name if g.name == "uniFFFD": continue # if i < 24: # continue # if i > 86: # for i,g in enumerate(fl.font.glyphs): # fl.UpdateGlyph(i) # # break # assert False # print g.name # if self.thinfont != None: # narrowFLGlyph(g,self.thinfont.getGlyph(g.name),factor=narrowAmmount) if g.name in self.lessItalic: italicizeGlyph(f, g, 9, stemWidth=stemWidth) elif False == (g.name in self.noItalic): italicizeGlyph(f, g, 10, stemWidth=stemWidth) #elif g.name != ".notdef": # italicizeGlyph(g, 10, stemWidth=stemWidth) if g.width != 0: g.width += 10 if swapSuffixes != None: for swap in swapSuffixes: swapList = [g.name for g in f if g.name.endswith(swap)] for gname in swapList: print gname swapContours(f, gname.replace(swap, ""), gname) for gname in self.predecompose: if f.has_key(gname): decomposeGlyph(f, gname) log(">> Generating glyphs") generateGlyphs(f, self.diacriticList, self.adobeGlyphList) log(">> Copying features") readFeatureFile(f, self.ot_classes + self.basefont.features.text) log(">> Decomposing") for gname in self.decompose: if f.has_key(gname): decomposeGlyph(f, gname) setNamesRF(f, n, foundry=self.config.get('main', 'foundry'), version=self.config.get('main', 'version')) cleanCurves(f) deleteGlyphs(f, self.deleteList) if kern: log(">> Generating kern classes") readFeatureFile(f, self.ot_kerningclasses) makeKernFeature(f, self.ot_kerningclasses) log(">> Generating font files") GenerateFeature_mark(f) GenerateFeature_mkmk(f) ufoName = self.generateOutputPath(f, "ufo") f.save(ufoName) if self.buildOTF: log(">> Generating OTF file") newFont = OpenFont(ufoName) otfName = self.generateOutputPath(f, "otf") builtSuccessfully = saveOTF(newFont, otfName, autohint=self.autohintOTF) if not builtSuccessfully: sys.exit(1) if self.buildTTF: log(">> Generating TTF file") import fontforge otFont = fontforge.open(otfName) otFont.generate(self.generateOutputPath(f, "ttf"))
#FLM: Check unopened font glyphs for MM # # Useful for testing to see if two fonts are compatible as as MM font # First import OpenFont, which allows the user open a font file # Also import RFont, so that a new font can be created from robofab.world import OpenFont, RFont # Get the two masters for the interpolated font minFont = OpenFont(None, "First font") maxFont = OpenFont(None, "Second font") for glyph in minFont: data = glyph.isCompatible(maxFont.getGlyph(glyph.name), report=True) print glyph print data print 'all done'
"""Correct contour direction for all glyphs in the font""" from robofab.world import OpenFont from robofab.interface.all.dialogs import ProgressBar font = OpenFont() bar = ProgressBar('Correcting contour direction...', len(font)) for glyph in font: bar.label(glyph.name) glyph.correctDirection() glyph.update() bar.tick() font.update() bar.close()
import os paths = [] for f in AllFonts(): paths.append(f.path) f.close() for p in paths: ufoPath = p.replace(".vfb", ".ufo") if os.path.exists(ufoPath): # the ufo exists, only export the glyphs and the features print "There is a UFO for this font already, exporting glyphs." path = os.path.join(os.path.dirname(ufoPath), os.path.basename(ufoPath), "glyphs") f = OpenFont(p) fl.CallCommand(fl_cmd.FontSortByCodepage) gs = GlyphSet(path, glyphNameToFileNameFunc=glyphNameToShortFileName) for g in f: print "saving glyph %s in %s"%(g.name, path) gs.writeGlyph(g.name, g, g.drawPoints) gs.writeContents() # make a new writer u = UFOWriter(ufoPath) # font info print "exporting font info.." u.writeInfo(f.info)
def run(): # if an input path is provided if len(sys.argv[1:] ) and sys.argv[1][0] != '-': # skip if it looks like an option baseFolderPath = sys.argv[1] if baseFolderPath[-1] == '/': # remove last slash if present baseFolderPath = baseFolderPath[:-1] # make sure the path is valid if not os.path.isdir(baseFolderPath): print >> sys.stderr, "ERROR: Invalid input folder\n\t%s" % baseFolderPath return # if an input path is not provided, use the current directory else: baseFolderPath = os.getcwd() # Load the options try: options = getOptions(baseFolderPath) except: return # Get paths to fonts and instances file fontPathsList, instancesFilePath = getFontPaths(baseFolderPath) if not len(fontPathsList): print >> sys.stderr, "ERROR: No UFO fonts were found in the path below\n\t%s" % baseFolderPath return # Handle the instances file if not instancesFilePath: print >> sys.stderr, "ERROR: Could not find the file named '%s' in the path below\n\t%s" % ( kInstancesDataFileName, baseFolderPath) return print "Parsing %s file..." % kInstancesDataFileName try: instancesList = readInstanceFile(instancesFilePath) except: print >> sys.stderr, "ERROR: Error parsing file or file is empty." return # Check the UFO file names masterIndexes = [] for ufoPath in fontPathsList: fileNameNoExtension, fileExtension = os.path.splitext(ufoPath) masterNumber = fileNameNoExtension.split('_')[-1] if masterNumber.isdigit(): masterIndexes.append(int(masterNumber)) if masterIndexes != range(len(fontPathsList)): print >> sys.stderr, "ERROR: The UFO master files are not named properly" return # Check the number of UFOs against the number of axes in the instances file axisNum = int(math.log(len(masterIndexes), 2)) for i in range(len(instancesList)): instanceDict = instancesList[i] axisVal = instanceDict[kCoordsKey] # Get AxisValues strings if axisNum != len(axisVal): print 'ERROR: The %s value for the instance named %s in the %s file is not compatible with the number of axis in the MM source font.' % ( kCoordsKey, instanceDict[kFontName], kInstancesDataFileName) return # XXX Only 1-axis MM space (two masters) is supported for now if len(fontPathsList) > 2: print >> sys.stderr, "ERROR: This script currently only supports 2 masters." return # Get the path to the output folder try: outputDirPath = options.outputPath if not os.path.isdir(outputDirPath): print >> sys.stderr, "ERROR: Invalid output folder\n\t%s" % outputDirPath return except AttributeError: # use the current folder to output the instances outputDirPath = baseFolderPath t1 = time.time() print "Reading %d UFO files..." % len(fontPathsList) ufoMasters = [OpenFont(ufoPath) for ufoPath in fontPathsList] totalInstances = len(instancesList) print "Generating %d instances..." % totalInstances for i in range(totalInstances): makeInstance((i + 1, totalInstances), ufoMasters, instancesList[i], outputDirPath, options) t2 = time.time() elapsedSeconds = t2 - t1 if (elapsedSeconds / 60) < 1: print 'Completed in %.1f seconds.' % elapsedSeconds else: print 'Completed in %.1f minutes.' % (elapsedSeconds / 60)
def importUFO(ufoPath, newFile=True, saveFile=True, closeFile=True, doInfo=True, doKerning=True, doGroups=True, doLib=True, doFeatures=True, doHints=False, doMarks=True, doMasks=True, glyphs=None): # get the VFB path vfbPath = os.path.splitext(ufoPath)[0] + ".vfb" if not newFile: font = None for font in AllFonts(): if font.path == vfbPath: break if font is None: if not os.path.exists(vfbPath): Message("Could not find the FontLab file \"%s\"." % os.path.basename(vfbPath)) return font = OpenFont(vfbPath) else: if saveFile: if os.path.exists(vfbPath): vfbPath = _findAvailablePathName(vfbPath) font = NewFont() # make the font the top font in FL fl.ifont = font.fontIndex # read the UFO font.readUFO(ufoPath, doHints=doHints, doInfo=doInfo, doKerning=doKerning, doGroups=doGroups, doLib=doLib, doFeatures=doFeatures, glyphs=glyphs) # load the masks and marks if doMasks or doMarks: for glyph in font: lib = glyph.lib if doMarks: if lib.has_key(MARK_LIB_KEY): glyph.mark = lib[MARK_LIB_KEY] del lib[MARK_LIB_KEY] if doMasks: if lib.has_key(MASK_LIB_KEY): # open a glyph window fl.EditGlyph(glyph.index) # switch to the mask layer fl.CallCommand(fl_cmd.ViewEditMask) # add the mask data instructions = lib[MASK_LIB_KEY] pen = glyph.getPointPen() instructionsDrawPoints(instructions, pen) # switch back to the edit layer fl.CallCommand(fl_cmd.ViewEditMask) # clear the mask data from the glyph lib del lib[MASK_LIB_KEY] # close all glyph windows. sometimes this actually works. fl.CallCommand(fl_cmd.WindowCloseAllGlyphWindows) # load the WWS names if doInfo: info = readPlist(os.path.join(ufoPath, "fontInfo.plist")) if "openTypeNameWWSFamilyName" in info: font.lib[WWS_FAMILY_KEY] = info["openTypeNameWWSFamilyName"] elif "openTypeNameWWSFamilyName" in font.lib: del font.lib[WWS_FAMILY_KEY] if "openTypeNameWWSSubfamilyName" in info: font.lib[WWS_SUBFAMILY_KEY] = info["openTypeNameWWSSubfamilyName"] elif "openTypeNameWWSSubfamilyName" in font.lib: del font.lib[WWS_SUBFAMILY_KEY] # update the font font.update() # save and close if saveFile: font.save(vfbPath) if closeFile: font.close()
def generateFont(self, mix, names, italic=False, swapSuffixes=None, stemWidth=185, kern=True): n = names.split("/") log("---------------------\n%s %s\n----------------------" % (n[0], n[1])) log(">> Mixing masters") if isinstance(mix, Mix): f = mix.generateFont(self.basefont) else: f = mix.copy() if italic == True: log(">> Italicizing") tweakAmmount = .085 narrowAmmount = .93 if names.find("Thin") != -1: tweakAmmount = .05 if names.find("Condensed") != -1: narrowAmmount = .96 i = 0 for g in f: i += 1 if i % 10 == 0: print g.name if g.name == "uniFFFD": continue removeGlyphOverlap(g) if g.name in self.lessItalic: italicizeGlyph(f, g, 9, stemWidth=stemWidth) elif False == (g.name in self.noItalic): italicizeGlyph(f, g, 10, stemWidth=stemWidth) #elif g.name != ".notdef": # italicizeGlyph(g, 10, stemWidth=stemWidth) if g.width != 0: g.width += 10 if swapSuffixes != None: for swap in swapSuffixes: swapList = [g.name for g in f if g.name.endswith(swap)] for gname in swapList: print gname swapContours(f, gname.replace(swap, ""), gname) for gname in self.predecompose: if f.has_key(gname): decomposeGlyph(f, gname) log(">> Generating glyphs") generateGlyphs(f, self.diacriticList, self.adobeGlyphList) log(">> Copying features") readFeatureFile(f, self.ot_classes + self.basefont.features.text) log(">> Decomposing") for gname in self.decompose: if f.has_key(gname): decomposeGlyph(f, gname) setNamesRF(f, n, foundry=self.config.get('main', 'foundry'), version=self.config.get('main', 'version')) if not self.compatible: cleanCurves(f) deleteGlyphs(f, self.deleteList) if kern: log(">> Generating kern classes") readFeatureFile(f, self.ot_kerningclasses) log(">> Generating font files") ufoName = self.generateOutputPath(f, "ufo") f.save(ufoName) self.generatedFonts.append(ufoName) if self.buildOTF: log(">> Generating OTF file") newFont = OpenFont(ufoName) otfName = self.generateOutputPath(f, "otf") saveOTF(newFont, otfName)
# robofab manual # Interpolate howto # Straight Interpolating examples from robofab.world import OpenFont minFont = OpenFont(pathToMinFont) maxFont = OpenFont(pathToMaxFont) # or any other way you like to get two font objects inbetweenFont = OpenFont(pathToInbetweenFont) # so now we have 3 font objects, right? inbetweenFont.interpolate(.5, minFont, maxFont) # presto, inbetweenFont is now 50% of one and 50% of the other inbetweenFont.interpolate((.92, .12), minFont, maxFont) # presto, inbetweenFont is now horizontally # vertically interpolated in different ways.
def makeDestination(root): macPath = os.path.join(root, 'FabFonts', 'ForMac') makeFolder(macPath) return macPath def generateOne(f, dstDir): print "generating %s" % f.info.fullName f.generate('otfcff', dstDir) f = GetFolder() if f is not None: paths = collectSources(f) dstDir = makeDestination(f) for f in paths: font = None print f try: font = OpenFont(f) generateOne(font, dstDir) finally: if font is not None: font.close(False) print 'done'
#FLM: RoboFab Intro, Font and Glyph Lib # # # demo of glyph properties # # from robofab.world import OpenFont # This is a specific test of some features which are probably # still only supported in one glyph in the DemoFont.ufo, # which you can find the robofab/Data/ folder. Here is goes. f = OpenFont(None, "") for c in f: if not c.properties.isEmpty(): print c.properties.dump() # This prints the available GlyphProperties objects. # Not very impressive at the moment, but it means # that at least they're getting stored with the glyphs # and that they can be read and interpreted.
from robofab.world import OpenFont path = "MyDrive/Folder1/Work/somefile" f = OpenFont(path) # hey look! it opens the file without asking.. print f
yAdvance += (UPM * _line_Height) * sc previousGlyph = None previousGlyphGroups = None restore() glyphStop = time() glyphDrawingTime += (glyphStop - glyphStart) * 1000 print 'average glyph drawing %0.2f ms, total %0.2f ms, %s glyphs drawn' % ( glyphDrawingTime / nbrOfGlyphs, glyphDrawingTime, nbrOfGlyphs) from robofab.world import OpenFont thisFont = OpenFont(ufoPath) typeSetter = TypeSetter(thisFont) typeSetter.canvas['margins'] = margins typeSetter.canvas['preset'](preset) typeSetter.type['size'] = pointSize typeSetter.type['_line_Height'] = _line_Height typeSetter.type['tracking'] = tracking typeSetter.type['color'] = color typeSetter.type['alpha'] = alpha typeSetter.settings['suffix'] = suffix typeSetter.settings['infoFont'] = infoFont typeSetter.settings['useKerning'] = useKerning typeSetter.settings['showKerning'] = showKerning