def save(self): print "Saving font..." """ A real hack here. If the font format was less than 3, we need to save it with the original format. I care specifically about RoboFont, which can still read only format 2. However, dfont.save() will save the processed layer only if the format is 3. If I ask to save(formatVersion=3) when the dfont format is 2, then the save function will first mark all the glyphs in all the layers as being 'dirty' and needing to be saved. and also causes the defcon font.py:save to delete the original font and write everything anew. In order to avoid this, I reach into the defcon code and save only the processed glyphs layer. """ from ufoLib import UFOWriter writer = UFOWriter(self.dFont.path, formatVersion=2) if self.saveToDefaultLayer: self.dFont.save() else: layers = self.dFont.layers layer = layers[kProcessedGlyphsLayerName] writer._formatVersion = 3 writer.layerContents[kProcessedGlyphsLayerName] = kProcessedGlyphsLayer glyphSet = writer.getGlyphSet(layerName=kProcessedGlyphsLayerName, defaultLayer=False) writer.writeLayerContents(layers.layerOrder) writer._formatVersion = 2 layer.save(glyphSet) layer.dirty = False if self.fontType == kUFOFontType: self.ufoFontHashData.close() # Write the hash data, if it has changed. elif self.fontType == kType1FontType: cmd = "tx -t1 \"%s\" \"%s\"" % (self.tempUFOPath, self.fontPath) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout log = p.read() elif self.fontType == kCFFFontType: cmd = "tx -cff +b -std \"%s\" \"%s\"" % (self.tempUFOPath, self.fontPath) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout log = p.read() elif self.fontType == kOpenTypeCFFFontType: tempCFFPath = self.tempUFOPath + ".cff" cmd = "tx -cff +b -std \"%s\" \"%s\"" % (self.tempUFOPath, tempCFFPath) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout log = p.read() cmd = "sfntedit -a \"CFF \"=\"%s\" \"%s\"" % (tempCFFPath, self.fontPath) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout log = p.read() if os.path.exists(tempCFFPath): os.remove(tempCFFPath) else: print "Font type is unknown: cannot save changes" if (self.tempUFOPath != None) and os.path.exists(self.tempUFOPath): shutil.rmtree(self.tempUFOPath)
def save(self): print "Saving font..." """ A real hack here. If the font format was less than 3, we need to save it with the original format. I care specifically about RoboFont, which can still read only format 2. However, dfont.save() will save the processed layer only if the format is 3. If I ask to save(formatVersion=3) when the dfont format is 2, then the save function will first mark all the glyphs in all the layers as being 'dirty' and needing to be saved. and also causes the defcon font.py:save to delete the original font and write everything anew. In order to avoid this, I reach into the defcon code and save only the processed glyphs layer. """ from ufoLib import UFOWriter writer = UFOWriter(self.dFont.path, formatVersion=2) layers = self.dFont.layers layer = layers[kProcessedGlyphsLayerName] writer._formatVersion = 3 writer.layerContents[kProcessedGlyphsLayerName] = kProcessedGlyphsLayer glyphSet = writer.getGlyphSet(layerName=kProcessedGlyphsLayerName, defaultLayer=False) writer.writeLayerContents(layers.layerOrder) writer._formatVersion = 2 layer.save(glyphSet) layer.dirty = False if self.fontType == kUFOFontType: self.ufoFontHashData.hashMapChanged = True self.ufoFontHashData.close() # Write the hash data. elif self.fontType == kType1FontType: cmd = "tx -t1 \"%s\" \"%s\"" % (self.tempUFOPath, self.fontPath) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout log = p.read() elif self.fontType == kCFFFontType: cmd = "tx -cff +b -std \"%s\" \"%s\"" % (self.tempUFOPath, self.fontPath) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout log = p.read() elif self.fontType == kOpenTypeCFFFontType: tempCFFPath = self.tempUFOPath + ".cff" cmd = "tx -cff +b -std \"%s\" \"%s\"" % (self.tempUFOPath, tempCFFPath) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout log = p.read() cmd = "sfntedit -a \"CFF \"=\"%s\" \"%s\"" % (tempCFFPath, self.fontPath) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout log = p.read() if os.path.exists(tempCFFPath): os.remove(tempCFFPath) else: print "Font type is unknown: cannot save changes" if (self.tempUFOPath != None) and os.path.exists(self.tempUFOPath): shutil.rmtree(self.tempUFOPath)
def save(self, path): if path is None: path = self.path if os.path.abspath(self.path) != os.path.abspath(path): # If user has specified a path other than the source font path, # then copy the entire UFO font, and operate on the copy. log.info("Copying from source UFO font to output UFO font before " "processing...") if os.path.exists(path): shutil.rmtree(path) shutil.copytree(self.path, path) writer = UFOWriter(path, self._reader.formatVersion, validate=False) if self.hashMapChanged: self.writeHashMap(writer) self.hashMapChanged = False layer = PROCESSED_LAYER_NAME if self.writeToDefaultLayer: layer = None # Write glyphs. glyphset = writer.getGlyphSet(layer, defaultLayer=layer is None) for name, glyph in self.newGlyphMap.items(): filename = self.glyphMap[name] if not self.writeToDefaultLayer and \ name in self.processedLayerGlyphMap: filename = self.processedLayerGlyphMap[name] glyphset.contents[name] = filename glyphset.writeGlyph(name, glyph, glyph.drawPoints) glyphset.writeContents() # Write layer contents. layers = {DEFAULT_LAYER_NAME: DEFAULT_GLYPHS_DIRNAME} if self.processedLayerGlyphMap: layers[PROCESSED_LAYER_NAME] = PROCESSED_GLYPHS_DIRNAME writer.layerContents.update(layers) writer.writeLayerContents([DEFAULT_LAYER_NAME, PROCESSED_LAYER_NAME])
def save(self): print("Saving font...") """ A real hack here. If the font format was less than 3, we need to save it with the original format. I care specifically about RoboFont, which can still read only format 2. However, dfont.save() will save the processed layer only if the format is 3. If I ask to save(formatVersion=3) when the dfont format is 2, then the save function will first mark all the glyphs in all the layers as being 'dirty' and needing to be saved. and also causes the defcon font.py:save to delete the original font and write everything anew. In order to avoid this, I reach into the defcon code and save only the processed glyphs layer. I also set glyph_set.ufoFormatVersion so that the glif files will be set to format 1. """ from ufoLib import UFOWriter writer = UFOWriter(self.defcon_font.path, formatVersion=2) if self.save_to_default_layer: self.defcon_font.save() else: layers = self.defcon_font.layers layer = layers[PROCD_GLYPHS_LAYER_NAME] writer._formatVersion = 3 writer.layerContents[PROCD_GLYPHS_LAYER_NAME] = \ PROCD_GLYPHS_LAYER glyph_set = writer.getGlyphSet(layerName=PROCD_GLYPHS_LAYER_NAME, defaultLayer=False) writer.writeLayerContents(layers.layerOrder) glyph_set.ufoFormatVersion = 2 layer.save(glyph_set) layer.dirty = False if self.font_type == UFO_FONT_TYPE: # Write the hash data, if it has changed. self.ufo_font_hash_data.close() elif self.font_type == TYPE1_FONT_TYPE: cmd = "tx -t1 \"%s\" \"%s\"" % (self.temp_ufo_path, self.font_path) subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) elif self.font_type == CFF_FONT_TYPE: cmd = "tx -cff +b -std \"%s\" \"%s\"" % (self.temp_ufo_path, self.font_path) subprocess.call(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) elif self.font_type == OPENTYPE_CFF_FONT_TYPE: temp_cff_path = self.temp_ufo_path + ".cff" cmd = "tx -cff +b -std \"%s\" \"%s\"" % (self.temp_ufo_path, temp_cff_path) subprocess.call(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) cmd = "sfntedit -a \"CFF \"=\"%s\" \"%s\"" % (temp_cff_path, self.font_path) subprocess.call(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if os.path.exists(temp_cff_path): os.remove(temp_cff_path) else: print("Font type is unknown: cannot save changes") if (self.temp_ufo_path is not None) \ and os.path.exists(self.temp_ufo_path): shutil.rmtree(self.temp_ufo_path)
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 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 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)
existingFont = fontforge.open(existingFontPath) existingGlyphNames = set(existingFont.__iter__()) justInSource = sourceGlyphNames - existingGlyphNames # print 'glyphs in both:', sourceGlyphNames & existingGlyphNames # print 'glyphs only in source:', justInSource filtered = [name for name in justInSource if isValid(name)] overlapping = [name for name in (sourceGlyphNames & existingGlyphNames) if isValid(name)] print 'from the latin and valid:', sorted(filtered) print '------------------' print 'overlapping and valid', sorted(overlapping) writer = UFOWriter('sources/jomhuria-latin.ufo', formatVersion=2) newGlypsSet = writer.getGlyphSet() for glyphName in filtered + overlapping: # note how incestuous Glyph and GlyphSet interact. glyph = Glyph(glyphName, sourceGlyphSet) # this reads just the attributes sourceGlyphSet.readGlyph(glyphName, glyph) newGlypsSet.writeGlyph( glyphName , glyphObject=glyph , drawPointsFunc=glyph.drawPoints ) # after writing glyphs write the contents.plist newGlypsSet.writeContents()