def fontToUFO(src, dst, fileType=None): from robofab.ufoLib import UFOWriter from robofab.pens.adapterPens import SegmentToPointPen if fileType is None: fileType = guessFileType(src) if fileType is None: raise ValueError, "Can't determine input file type" ufoWriter = UFOWriter(dst) if fileType == "TTF": from fontTools.ttLib import TTFont font = TTFont(src, 0) elif fileType == "Type 1": from fontTools.t1Lib import T1Font font = T1Font(src) else: assert 0, "unknown file type: %r" % fileType inGlyphSet = font.getGlyphSet() outGlyphSet = ufoWriter.getGlyphSet() for glyphName in inGlyphSet.keys(): print "-", glyphName glyph = inGlyphSet[glyphName] def drawPoints(pen): pen = SegmentToPointPen(pen) glyph.draw(pen) outGlyphSet.writeGlyph(glyphName, glyph, drawPoints) outGlyphSet.writeContents() if fileType == "TTF": info = extractTTFFontInfo(font) elif fileType == "Type 1": info = extractT1FontInfo(font) ufoWriter.writeInfo(info)
def combineKerning(path1, path2, destPath, WORRY=False): """ This is a rather nasty tool, but it does the job. Give it two UFOs that you want to combine the kerning from. It'll go through, and combine the kerning of two UFOs. If WORRY is set to True, it will enforce a rule that one can't add together kerning that has groups which contain different members. It finishes by writing out a 'dummy' UFO, one that contains no glyphs, but only the groups and kerning info for the combined kerning. One must go in a open the UFO package to grab the kerning and put in into a UFO with the glyphs combined. This way, at least, the source UFOs are not touched, incase one needs to beat a retreat to the source UFOs. """ ufo1 = UFOReader(path1) groups1 = ufo1.readGroups() kerning1 = ufo1.readKerning() ufo2 = UFOReader(path2) groups2 = ufo2.readGroups() kerning2 = ufo2.readKerning() combinedKerning = dict(kerning1) for pair, value in kerning2.items(): if pair in combinedKerning: assert value == combinedKerning[pair] combinedKerning[pair] = value combinedGroups = {} for groups in (groups1, groups2): for name, group in groups.items(): if not name.startswith("@MMK_"): continue if name in combinedGroups and WORRY: assert group == combinedGroups[name] combinedGroups[name] = group else: combinedGroups[name] = group ufo = UFOWriter(destPath) ufo.writeKerning(combinedKerning) ufo.writeGroups(combinedGroups)
def save(self, destDir=None, doProgress=False, formatVersion=2): """Save the Font in UFO format.""" # XXX note that when doing "save as" by specifying the destDir argument # _all_ glyphs get loaded into memory. This could be optimized by either # copying those .glif files that have not been edited or (not sure how # well that would work) by simply clearing out self._objects after the # save. from robofab.ufoLib import UFOWriter from robofab.tools.fontlabFeatureSplitter import splitFeaturesForFontLab # if no destination is given, or if # the given destination is the current # path, this is not a save as operation if destDir is None or destDir == self._path: saveAs = False destDir = self._path else: saveAs = True # start a progress bar nonGlyphCount = 5 bar = None if doProgress: from robofab.interface.all.dialogs import ProgressBar bar = ProgressBar("Exporting UFO", nonGlyphCount + len(self._object.keys())) # write writer = UFOWriter(destDir, formatVersion=formatVersion) try: # make a shallow copy of the lib. stuff may be added to it. fontLib = dict(self.lib) # info if bar: bar.label("Saving info...") writer.writeInfo(self.info) if bar: bar.tick() # kerning if self.kerning.changed or saveAs: if bar: bar.label("Saving kerning...") writer.writeKerning(self.kerning.asDict()) if bar: bar.tick() # groups if bar: bar.label("Saving groups...") writer.writeGroups(self.groups) if bar: bar.tick() # features if bar: bar.label("Saving features...") features = self.features.text if features is None: features = "" if formatVersion == 2: writer.writeFeatures(features) elif formatVersion == 1: classes, features = splitFeaturesForFontLab(features) if classes: fontLib["org.robofab.opentype.classes"] = classes.strip() + "\n" if features: featureDict = {} for featureName, featureText in features: featureDict[featureName] = featureText.strip() + "\n" fontLib["org.robofab.opentype.features"] = featureDict fontLib["org.robofab.opentype.featureorder"] = [featureName for featureName, featureText in features] if bar: bar.tick() # lib if formatVersion == 1: fontLib[postScriptHintDataLibKey] = self.psHints.asDict() if bar: bar.label("Saving lib...") writer.writeLib(fontLib) if bar: bar.tick() # glyphs glyphNameToFileNameFunc = self.getGlyphNameToFileNameFunc() glyphSet = writer.getGlyphSet(glyphNameToFileNameFunc) if len(self._scheduledForDeletion) != 0: if bar: bar.label("Removing deleted glyphs...") for glyphName in self._scheduledForDeletion: if glyphSet.has_key(glyphName): glyphSet.deleteGlyph(glyphName) if bar: bar.tick() if bar: bar.label("Saving glyphs...") count = nonGlyphCount if saveAs: glyphNames = self.keys() else: glyphNames = self._object.keys() for glyphName in glyphNames: glyph = self[glyphName] glyph.psHints._saveToLib(glyph.lib) glyph._saveToGlyphSet(glyphSet, glyphName=glyphName, force=saveAs) if bar and not count % 10: bar.tick(count) count = count + 1 glyphSet.writeContents() self._glyphSet = glyphSet # only blindly stop if the user says to except KeyboardInterrupt: bar.close() bar = None # kill the progress bar if bar: bar.close() # reset internal stuff self._path = destDir self._scheduledForDeletion = [] self.setChanged(False)
def save(self, destDir=None, doProgress=False, formatVersion=2): """Save the Font in UFO format.""" # XXX note that when doing "save as" by specifying the destDir argument # _all_ glyphs get loaded into memory. This could be optimized by either # copying those .glif files that have not been edited or (not sure how # well that would work) by simply clearing out self._objects after the # save. from robofab.ufoLib import UFOWriter from robofab.tools.fontlabFeatureSplitter import splitFeaturesForFontLab # if no destination is given, or if # the given destination is the current # path, this is not a save as operation if destDir is None or destDir == self._path: saveAs = False destDir = self._path else: saveAs = True # start a progress bar nonGlyphCount = 5 bar = None if doProgress: from robofab.interface.all.dialogs import ProgressBar bar = ProgressBar("Exporting UFO", nonGlyphCount + len(self._object.keys())) # write writer = UFOWriter(destDir, formatVersion=formatVersion) try: # make a shallow copy of the lib. stuff may be added to it. fontLib = dict(self.lib) # info if bar: bar.label("Saving info...") writer.writeInfo(self.info) if bar: bar.tick() # kerning if self.kerning.changed or saveAs: if bar: bar.label("Saving kerning...") writer.writeKerning(self.kerning.asDict()) if bar: bar.tick() # groups if bar: bar.label("Saving groups...") writer.writeGroups(self.groups) if bar: bar.tick() # features if bar: bar.label("Saving features...") features = self.features.text if features is None: features = "" if formatVersion == 2: writer.writeFeatures(features) elif formatVersion == 1: classes, features = splitFeaturesForFontLab(features) if classes: fontLib["org.robofab.opentype.classes"] = classes.strip( ) + "\n" if features: featureDict = {} for featureName, featureText in features: featureDict[featureName] = featureText.strip() + "\n" fontLib["org.robofab.opentype.features"] = featureDict fontLib["org.robofab.opentype.featureorder"] = [ featureName for featureName, featureText in features ] if bar: bar.tick() # lib if formatVersion == 1: fontLib[postScriptHintDataLibKey] = self.psHints.asDict() if bar: bar.label("Saving lib...") writer.writeLib(fontLib) if bar: bar.tick() # glyphs glyphNameToFileNameFunc = self.getGlyphNameToFileNameFunc() glyphSet = writer.getGlyphSet(glyphNameToFileNameFunc) if len(self._scheduledForDeletion) != 0: if bar: bar.label("Removing deleted glyphs...") for glyphName in self._scheduledForDeletion: if glyphSet.has_key(glyphName): glyphSet.deleteGlyph(glyphName) if bar: bar.tick() if bar: bar.label("Saving glyphs...") count = nonGlyphCount if saveAs: glyphNames = self.keys() else: glyphNames = self._object.keys() for glyphName in glyphNames: glyph = self[glyphName] glyph.psHints._saveToLib(glyph.lib) glyph._saveToGlyphSet(glyphSet, glyphName=glyphName, force=saveAs) if bar and not count % 10: bar.tick(count) count = count + 1 glyphSet.writeContents() self._glyphSet = glyphSet # only blindly stop if the user says to except KeyboardInterrupt: bar.close() bar = None # kill the progress bar if bar: bar.close() # reset internal stuff self._path = destDir self._scheduledForDeletion = [] self.setChanged(False)
def exportKerningFL(font, UFOfilepath): MMK_kernClasses = [] MMK_baseGlyph_Left = {} MMK_baseGlyph_Right = {} UFO = UFOWriter(UFOfilepath) kernClasses, kern_L_R_table, feaClasses = getKernStrukt(font) for glyphClass in kernClasses: MMK_glyphClass = glyphClass.replace('\'', '') MMK_Name_glyphClass, MMK_Content_glyphClass = MMK_glyphClass.split( ':')[0], MMK_glyphClass.split(':')[1] MMK_Base_Glyph = MMK_Content_glyphClass.split(' ')[1] leftClass, rightClass = kern_L_R_table[glyphClass] if (leftClass == 1) and (rightClass == 1): MMK_Name_glyphClass_L = '@MMK_L' + MMK_Name_glyphClass MMK_kernClasses.append( [MMK_Name_glyphClass_L, MMK_Content_glyphClass]) MMK_baseGlyph_Left[MMK_Base_Glyph] = MMK_Name_glyphClass_L MMK_Name_glyphClass_R = '@MMK_R' + MMK_Name_glyphClass MMK_kernClasses.append( [MMK_Name_glyphClass_R, MMK_Content_glyphClass]) MMK_baseGlyph_Right[MMK_Base_Glyph] = MMK_Name_glyphClass_R else: if leftClass == 1: MMK_Name_glyphClass = '@MMK_L' + MMK_Name_glyphClass MMK_baseGlyph_Left[MMK_Base_Glyph] = MMK_Name_glyphClass MMK_kernClasses.append( [MMK_Name_glyphClass, MMK_Content_glyphClass]) if rightClass == 1: MMK_Name_glyphClass = '@MMK_R' + MMK_Name_glyphClass MMK_baseGlyph_Right[MMK_Base_Glyph] = MMK_Name_glyphClass MMK_kernClasses.append( [MMK_Name_glyphClass, MMK_Content_glyphClass]) if (leftClass == 0) and (rightClass == 0): print 'WARNING! Wrong Kern group:', MMK_Name_glyphClass, '* NOT Left and NOT Right *. Please fix it.' for glyphClass in feaClasses: FEA_Name_glyphClass, FEA_Content_glyphClass = glyphClass.split( ':')[0], glyphClass.split(':')[1] MMK_kernClasses.append([FEA_Name_glyphClass, FEA_Content_glyphClass]) cycleCountColors = len(GROUP_COLORS) dicColors = {} groups = {} for index, gl in enumerate(MMK_kernClasses): content = gl[1].split(' ') nameClass = gl[0] content = checkContent(content) groups[nameClass] = content dicColors[nameClass] = GROUP_COLORS[index % cycleCountColors] font.lib[KEY_MMK_Colors] = dicColors font.update() UFO.writeGroups(groups) # TODO maybe need to compare UFO and VFB before overwriting font.LIB , and merge LIB if they are not equal UFO.writeLib(font.lib) kerntabl = font.kerning new_kern1 = {} new_kern2 = {} for (left, right), value in kerntabl.items(): #font.kerning.items(): if MMK_baseGlyph_Left.has_key(left): new_L = MMK_baseGlyph_Left[left] new_kern1[(new_L, right)] = value else: new_kern1[(left, right)] = value for (left, right), value in new_kern1.items(): #font.kerning.items(): if MMK_baseGlyph_Right.has_key(right): new_R = MMK_baseGlyph_Right[right] new_kern2[(left, new_R)] = value else: new_kern2[(left, right)] = value UFO.writeKerning(new_kern2) print 'Converting Classes and Kerning from Fontlab to MetricsMachine: DONE'
def exportKerningFL (font, UFOfilepath): MMK_kernClasses = [] MMK_baseGlyph_Left = {} MMK_baseGlyph_Right = {} UFO = UFOWriter(UFOfilepath) kernClasses, kern_L_R_table, feaClasses = getKernStrukt(font) for glyphClass in kernClasses: MMK_glyphClass = glyphClass.replace('\'', '') MMK_Name_glyphClass, MMK_Content_glyphClass = MMK_glyphClass.split(':')[0], MMK_glyphClass.split(':')[1] MMK_Base_Glyph = MMK_Content_glyphClass.split(' ')[1] leftClass, rightClass = kern_L_R_table[glyphClass] if (leftClass == 1) and (rightClass == 1): MMK_Name_glyphClass_L = '@MMK_L' + MMK_Name_glyphClass MMK_kernClasses.append([MMK_Name_glyphClass_L, MMK_Content_glyphClass]) MMK_baseGlyph_Left[MMK_Base_Glyph] = MMK_Name_glyphClass_L MMK_Name_glyphClass_R = '@MMK_R' + MMK_Name_glyphClass MMK_kernClasses.append([MMK_Name_glyphClass_R, MMK_Content_glyphClass]) MMK_baseGlyph_Right[MMK_Base_Glyph] = MMK_Name_glyphClass_R else: if leftClass == 1: MMK_Name_glyphClass = '@MMK_L' + MMK_Name_glyphClass MMK_baseGlyph_Left[MMK_Base_Glyph] = MMK_Name_glyphClass MMK_kernClasses.append([MMK_Name_glyphClass, MMK_Content_glyphClass]) if rightClass == 1: MMK_Name_glyphClass = '@MMK_R' + MMK_Name_glyphClass MMK_baseGlyph_Right[MMK_Base_Glyph] = MMK_Name_glyphClass MMK_kernClasses.append([MMK_Name_glyphClass, MMK_Content_glyphClass]) if (leftClass == 0) and (rightClass == 0): print 'WARNING! Wrong Kern group:', MMK_Name_glyphClass, '* NOT Left and NOT Right *. Please fix it.' for glyphClass in feaClasses: FEA_Name_glyphClass, FEA_Content_glyphClass = glyphClass.split(':')[0], glyphClass.split(':')[1] MMK_kernClasses.append([FEA_Name_glyphClass, FEA_Content_glyphClass]) cycleCountColors = len(GROUP_COLORS) dicColors = {} groups = {} for index, gl in enumerate(MMK_kernClasses): content = gl[1].split(' ') nameClass = gl[0] content = checkContent(content) groups[nameClass] = content dicColors[nameClass] = GROUP_COLORS[index % cycleCountColors] font.lib[KEY_MMK_Colors] = dicColors font.update() UFO.writeGroups(groups) # TODO maybe need to compare UFO and VFB before overwriting font.LIB , and merge LIB if they are not equal UFO.writeLib(font.lib) kerntabl = font.kerning new_kern1 = {} new_kern2 = {} for (left, right), value in kerntabl.items(): #font.kerning.items(): if MMK_baseGlyph_Left.has_key(left): new_L = MMK_baseGlyph_Left[left] new_kern1[(new_L, right)] = value else: new_kern1[(left, right)] = value for (left, right), value in new_kern1.items(): #font.kerning.items(): if MMK_baseGlyph_Right.has_key(right): new_R = MMK_baseGlyph_Right[right] new_kern2[(left, new_R)] = value else: new_kern2[(left, right)] = value UFO.writeKerning(new_kern2) print 'Converting Classes and Kerning from Fontlab to MetricsMachine: DONE'
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) # features print "exporting features.." glyphOrder = [] for nakedGlyph in f.naked().glyphs: glyph = RGlyph(nakedGlyph) glyphOrder.append(glyph.name) assert None not in glyphOrder, glyphOrder # We make a shallow copy if lib, since we add some stuff for export # that doesn't need to be retained in memory. fontLib = dict(f.lib)