def importAllGlifFiles(font, dirName=None, doProgress=True, bar=None): """import all GLIFs into a FontLab font""" if dirName is None: if font.file_name: dir, base = os.path.split(font.file_name) base = base.split(".")[0] + ".glyphs" dirName = os.path.join(dir, base) else: dirName = GetFolder("Please select a folder with .glif files") glyphSet = GlyphSet(dirName) glyphNames = glyphSet.keys() glyphNames.sort() barStart = 0 closeBar = False if doProgress: if not bar: bar = ProgressBar("Importing Glyphs", len(glyphNames)) closeBar = True else: barStart = bar.getCurrentTick() else: bar = None try: for i in range(len(glyphNames)): #if not (i % 10) and not bar.tick(barStart + i): # raise KeyboardInterrupt glyphName = glyphNames[i] flGlyph = NewGlyph(font, glyphName, clear=True) pen = FLPointPen(flGlyph) glyph = GlyphPlaceholder() glyphSet.readGlyph(glyphName, glyph, pen) if hasattr(glyph, "width"): flGlyph.width = int(round(glyph.width)) if hasattr(glyph, "unicodes"): flGlyph.unicodes = glyph.unicodes if hasattr(glyph, "note"): flGlyph.note = glyph.note # XXX must encode if hasattr(glyph, "lib"): from cStringIO import StringIO from robofab.plistlib import writePlist lib = glyph.lib if lib: if len(lib) == 1 and "org.robofab.fontlab.customdata" in lib: data = lib["org.robofab.fontlab.customdata"].data else: f = StringIO() writePlist(glyph.lib, f) data = f.getvalue() flGlyph.customdata = data # XXX the next bit is only correct when font is the current font :-( fl.UpdateGlyph(font.FindGlyph(glyphName)) if bar and not i % 10: bar.tick(barStart + i) except KeyboardInterrupt: if bar: bar.close() bar = None fl.UpdateFont(FontIndex(font)) if bar and closeBar: bar.close()
def exportGlyphs(font, glyphs=None, dest=None, doProgress=True, bar=None): """Export all glyphs in a FontLab font""" if dest is None: dir, base = os.path.split(font.file_name) base = base.split(".")[0] + ".glyphs" dest = os.path.join(dir, base) if not os.path.exists(dest): os.makedirs(dest) glyphSet = GlyphSet(dest) if glyphs is None: indices = range(len(font)) else: indices = [] for glyphName in glyphs: indices.append(font.FindGlyph(glyphName)) barStart = 0 closeBar = False if doProgress: if not bar: bar = ProgressBar("Exporting Glyphs", len(indices)) closeBar = True else: barStart = bar.getCurrentTick() else: bar = None try: done = {} for i in range(len(indices)): #if not (i % 10) and not bar.tick(i + barStart): # raise KeyboardInterrupt index = indices[i] flGlyph = font[index] if flGlyph is None: continue glyphName = flGlyph.name if not glyphName: print "can't dump glyph #%s, it has no glyph name" % i else: if glyphName in done: n = 1 while ("%s#%s" % (glyphName, n)) in done: n += 1 glyphName = "%s#%s" % (glyphName, n) done[glyphName] = None exportGlyph(glyphName, flGlyph, glyphSet) if bar and not i % 10: bar.tick(barStart + i) # Write out contents.plist glyphSet.writeContents() except KeyboardInterrupt: if bar: bar.close() bar = None if bar and closeBar: bar.close()
def clearAnchors(self, doProgress=True): """clear all anchors in the font""" tickCount = len(self.font) if doProgress: bar = ProgressBar("Cleaning all anchors...", tickCount) tick = 0 for glyphName in self.accentList: if doProgress: bar.label(glyphName) baseName, stripedSuffixName, accentNames, errors = nameBuster(glyphName, self.glyphConstructions) existError = False if len(errors) > 0: existError = True if not existError: toClear = [baseName] for accent, position in accentNames: toClear.append(accent) for glyphName in toClear: try: self.font[glyphName].clearAnchors() except IndexError: pass if doProgress: bar.tick(tick) tick = tick+1 if doProgress: bar.close()
def buildAccents(self, clear=True, adjustWidths=True, markGlyph=True, doProgress=True): """build accented glyphs. some flag definitions: clear=1 clear the glyphs if they already exist markGlyph=1 mark the glyph that is created doProgress=1 show a progress bar adjustWidths=1 will fix right and left margins when left or right accents are added""" tickCount = len(self.accentList) if doProgress: bar = ProgressBar('Building accented glyphs...', tickCount) tick = 0 for glyphName in self.accentList: if doProgress: bar.label(glyphName) existError = False anchorError = False baseName, stripedSuffixName, accentNames, errors = nameBuster(glyphName, self.glyphConstructions) if len(errors) > 0: existError = True for accentError in errors: self.accentErrors.append(accentError) if not existError: baseAnchors = [] try: self.font[baseName] except IndexError: self.accentErrors.append('%s: %s does not exist.'%(glyphName, baseName)) existError = True else: for anchor in self.font[baseName].anchors: baseAnchors.append(anchor.name) for accentName, accentPosition in accentNames: accentAnchors = [] try: self.font[accentName] except IndexError: self.accentErrors.append('%s: %s does not exist.'%(glyphName, accentName)) existError = True else: for anchor in self.font[accentName].getAnchors(): accentAnchors.append(anchor.name) if accentPosition not in baseAnchors: self.accentErrors.append('%s: %s not in %s anchors.'%(glyphName, accentPosition, baseName)) anchorError = True if ''.join(['_', accentPosition]) not in accentAnchors: self.accentErrors.append('%s: %s not in %s anchors.'%(glyphName, ''.join(['_', accentPosition]), accentName)) anchorError = True if not existError and not anchorError: destination = self.font.compileGlyph(glyphName, baseName, self.glyphConstructions[stripedSuffixName][1:], adjustWidths) if markGlyph: destination.mark = accentColor if doProgress: bar.tick(tick) tick = tick+1 if doProgress: bar.close()
def dump(font): filePath = checkPath(font.path[:-4] + ".txt") if filePath is not None: tickCount = len(font) bar = ProgressBar('Writing dump file', tickCount) tick = 0 outList = [] for glyph in font: bar.tick(tick) tick = tick+1 if len(glyph.components) != 0: output = glyph.name + ';' + str(glyph.width) componentNumber = 0 while componentNumber < len(glyph.components): x, y = glyph.components[componentNumber].offset output = output + ';' + glyph.components[componentNumber].baseGlyph + ';' + str(x) + ';' + str(y) componentNumber = componentNumber + 1 output = output + '\n' outList.append((glyph.index, output)) # Create a dictionary for sorting the glyphs by GID outDictionary = dict(outList) outKeys = outDictionary.keys() outKeys.sort() # Write out the file file = open(filePath, 'w') keyCount = 0 while keyCount < len(outKeys): file.write(outDictionary[outKeys[keyCount]]) keyCount = keyCount + 1 file.close() bar.close() Message('Dump file written')
def buildAccents(font, list, message, overwrite, preflight=False): """ Takes in a list of accents to build in the format of (baseGlyph, finalName, accentList) Marks glyphs that it has built, and updates the font """ tickCount = len(list) bar = ProgressBar(message, tickCount) tick = 0 for item in list: baseGlyph, outputName, accents = item if font.has_key(baseGlyph): if font.has_key(outputName): if overwrite == 1 or overwrite == 3: answer = AskYesNoCancel(outputName + ' exists in font, overwrite?') if answer == 1: font.compileGlyph(outputName, baseGlyph, accents, preflight=preflight) font[outputName].mark = 200 font[outputName].autoUnicodes() font[outputName].update() font.update() if overwrite == 2: font.compileGlyph(outputName, baseGlyph, accents, preflight=preflight) font[outputName].mark = 200 font[outputName].autoUnicodes() font[outputName].update() font.update() else: font.compileGlyph(outputName, baseGlyph, accents, preflight=preflight) font[outputName].mark = 200 font[outputName].autoUnicodes() font[outputName].update() font.update() bar.tick(tick) tick = tick+1 bar.close()
def decomposeFont(font): nakedFont = font.naked() tickCount = len(nakedFont) tick = 0 bar = ProgressBar('Cleaning up glyphs', tickCount) for g in font: nakedFont[g.name].Decompose() nakedFont[g.name].RemoveOverlap() bar.tick(tick) tick = tick+1 bar.close() tickCount = len(font) tick = 0 bar = ProgressBar('Correcting direction', tickCount) for g in font: fl.TransformGlyph(g.naked(), TR_CODE_REVERSE_ALL, '0002') bar.close() return nakedFont
def decomposeComp(f): '''decompose composites for all glyphs in the font''' myBar = ProgressBar('Decomposing...', len(f)) for g in f: if g.components: for c in range(len(g.components)): g.components[-1].decompose() g.update() myBar.tick() myBar.close() f.update()
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)
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) tick = tick+1 bar.close() orignalMetricsFont.close() else:
""" Remove overlap on all glyphs in a .ufo font. This script sis more than a little silly, but it demonstrates how objectsRF and objectsFL can work hand in hand. """ from robofab.objects.objectsRF import OpenFont from robofab.objects.objectsFL import NewFont from robofab.interface.all.dialogs import ProgressBar ufoFont = OpenFont(note="Select a .ufo") if ufoFont: bar = ProgressBar('Removing Overlap...', len(ufoFont)) flFont = NewFont() flGlyph = flFont.newGlyph('OverlapRemover') for ufoGlyph in ufoFont: flPen = flGlyph.getPointPen() ufoGlyph.drawPoints(flPen) flGlyph.removeOverlap() ufoPen = ufoGlyph.getPointPen() ufoGlyph.clear() flGlyph.drawPoints(ufoPen) flGlyph.clear() bar.tick() flFont.close(save=0) bar.close() ufoFont.save(doProgress=True)
"""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()
def buildAnchors(self, ucXOffset=0, ucYOffset=0, lcXOffset=0, lcYOffset=0, markGlyph=True, doProgress=True): """add the necessary anchors to the glyphs if they don't exist some flag definitions: uc/lc/X/YOffset=20 offset values for the anchors markGlyph=1 mark the glyph that is created doProgress=1 show a progress bar""" accentOffset = 10 tickCount = len(self.accentList) if doProgress: bar = ProgressBar('Adding anchors...', tickCount) tick = 0 for glyphName in self.accentList: if doProgress: bar.label(glyphName) previousPositions = {} baseName, stripedSuffixName, accentNames, errors = nameBuster(glyphName, self.glyphConstructions) existError = False if len(errors) > 0: existError = True for anchorError in errors: self.anchorErrors.append(anchorError) if not existError: existError = False try: self.font[baseName] except IndexError: self.anchorErrors.append(' '.join([glyphName, ':', baseName, 'does not exist.'])) existError = True for accentName, accentPosition in accentNames: try: self.font[accentName] except IndexError: self.anchorErrors.append(' '.join([glyphName, ':', accentName, 'does not exist.'])) existError = True if not existError: #glyph = self.font.newGlyph(glyphName, clear=True) for accentName, accentPosition in accentNames: if baseName.split('.')[0] in lowercase_plain: xOffset = lcXOffset-accentOffset yOffset = lcYOffset-accentOffset else: xOffset = ucXOffset-accentOffset yOffset = ucYOffset-accentOffset # should I add a cedilla and ogonek yoffset override here? if accentPosition not in previousPositions.keys(): self._dropAnchor(self.font[baseName], accentPosition, xOffset, yOffset) if markGlyph: self.font[baseName].mark = anchorColor if inFontLab: self.font[baseName].update() else: self._dropAnchor(self.font[previousPositions[accentPosition]], accentPosition, xOffset, yOffset) self._dropAnchor(self.font[accentName], accentPosition, accentOffset, accentOffset, doAccentPosition=1) previousPositions[accentPosition] = accentName if markGlyph: self.font[accentName].mark = anchorColor if inFontLab: self.font[accentName].update() if inFontLab: self.font.update() if doProgress: bar.tick(tick) tick = tick+1 if doProgress: bar.close()
def makeGlyph(glyphList, font, message, mark, saveBackup): # Initialize the progress bar tickCount = len(glyphList) bar = ProgressBar(message, tickCount) tick = 0 testingFont = _RFont() for item in glyphList: glyphName, advanceWidth, components = item # If the font has the glyph, lots of checking is required to see if changes have been made if font.has_key(glyphName): glyph = font[glyphName] #Build new glyph for comparisons testingFont.newGlyph(glyphName, clear=True) newGlyph = testingFont[glyphName] newGlyphCount = 0 while newGlyphCount < len(components): component, x, y = components[newGlyphCount] newGlyph.appendComponent(component, offset=(x,y)) newGlyphCount = newGlyphCount+1 newGlyph.width = advanceWidth newGlyph.round() # Make digest of the new glyph pointPen = DigestPointPen() newGlyph.drawPoints(pointPen) newDigest = pointPen.getDigest() # Make digest of the old glyph pointPen = DigestPointPen() glyph.drawPoints(pointPen) oldDigest = pointPen.getDigest() # Check the advance width if glyph.width != advanceWidth: glyph.width = advanceWidth if mark == 1: glyph.mark = 200 # If the digests don't match, rebuild components if oldDigest != newDigest: if saveBackup == 1: backupName = glyph.name + '.bkup' font.insertGlyph(glyph, as=backupName) font[backupName].update() glyph.clearComponents() count = 0 while count < len(components): component, x, y = components[count] glyph.appendComponent(component, offset=(x,y)) count = count+1 if mark == 1: glyph.mark = 200 # Clean up things glyph.update() bar.tick(tick) tick = tick+1 # If the glyph is not in the font, build a new glyph else: font.newGlyph(glyphName, clear=True) glyph = font[glyphName] glyph.width = advanceWidth count = 0 while count < len(components): component, x, y = components[count] glyph.appendComponent(component, offset=(x,y)) count = count+1 if mark == 1: glyph.mark = 300 glyph.update() bar.tick(tick) tick = tick+1 font.update() testingFont.close() bar.close()