def prepareMathShapeUFO(narrow=500, wide=2500, upm=1000, familyName="MathShape", styleName="New"): f = NewFont(familyName=familyName, styleName=styleName) f.info.note = "This is a template font for a MathShape. The font names and glyph widths can all tbe changed." f.info.unitsPerEm = upm f.info.ascender = .75*upm f.info.descender = -.25*upm glyphs = [ ('narrow-thin', narrow), ('wide-thin', wide), ('narrow-bold',narrow), ('wide-bold', wide), ] names = [a for a, b in glyphs] f.lib['public.glyphOrder'] = names # draw bounds layer asc = f.info.ascender dsc = f.info.descender for name, width in glyphs: f.newGlyph(name) g = f[name] g.width = width boundsGlyph = g.getLayer('bounds', clear=True) pen = boundsGlyph.getPen() pen.moveTo((0,dsc)) pen.lineTo((g.width,dsc)) pen.lineTo((g.width,asc)) pen.lineTo((0,asc)) pen.closePath() g.update() # draw some sort of intro / test shape? thin = 5 thick = 100 for g in f: w = g.width if g.name.find("thin")!=-1: thin = 5 else: thin = 100 pen = g.getPen() pen.moveTo((0,dsc)) pen.lineTo((thin, dsc)) pen.lineTo((w, asc-thin)) pen.lineTo((w, asc)) pen.lineTo((w-thin,asc)) pen.lineTo((0,dsc+thin)) pen.closePath() pen.moveTo((0,asc)) pen.lineTo((0,asc-thin)) pen.lineTo((w-thin,dsc)) pen.lineTo((w,dsc)) pen.lineTo((w,dsc+thin)) pen.lineTo((thin,asc)) pen.closePath() return f # handle the saving in the UI
# robothon 2006 # batch interpolate import os from robofab.world import SelectFont, NewFont # ask for two masters to interpolate: font1 = SelectFont("Select font 1") font2 = SelectFont("Select font 2") # these are the interpolation factors: values = [.3, .6] for value in values: # make a new font destination = NewFont() # do the interpolation destination.interpolate(value, font1, font2, doProgress=True) destination.update() # make a new path + filename for the new font to be saved at: dir = os.path.dirname(font1.path) fileName = "Demo_%d.vfb" % (1000 * value) # save at this path and close the font destination.save(os.path.join(dir, fileName)) destination.close()
def globUFO(dir, filter=None): """Collect paths for all ufos in dir. Check for nested dirs. Optionally, select only ufos which match a filter string. """ ufo = [] names = os.listdir(dir) for n in names: p = os.path.join(dir, n) if n[-4:] == ".ufo": if filter is not None: if dir.find(filter) <> -1: ufo.append(p) else: ufo.append(p) continue if os.path.isdir(p): ufo += globUFO(p, filter) return ufo dir = GetFolder() ufo = globUFO(dir) for path in ufo: font = NewFont() font.readUFO(path, doProgress=True) font.update() vfbPath = path[:-4] + ".vfb" font.save(vfbPath) print 'DONE!'
from robofab.world import NewFont, OpenFont from robofab import plistlib import sys, os def ufoGlyphOrderSetter(existingOrder, newOrder): outOrder=[] for glyphName in newOrder: if glyphName not in existingOrder: outOrder.append(glyphName) return outOrder arguments=sys.argv fontList=arguments[2:] print "Merging fonts..." print os.getcwd() NewUFO = NewFont() font_source = OpenFont(fontList[0]) for glyphName in ufoGlyphOrderSetter([], font_source.keys()): glyph = font_source[glyphName] NewUFO.insertGlyph(glyph) print glyphName, NewUFO[glyphName].unicode = font_source[glyphName].unicode NewUFO.lib=font_source.lib NewUFO.info=font_source.info for font in fontList[1:]: source= OpenFont(font) for glyph_name in ufoGlyphOrderSetter(NewUFO.keys(), source.keys()): glyph = source[glyph_name] print glyph_name, NewUFO.insertGlyph(glyph)
from robofab.world import NewFont src1 = SelectFont('Select source font one:') if src1: src2 = SelectFont('Select source font two:') if src2: # collect a list of all compatible glyphs common = [] for glyphName in src1.keys(): if src2.has_key(glyphName): if src1[glyphName].isCompatible(src2[glyphName]): common.append(glyphName) common.sort() selName = OneList(common, 'Select a glyph:') if selName: dest = NewFont() g1 = src1[selName] g2 = src2[selName] count = 1 bar = ProgressBar('Interpolating...', 100) # add the sourec one glyph for reference dest.newGlyph(selName + '_000') dest[selName + '_000'].width = src1[selName].width dest[selName + '_000'].appendGlyph(src1[selName]) dest[selName + '_000'].mark = 1 dest[selName + '_000'].update() # add a new glyph and interpolate it while count != 100: factor = count * .01 newName = selName + '_' + ` count `.zfill(3) gD = dest.newGlyph(newName)
class FontStructionHandler(ContentHandler): """FSML parser""" def __init__(self): print 'FSML parser' def startElement(self, name, attrs): if name == 'fontstruction': print "parsing fsml..." # font info self.name = attrs.get('name') self.brick_scale_x = attrs.get('brick_scale_x') self.brick_scale_y = attrs.get('brick_scale_y') self.grid_scale_x = attrs.get('grid_scale_x') self.grid_scale_xgrid_scale_y = attrs.get( 'grid_scale_xgrid_scale_y') self.spacing = attrs.get('spacing') # glyphs self.glyphs = {} self.glyphCount = 0 self._tmpGlyph = "" # bricks self.bricks = {} self.brickCount = 0 # slots self.slots = {} elif name == 'glyph': glyphID = attrs.get('id') self.glyphs[glyphID] = {} self.glyphs[glyphID]['codepoint'] = attrs.get('codepoint') self.glyphs[glyphID]['nodes'] = [] self._tmpGlyph = glyphID elif name == 'node': glyphID = self._tmpGlyph br = attrs.get('br') x = attrs.get('x') y = attrs.get('y') self.glyphs[glyphID]['nodes'].append([str(br), (int(x), int(y))]) elif name == 'brick': brickID = attrs.get('id') self.bricks[brickID] = {} self.bricks[brickID]['name'] = attrs.get('name') self.bricks[brickID]['contours'] = attrs.get('contours') self.bricks[brickID]['user_id'] = attrs.get('user_id') elif name == 'palette_slot': brickPos = attrs.get('pos') self.slots[brickPos] = {} self.slots[brickPos]['brick_id'] = attrs.get('brick_id') self.slots[brickPos]['id'] = attrs.get('id') def endElement(self, name): if name == 'glyph': self.glyphCount = self.glyphCount + 1 if name == "fontstruction": print "...done." def printInfo(self): print "FontStruction name: %s" % self.name print "brick scale: %s, %s" % (self.brick_scale_x, self.brick_scale_y) print "glyphs: %s" % len(self.glyphs) def printGlyphs(self): for g in self.glyphs.keys(): print "glyph: %s" % g print "codepoint: %s" % self.glyphs[g]['codepoint'] print "nodes: %s" % self.glyphs[g]['nodes'] print def printBricks(self): for b in self.bricks.keys(): print "brick: %s" % b print "id: %s" % self.bricks[b]['id'] print "contours: %s" % self.bricks[b]['contours'] print def createUFO(self): # create new font self.f = NewFont() self.f.info.familyName = str(self.name) def importBricks(self): for brickID in self.bricks.keys(): # create element glyph gName = "element_%s" % str(brickID) self.f.newGlyph(gName, clear=True) self.f[gName].note = self.bricks[brickID]['name'] # get pen pen = self.f[gName].getPen() # parse SVG & draw with pen svgSource = self.bricks[brickID]['contours'] s = svgImporter(svgSource) for command in s._svg: svgCommand = command[0] points = command[1] if svgCommand == "M" or svgCommand == "m": pen.moveTo(points[0]) elif svgCommand == "L" or svgCommand == "l": pen.lineTo(points[0]) elif svgCommand == "Q" or svgCommand == "q": pen.qCurveTo(*points) pen.closePath() # scale & colorize bricks self.f[gName].scale((.125, .125)) #self.f[gName].mark = 30 self.f[gName].update() def parseGlyphs(self): missingBricks = [] eSize = 125 for g in self.glyphs.keys(): uni = int(self.glyphs[g]['codepoint']) # create empty glyph if unicode2psnames.has_key(uni): gName = unicode2psnames[uni] self.f.newGlyph(gName, clear=True) # append modules for node in self.glyphs[g]['nodes']: x, y = node[1][0] * eSize, node[1][1] * eSize zeroPos = str(int(node[0]) + 1) brickPos = zeroPos if self.slots.has_key(brickPos): componentName = "element_%s" % str( self.slots[brickPos]['brick_id']) #self.f[componentName].mark = 170 self.f[componentName].update() # append component self.f[gName].appendComponent(componentName, (x, y)) self.f[gName].update() else: if brickPos not in missingBricks: missingBricks.append(brickPos) self.f.update() print "missing bricks: %s" % missingBricks
def makeInstance(counter, ufoMasters, instanceInfo, outputDirPath, options): if len(ufoMasters) == 2: 'Linear interpolation with 2 masters' pass else: 'Linear interpolation with intermediate masters' ufoMasters = [master for master in ufoMasters if os.path.basename(master.path) in instanceInfo.get(kMasters)] try: faceName = instanceInfo[kFontName].split('-')[1] except IndexError: faceName = 'Regular' print print "%s (%d/%d)" % (faceName, counter[0], counter[1]) # Calculate the value of the interpolation factor # XXX It's currently assuming a 0-1000 axis interpolationFactor = instanceInfo[kCoordsKey][0]/1000.000 glyphOrder = ufoMasters[0].lib["public.glyphOrder"] # aGlyph.isCompatible(otherGlyph, report=True) # for glyphName in glyphOrder: # ufoMasters[0][glyphName].isCompatible(ufoMasters[1][glyphName], True) ufoInstance = NewFont() # Interpolate the masters # Documentation: http://www.robofab.org/howto/interpolate.html # aFont.interpolate(factor, minFont, maxFont, suppressError=True, analyzeOnly=False) # aFont.interpolate() interpolates: # - positions of components # - anchors # - ascender # - descender # - glyph widths for the whole font ufoInstance.interpolate(interpolationFactor, ufoMasters[0], ufoMasters[1]) # Round all the point coordinates to whole integer numbers ufoInstance.round() # Interpolate the kerning # Documentation: http://www.robofab.org/objects/kerning.html # f.kerning.interpolate(sourceDictOne, sourceDictTwo, value, clearExisting=True) if len(ufoMasters[0].kerning): ufoInstance.kerning.interpolate(ufoMasters[0].kerning, ufoMasters[1].kerning, interpolationFactor) ufoInstance.kerning.round(1) # convert the interpolated values to integers for glyphName in glyphOrder: ufoInstance[glyphName].unicode = ufoMasters[0][glyphName].unicode if len(ufoMasters[0][glyphName]) != len(ufoInstance[glyphName]): print "\tWARNING: Interpolation failed in glyph %s" % glyphName styleName = instanceInfo[kFullName].replace(instanceInfo[kFamilyName], '').strip() ufoInstance.info.styleName = styleName ufoInstance.info.familyName = instanceInfo[kFamilyName] ufoInstance.info.postscriptFontName = instanceInfo[kFontName] ufoInstance.info.postscriptFullName = instanceInfo[kFullName] ufoInstance.info.postscriptWeightName = instanceInfo[kWeight] ufoInstance.info.postscriptForceBold = True if instanceInfo[kIsBoldKey] else False ufoInstance.lib = ufoMasters[0].lib ufoInstance.groups = ufoMasters[0].groups ufoInstance.info.copyright = ufoMasters[0].info.copyright ufoInstance.info.trademark = ufoMasters[0].info.trademark ufoInstance.info.unitsPerEm = ufoMasters[0].info.unitsPerEm ufoInstance.info.versionMajor = ufoMasters[0].info.versionMajor ufoInstance.info.versionMinor = ufoMasters[0].info.versionMinor ufoInstance.info.postscriptIsFixedPitch = ufoMasters[0].info.postscriptIsFixedPitch # ascender if ufoMasters[0].info.ascender and ufoMasters[1].info.ascender: ufoInstance.info.ascender = int(round(objectsBase._interpolate(ufoMasters[0].info.ascender, ufoMasters[1].info.ascender, interpolationFactor))) # descender if ufoMasters[0].info.descender and ufoMasters[1].info.descender: ufoInstance.info.descender = int(round(objectsBase._interpolate(ufoMasters[0].info.descender, ufoMasters[1].info.descender, interpolationFactor))) # capHeight if ufoMasters[0].info.capHeight and ufoMasters[1].info.capHeight: ufoInstance.info.capHeight = int(round(objectsBase._interpolate(ufoMasters[0].info.capHeight, ufoMasters[1].info.capHeight, interpolationFactor))) # xHeight if ufoMasters[0].info.xHeight and ufoMasters[1].info.xHeight: ufoInstance.info.xHeight = int(round(objectsBase._interpolate(ufoMasters[0].info.xHeight, ufoMasters[1].info.xHeight, interpolationFactor))) # italicAngle if (ufoMasters[0].info.italicAngle != None) and (ufoMasters[1].info.italicAngle != None): ufoInstance.info.italicAngle = int(round(objectsBase._interpolate(ufoMasters[0].info.italicAngle, ufoMasters[1].info.italicAngle, interpolationFactor))) # postscriptUnderlinePosition if ufoMasters[0].info.postscriptUnderlinePosition and ufoMasters[1].info.postscriptUnderlinePosition: ufoInstance.info.postscriptUnderlinePosition = int(round(objectsBase._interpolate(ufoMasters[0].info.postscriptUnderlinePosition, ufoMasters[1].info.postscriptUnderlinePosition, interpolationFactor))) # postscriptUnderlineThickness if ufoMasters[0].info.postscriptUnderlineThickness and ufoMasters[1].info.postscriptUnderlineThickness: ufoInstance.info.postscriptUnderlineThickness = int(round(objectsBase._interpolate(ufoMasters[0].info.postscriptUnderlineThickness, ufoMasters[1].info.postscriptUnderlineThickness, interpolationFactor))) # postscriptBlueFuzz if (ufoMasters[0].info.postscriptBlueFuzz != None) and (ufoMasters[1].info.postscriptBlueFuzz != None): ufoInstance.info.postscriptBlueFuzz = int(round(objectsBase._interpolate(ufoMasters[0].info.postscriptBlueFuzz, ufoMasters[1].info.postscriptBlueFuzz, interpolationFactor))) # postscriptBlueScale if ufoMasters[0].info.postscriptBlueScale and ufoMasters[1].info.postscriptBlueScale: ufoInstance.info.postscriptBlueScale = objectsBase._interpolate(ufoMasters[0].info.postscriptBlueScale, ufoMasters[1].info.postscriptBlueScale, interpolationFactor) # postscriptBlueShift if ufoMasters[0].info.postscriptBlueShift and ufoMasters[1].info.postscriptBlueShift: ufoInstance.info.postscriptBlueShift = int(round(objectsBase._interpolate(ufoMasters[0].info.postscriptBlueShift, ufoMasters[1].info.postscriptBlueShift, interpolationFactor))) # postscriptBlueValues if len(ufoMasters[0].info.postscriptBlueValues) == len(ufoMasters[1].info.postscriptBlueValues): ufoMasters[0].info.postscriptBlueValues.sort() ufoMasters[1].info.postscriptBlueValues.sort() tempArray = [] for i in range(len(ufoMasters[0].info.postscriptBlueValues)): tempArray.append(int(round(objectsBase._interpolate(ufoMasters[0].info.postscriptBlueValues[i], ufoMasters[1].info.postscriptBlueValues[i], interpolationFactor)))) ufoInstance.info.postscriptBlueValues = tempArray # postscriptOtherBlues if len(ufoMasters[0].info.postscriptOtherBlues) == len(ufoMasters[1].info.postscriptOtherBlues): ufoMasters[0].info.postscriptOtherBlues.sort() ufoMasters[1].info.postscriptOtherBlues.sort() tempArray = [] for i in range(len(ufoMasters[0].info.postscriptOtherBlues)): tempArray.append(int(round(objectsBase._interpolate(ufoMasters[0].info.postscriptOtherBlues[i], ufoMasters[1].info.postscriptOtherBlues[i], interpolationFactor)))) ufoInstance.info.postscriptOtherBlues = tempArray # postscriptFamilyBlues if len(ufoMasters[0].info.postscriptFamilyBlues) == len(ufoMasters[1].info.postscriptFamilyBlues): ufoMasters[0].info.postscriptFamilyBlues.sort() ufoMasters[1].info.postscriptFamilyBlues.sort() tempArray = [] for i in range(len(ufoMasters[0].info.postscriptFamilyBlues)): tempArray.append(int(round(objectsBase._interpolate(ufoMasters[0].info.postscriptFamilyBlues[i], ufoMasters[1].info.postscriptFamilyBlues[i], interpolationFactor)))) ufoInstance.info.postscriptFamilyBlues = tempArray # postscriptFamilyOtherBlues if len(ufoMasters[0].info.postscriptFamilyOtherBlues) == len(ufoMasters[1].info.postscriptFamilyOtherBlues): ufoMasters[0].info.postscriptFamilyOtherBlues.sort() ufoMasters[1].info.postscriptFamilyOtherBlues.sort() tempArray = [] for i in range(len(ufoMasters[0].info.postscriptFamilyOtherBlues)): tempArray.append(int(round(objectsBase._interpolate(ufoMasters[0].info.postscriptFamilyOtherBlues[i], ufoMasters[1].info.postscriptFamilyOtherBlues[i], interpolationFactor)))) ufoInstance.info.postscriptFamilyOtherBlues = tempArray # postscriptStemSnapH if len(ufoMasters[0].info.postscriptStemSnapH) == len(ufoMasters[1].info.postscriptStemSnapH): ufoMasters[0].info.postscriptStemSnapH.sort() ufoMasters[1].info.postscriptStemSnapH.sort() tempArray = [] for i in range(len(ufoMasters[0].info.postscriptStemSnapH)): tempArray.append(int(round(objectsBase._interpolate(ufoMasters[0].info.postscriptStemSnapH[i], ufoMasters[1].info.postscriptStemSnapH[i], interpolationFactor)))) ufoInstance.info.postscriptStemSnapH = tempArray # postscriptStemSnapV if len(ufoMasters[0].info.postscriptStemSnapV) == len(ufoMasters[1].info.postscriptStemSnapV): ufoMasters[0].info.postscriptStemSnapV.sort() ufoMasters[1].info.postscriptStemSnapV.sort() tempArray = [] for i in range(len(ufoMasters[0].info.postscriptStemSnapV)): tempArray.append(int(round(objectsBase._interpolate(ufoMasters[0].info.postscriptStemSnapV[i], ufoMasters[1].info.postscriptStemSnapV[i], interpolationFactor)))) ufoInstance.info.postscriptStemSnapV = tempArray faceFolder = makeFaceFolder(outputDirPath, faceName) ufoPath = os.path.join(faceFolder, kFontInstanceFileName) # Save UFO instance if not options.noUFOs: print '\tSaving %s file...' % kFontInstanceFileName # Delete the old UFO file, if it exists while os.path.exists(ufoPath): shutil.rmtree(ufoPath) ufoInstance.save(ufoPath) # Generate 'kern' feature if options.genKernFeature: print "\tGenerating 'kern' feature..." WriteFeaturesKernFDK.KernDataClass(ufoInstance, faceFolder, options.minKern, options.writeTrimmed, options.writeSubtables) # Generate 'mark/mkmk' features if options.genMarkFeature: if options.genMkmkFeature: print "\tGenerating 'mark' and 'mkmk' features..." else: print "\tGenerating 'mark' feature..." WriteFeaturesMarkFDK.MarkDataClass(ufoInstance, faceFolder, options.trimCasingTags, options.genMkmkFeature, options.writeClassesFile, options.indianScriptsFormat) # Decompose and remove overlaps (using checkoutlines) if options.flatten: print '\tFlattening the glyphs...' if os.name == "nt": coTool = 'checkoutlines.cmd' else: coTool = 'checkoutlines' cmd = '%s -e "%s"' % (coTool, ufoPath) popen = Popen(cmd, shell=True, stdout=PIPE) popenout, popenerr = popen.communicate() if options.verboseMode: if popenout: print popenout if popenerr: print popenerr # Autohint if options.autohint: print '\tHinting the font...' cmd = 'autohint -q "%s"' % ufoPath popen = Popen(cmd, shell=True, stdout=PIPE) popenout, popenerr = popen.communicate() if options.verboseMode: if popenout: print popenout if popenerr: print popenerr
def createUFO(self): # create new font self.f = NewFont() self.f.info.familyName = str(self.name)
class FontStructionHandler(ContentHandler): '''FSML parser''' def __init__ (self): print 'FSML parser' def startElement(self, name, attrs): if name == 'fontstruction': print "parsing fsml..." # font info self.name = attrs.get('name') self.brick_scale_x = attrs.get('brick_scale_x') self.brick_scale_y = attrs.get('brick_scale_y') self.grid_scale_x = attrs.get('grid_scale_x') self.grid_scale_xgrid_scale_y = attrs.get('grid_scale_xgrid_scale_y') self.spacing = attrs.get('spacing') # glyphs self.glyphs = {} self.glyphCount = 0 self._tmpGlyph = "" # bricks self.bricks = {} self.brickCount = 0 # slots self.slots = {} elif name == 'glyph': glyphID = attrs.get('id') self.glyphs[glyphID] = {} self.glyphs[glyphID]['codepoint'] = attrs.get('codepoint') self.glyphs[glyphID]['nodes'] = [ ] self._tmpGlyph = glyphID elif name == 'node': glyphID = self._tmpGlyph br = attrs.get('br') x = attrs.get('x') y = attrs.get('y') self.glyphs[glyphID]['nodes'].append( [ str(br), ( int(x), int(y) ) ] ) elif name == 'brick': brickID = attrs.get('id') self.bricks[brickID] = {} self.bricks[brickID]['name'] = attrs.get('name') self.bricks[brickID]['contours'] = attrs.get('contours') self.bricks[brickID]['user_id'] = attrs.get('user_id') elif name == 'palette_slot': brickPos = attrs.get('pos') self.slots[brickPos] = {} self.slots[brickPos]['brick_id'] = attrs.get('brick_id') self.slots[brickPos]['id'] = attrs.get('id') def endElement(self, name): if name == 'glyph': self.glyphCount = self.glyphCount + 1 if name == "fontstruction": print "...done." def printInfo(self): print "FontStruction name: %s" % self.name print "brick scale: %s, %s" % ( self.brick_scale_x, self.brick_scale_y ) print "glyphs: %s" % len(self.glyphs) def printGlyphs(self): for g in self.glyphs.keys(): print "glyph: %s" % g print "codepoint: %s" % self.glyphs[g]['codepoint'] print "nodes: %s" % self.glyphs[g]['nodes'] print def printBricks(self): for b in self.bricks.keys(): print "brick: %s" % b print "id: %s" % self.bricks[b]['id'] print "contours: %s" % self.bricks[b]['contours'] print def createUFO(self): # create new font self.f = NewFont() self.f.info.familyName = str(self.name) def importBricks(self): for brickID in self.bricks.keys(): # create element glyph gName = "element_%s" % str(brickID) self.f.newGlyph(gName, clear=True) self.f[gName].note = self.bricks[brickID]['name'] # get pen pen = self.f[gName].getPen() # parse SVG & draw with pen svgSource= self.bricks[brickID]['contours'] s = svgImporter(svgSource) for command in s._svg: svgCommand = command[0] points = command[1] if svgCommand == "M" or svgCommand == "m": pen.moveTo( points[0] ) elif svgCommand == "L" or svgCommand == "l": pen.lineTo( points[0] ) elif svgCommand == "Q" or svgCommand == "q": pen.qCurveTo( *points ) pen.closePath() # scale & colorize bricks self.f[gName].scale((.125, .125)) #self.f[gName].mark = 30 self.f[gName].update() def parseGlyphs(self): missingBricks = [] eSize= 125 for g in self.glyphs.keys(): uni = int(self.glyphs[g]['codepoint']) # create empty glyph if unicode2psnames.has_key(uni): gName = unicode2psnames[uni] self.f.newGlyph(gName, clear=True) # append modules for node in self.glyphs[g]['nodes']: x, y = node[1][0]*eSize, node[1][1]*eSize zeroPos = str(int(node[0])+1) brickPos = zeroPos if self.slots.has_key(brickPos): componentName = "element_%s" % str(self.slots[brickPos]['brick_id']) #self.f[componentName].mark = 170 self.f[componentName].update() # append component self.f[gName].appendComponent(componentName, (x, y)) self.f[gName].update() else: if brickPos not in missingBricks: missingBricks.append(brickPos) self.f.update() print "missing bricks: %s" % missingBricks
# FLM: Import .ufo File into FontLab from robofab.world import NewFont from robofab.interface.all.dialogs import GetFileOrFolder path = GetFileOrFolder("Please select a .ufo") if path is not None: font = NewFont() font.readUFO(path, doProgress=True) font.update() print "DONE!"
from robofab.world import NewFont src1 = SelectFont('Select source font one:') if src1: src2 = SelectFont('Select source font two:') if src2: # collect a list of all compatible glyphs common = [] for glyphName in src1.keys(): if src2.has_key(glyphName): if src1[glyphName].isCompatible(src2[glyphName]): common.append(glyphName) common.sort() selName = OneList(common, 'Select a glyph:') if selName: dest = NewFont() g1 = src1[selName] g2 = src2[selName] count = 1 bar = ProgressBar('Interpolating...', 100) # add the sourec one glyph for reference dest.newGlyph(selName + '_000') dest[selName + '_000'].width = src1[selName].width dest[selName + '_000'].appendGlyph(src1[selName]) dest[selName + '_000'].mark = 1 dest[selName + '_000'].update() # add a new glyph and interpolate it while count != 100: factor = count * .01 newName = selName + '_' + `count`.zfill(3) gD = dest.newGlyph(newName)
# robothon06 # interpolate two fonts from robofab.world import SelectFont, NewFont from robofab.interface.all.dialogs import AskString font1 = SelectFont("Select font 1") font2 = SelectFont("Select font 2") value = AskString("What percentage?") value = int(value) * .01 destination = NewFont() # this interpolates the glyphs destination.interpolate(value, font1, font2, doProgress=True) # this interpolates the kerning # comment this line out of you're just testing destination.kerning.interpolate(font1.kerning, font2.kerning, value) destination.update()
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 makeInstance(counter, ufoMasters, instanceInfo, outputDirPath, options): try: faceName = instanceInfo[kFontName].split('-')[1] except IndexError: faceName = 'Regular' print print "%s (%d/%d)" % (faceName, counter[0], counter[1]) # Calculate the value of the interpolation factor # XXX It's currently assuming a 0-1000 axis interpolationFactor = instanceInfo[kCoordsKey][0] / 1000.000 glyphOrder = ufoMasters[0].lib["public.glyphOrder"] # aGlyph.isCompatible(otherGlyph, report=True) # for glyphName in glyphOrder: # ufoMasters[0][glyphName].isCompatible(ufoMasters[1][glyphName], True) ufoInstance = NewFont() # Interpolate the masters # Documentation: http://www.robofab.org/howto/interpolate.html # aFont.interpolate(factor, minFont, maxFont, suppressError=True, analyzeOnly=False) # aFont.interpolate() interpolates: # - positions of components # - anchors # - ascender # - descender # - glyph widths for the whole font ufoInstance.interpolate(interpolationFactor, ufoMasters[0], ufoMasters[1]) # Round all the point coordinates to whole integer numbers ufoInstance.round() # Interpolate the kerning # Documentation: http://www.robofab.org/objects/kerning.html # f.kerning.interpolate(sourceDictOne, sourceDictTwo, value, clearExisting=True) if len(ufoMasters[0].kerning): ufoInstance.kerning.interpolate(ufoMasters[0].kerning, ufoMasters[1].kerning, interpolationFactor) ufoInstance.kerning.round( 1) # convert the interpolated values to integers for glyphName in glyphOrder: ufoInstance[glyphName].unicode = ufoMasters[0][glyphName].unicode if len(ufoMasters[0][glyphName]) != len(ufoInstance[glyphName]): print "\tWARNING: Interpolation failed in glyph %s" % glyphName styleName = instanceInfo[kFullName].replace(instanceInfo[kFamilyName], '').strip() ufoInstance.info.styleName = styleName ufoInstance.info.familyName = instanceInfo[kFamilyName] ufoInstance.info.postscriptFontName = instanceInfo[kFontName] ufoInstance.info.postscriptFullName = instanceInfo[kFullName] ufoInstance.info.postscriptWeightName = instanceInfo[kWeight] ufoInstance.info.postscriptForceBold = True if instanceInfo[ kIsBoldKey] else False ufoInstance.lib = ufoMasters[0].lib ufoInstance.groups = ufoMasters[0].groups ufoInstance.info.copyright = ufoMasters[0].info.copyright ufoInstance.info.trademark = ufoMasters[0].info.trademark ufoInstance.info.unitsPerEm = ufoMasters[0].info.unitsPerEm ufoInstance.info.versionMajor = ufoMasters[0].info.versionMajor ufoInstance.info.versionMinor = ufoMasters[0].info.versionMinor ufoInstance.info.postscriptIsFixedPitch = ufoMasters[ 0].info.postscriptIsFixedPitch # ascender if ufoMasters[0].info.ascender and ufoMasters[1].info.ascender: ufoInstance.info.ascender = int( round( objectsBase._interpolate(ufoMasters[0].info.ascender, ufoMasters[1].info.ascender, interpolationFactor))) # descender if ufoMasters[0].info.descender and ufoMasters[1].info.descender: ufoInstance.info.descender = int( round( objectsBase._interpolate(ufoMasters[0].info.descender, ufoMasters[1].info.descender, interpolationFactor))) # capHeight if ufoMasters[0].info.capHeight and ufoMasters[1].info.capHeight: ufoInstance.info.capHeight = int( round( objectsBase._interpolate(ufoMasters[0].info.capHeight, ufoMasters[1].info.capHeight, interpolationFactor))) # xHeight if ufoMasters[0].info.xHeight and ufoMasters[1].info.xHeight: ufoInstance.info.xHeight = int( round( objectsBase._interpolate(ufoMasters[0].info.xHeight, ufoMasters[1].info.xHeight, interpolationFactor))) # italicAngle if (ufoMasters[0].info.italicAngle != None) and (ufoMasters[1].info.italicAngle != None): ufoInstance.info.italicAngle = int( round( objectsBase._interpolate(ufoMasters[0].info.italicAngle, ufoMasters[1].info.italicAngle, interpolationFactor))) # postscriptUnderlinePosition if ufoMasters[0].info.postscriptUnderlinePosition and ufoMasters[ 1].info.postscriptUnderlinePosition: ufoInstance.info.postscriptUnderlinePosition = int( round( objectsBase._interpolate( ufoMasters[0].info.postscriptUnderlinePosition, ufoMasters[1].info.postscriptUnderlinePosition, interpolationFactor))) # postscriptUnderlineThickness if ufoMasters[0].info.postscriptUnderlineThickness and ufoMasters[ 1].info.postscriptUnderlineThickness: ufoInstance.info.postscriptUnderlineThickness = int( round( objectsBase._interpolate( ufoMasters[0].info.postscriptUnderlineThickness, ufoMasters[1].info.postscriptUnderlineThickness, interpolationFactor))) # postscriptBlueFuzz if (ufoMasters[0].info.postscriptBlueFuzz != None) and (ufoMasters[1].info.postscriptBlueFuzz != None): ufoInstance.info.postscriptBlueFuzz = int( round( objectsBase._interpolate(ufoMasters[0].info.postscriptBlueFuzz, ufoMasters[1].info.postscriptBlueFuzz, interpolationFactor))) # postscriptBlueScale if ufoMasters[0].info.postscriptBlueScale and ufoMasters[ 1].info.postscriptBlueScale: ufoInstance.info.postscriptBlueScale = objectsBase._interpolate( ufoMasters[0].info.postscriptBlueScale, ufoMasters[1].info.postscriptBlueScale, interpolationFactor) # postscriptBlueShift if ufoMasters[0].info.postscriptBlueShift and ufoMasters[ 1].info.postscriptBlueShift: ufoInstance.info.postscriptBlueShift = int( round( objectsBase._interpolate( ufoMasters[0].info.postscriptBlueShift, ufoMasters[1].info.postscriptBlueShift, interpolationFactor))) # postscriptBlueValues if len(ufoMasters[0].info.postscriptBlueValues) == len( ufoMasters[1].info.postscriptBlueValues): ufoMasters[0].info.postscriptBlueValues.sort() ufoMasters[1].info.postscriptBlueValues.sort() tempArray = [] for i in range(len(ufoMasters[0].info.postscriptBlueValues)): tempArray.append( int( round( objectsBase._interpolate( ufoMasters[0].info.postscriptBlueValues[i], ufoMasters[1].info.postscriptBlueValues[i], interpolationFactor)))) ufoInstance.info.postscriptBlueValues = tempArray # postscriptOtherBlues if len(ufoMasters[0].info.postscriptOtherBlues) == len( ufoMasters[1].info.postscriptOtherBlues): ufoMasters[0].info.postscriptOtherBlues.sort() ufoMasters[1].info.postscriptOtherBlues.sort() tempArray = [] for i in range(len(ufoMasters[0].info.postscriptOtherBlues)): tempArray.append( int( round( objectsBase._interpolate( ufoMasters[0].info.postscriptOtherBlues[i], ufoMasters[1].info.postscriptOtherBlues[i], interpolationFactor)))) ufoInstance.info.postscriptOtherBlues = tempArray # postscriptFamilyBlues if len(ufoMasters[0].info.postscriptFamilyBlues) == len( ufoMasters[1].info.postscriptFamilyBlues): ufoMasters[0].info.postscriptFamilyBlues.sort() ufoMasters[1].info.postscriptFamilyBlues.sort() tempArray = [] for i in range(len(ufoMasters[0].info.postscriptFamilyBlues)): tempArray.append( int( round( objectsBase._interpolate( ufoMasters[0].info.postscriptFamilyBlues[i], ufoMasters[1].info.postscriptFamilyBlues[i], interpolationFactor)))) ufoInstance.info.postscriptFamilyBlues = tempArray # postscriptFamilyOtherBlues if len(ufoMasters[0].info.postscriptFamilyOtherBlues) == len( ufoMasters[1].info.postscriptFamilyOtherBlues): ufoMasters[0].info.postscriptFamilyOtherBlues.sort() ufoMasters[1].info.postscriptFamilyOtherBlues.sort() tempArray = [] for i in range(len(ufoMasters[0].info.postscriptFamilyOtherBlues)): tempArray.append( int( round( objectsBase._interpolate( ufoMasters[0].info.postscriptFamilyOtherBlues[i], ufoMasters[1].info.postscriptFamilyOtherBlues[i], interpolationFactor)))) ufoInstance.info.postscriptFamilyOtherBlues = tempArray # postscriptStemSnapH if len(ufoMasters[0].info.postscriptStemSnapH) == len( ufoMasters[1].info.postscriptStemSnapH): ufoMasters[0].info.postscriptStemSnapH.sort() ufoMasters[1].info.postscriptStemSnapH.sort() tempArray = [] for i in range(len(ufoMasters[0].info.postscriptStemSnapH)): tempArray.append( int( round( objectsBase._interpolate( ufoMasters[0].info.postscriptStemSnapH[i], ufoMasters[1].info.postscriptStemSnapH[i], interpolationFactor)))) ufoInstance.info.postscriptStemSnapH = tempArray # postscriptStemSnapV if len(ufoMasters[0].info.postscriptStemSnapV) == len( ufoMasters[1].info.postscriptStemSnapV): ufoMasters[0].info.postscriptStemSnapV.sort() ufoMasters[1].info.postscriptStemSnapV.sort() tempArray = [] for i in range(len(ufoMasters[0].info.postscriptStemSnapV)): tempArray.append( int( round( objectsBase._interpolate( ufoMasters[0].info.postscriptStemSnapV[i], ufoMasters[1].info.postscriptStemSnapV[i], interpolationFactor)))) ufoInstance.info.postscriptStemSnapV = tempArray faceFolder = makeFaceFolder(outputDirPath, faceName) ufoPath = os.path.join(faceFolder, kFontInstanceFileName) # Save UFO instance if not options.noUFOs: print '\tSaving %s file...' % kFontInstanceFileName # Delete the old UFO file, if it exists while os.path.exists(ufoPath): shutil.rmtree(ufoPath) ufoInstance.save(ufoPath) # Generate 'kern' feature if options.genKernFeature: print "\tGenerating 'kern' feature..." WriteFeaturesKernFDK.KernDataClass(ufoInstance, faceFolder, options.minKern, options.writeTrimmed, options.writeSubtables) # Generate 'mark/mkmk' features if options.genMarkFeature: if options.genMkmkFeature: print "\tGenerating 'mark' and 'mkmk' features..." else: print "\tGenerating 'mark' feature..." WriteFeaturesMarkFDK.MarkDataClass(ufoInstance, faceFolder, options.trimCasingTags, options.genMkmkFeature, options.writeClassesFile, options.indianScriptsFormat) # Decompose and remove overlaps (using checkoutlines) if options.flatten: print '\tFlattening the glyphs...' if os.name == "nt": coTool = 'checkoutlines.cmd' else: coTool = 'checkoutlines' cmd = '%s -e "%s"' % (coTool, ufoPath) popen = Popen(cmd, shell=True, stdout=PIPE) popenout, popenerr = popen.communicate() if options.verboseMode: if popenout: print popenout if popenerr: print popenerr # Autohint if options.autohint: print '\tHinting the font...' cmd = 'autohint -q "%s"' % ufoPath popen = Popen(cmd, shell=True, stdout=PIPE) popenout, popenerr = popen.communicate() if options.verboseMode: if popenout: print popenout if popenerr: print popenerr
def testUFOVersusGlifImport(self): font = NewFont() font.readUFO(getDemoFontPath(), doProgress=False) d1 = getDigests(font) font.close(False) font = NewFont() importAllGlifFiles(font.naked(), getDemoFontGlyphSetPath(), doProgress=False) d2 = getDigests(font) self.assertEqual(d1, d2) font.close(False)
"""Collect paths for all ufos in dir. Check for nested dirs. Optionally, select only ufos which match a filter string. """ ufo = [] names = os.listdir(dir) for n in names: p = os.path.join(dir, n) if n[-4:] == ".ufo": if filter is not None: if dir.find(filter) <> -1: ufo.append(p) else: ufo.append(p) continue if os.path.isdir(p): ufo += globUFO(p, filter) return ufo dir = GetFolder() ufo = globUFO(dir) for path in ufo: font = NewFont() font.readUFO(path, doProgress=True) font.update() vfbPath = path[:-4] + ".vfb" font.save(vfbPath) print 'DONE!'
def testTwoUntitledFonts(self): font1 = NewFont() font2 = NewFont() font1.unitsPerEm = 1024 font2.unitsPerEm = 2048 self.assertNotEqual(font1.unitsPerEm, font2.unitsPerEm) font1.update() font2.update() font1.close(False) font2.close(False)
font1 = SelectFont("Select font 1") font2 = SelectFont("Select font 2") where = GetFolder("Select a folder to save the interpolations") instances = [ ("Light", 0), ("NotTooLight", 0.25), ("Regular", 0.5), ("Demi", 0.75), ("Medium", 1), ] for thing in instances: name, value = thing print "generating", name, value dst = NewFont() # this interpolates the glyphs dst.interpolate(value, font1, font2, doProgress=True) # this interpolates the kerning # comment this line out of you're just testing #dst.kerning.interpolate(font1.kerning, font2.kerning, value) dst.info.familyName = "MyBigFamily" dst.info.styleName = name dst.info.autoNaming() dst.update() fileName = dst.info.familyName + "-" + dst.info.styleName + ".vfb" path = os.path.join(where, fileName) print 'saving at', path dst.save(path) dst.close()