def replaceSuffixes(self, sender): """ Handle replacing/appending of suffixes. """ mode = "replace" if self.w.replace.get() == 1 else "append" oldSuffix = self.w.oldSuffix.getItems()[self.w.oldSuffix.get()] enteredSuffix = self.w.newSuffix.get() suffixes_in = [oldSuffix, enteredSuffix] suffixes = [] # build proper suffixes list for s in suffixes_in: if s is not None and len(s) > 0: if s[0] == ".": s = s[1:] # handle suffixes without periods suffixes.append(s) if mode == "replace" and suffixes[0] == suffixes[1]: Message( u"Cannot replace a suffix with itself.\nI mean I could, but there seems to be little point :)" ) elif mode == "append" and suffixes[1] == "": Message( u"Cannot append an empty suffix.\n(Or you could just pretend I've already done it.)" ) else: scope = self.f.keys() if self.w.scope.get( ) == 1 else self.f.selection if mode == "replace": for gname in scope: if gname.endswith(suffixes[0]): sufLen = len(suffixes[0]) if len(suffixes[1]) > 0: newName = gname[:-sufLen] + suffixes[1] else: sufLenWithPeriod = sufLen + 1 newName = gname[:-sufLenWithPeriod] self._changeGlyphname(gname, newName) elif mode == "append": for gname in scope: newName = gname + "." + suffixes[1] self._changeGlyphname(gname, newName) self.f.update() # store new values as defaults savedPresets = getExtensionDefault( "nl.typologic.suffixer.presetSuffixes") if enteredSuffix != "" and enteredSuffix not in savedPresets: savedPresetsList = savedPresets.split() savedPresetsList.append(enteredSuffix) savedPresetsList.sort() newPresets = " ".join(savedPresetsList) setExtensionDefault("nl.typologic.suffixer.presetSuffixes", newPresets) self.w.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 startDialog(self): # Welcome message! Message("Hi! My name is typeStats.") # Mode verboso = AskYesNoCancel("Do you prefer the verbose mode?", title='typeStats', default=0) # Search path folder = GetFolder("Choose the directory to analyze") return folder, verboso
def fuse(font): readGlyphList = getDataFile(font.path, 'Choose a dump file') if readGlyphList is not None: # Check to make sure that all compontents are present in the font checkedGlyphList = checkGlyphs(font, readGlyphList) if len(checkedGlyphList) == 0: mark = AskYesNoCancel('Do you wish to mark changed glyphs?') if mark != -1: saveBackup = AskYesNoCancel('Do you want a backup of changed glyphs?') if saveBackup != -1: makeGlyph(readGlyphList, font, 'Updating glyphs', mark, saveBackup) font.update() Message('Done updating glyphs') else: # Gives a list of the components missing from the VFB OneList(checkedGlyphList, 'Sorry, your VFB is missing:')
def checkFont(self, useSelection=False, excludeZeroWidth=True): f = CurrentFont() if f is not None: # initialize things self.w.options.progress.start() time0 = time.time() self.excludeZeroWidth = excludeZeroWidth self.f = f glyphNames = f.selection if useSelection else f.keys() glyphList = [f[x] for x in glyphNames] glyphList = self._trimGlyphList(glyphList) self.touchingPairs = Touche(f).findTouchingPairs(glyphList) # display output self.w.results.stats.set("%d glyphs checked" % len(glyphList)) self.w.results.result.set("%d touching pairs found" % len(self.touchingPairs)) self.w.results.show(True) outputList = [{ "left glyph": g1, "right glyph": g2 } for (g1, g2) in self.touchingPairs] self.w.outputList.set(outputList) if len(self.touchingPairs) > 0: self.w.outputList.setSelection([0]) else: self.w.preview.set("") outputButtons = [ self.w.results.spaceView, self.w.results.exportTxt ] for b in outputButtons: b.enable(False) if len( self.touchingPairs) == 0 else b.enable(True) self.w.preview.setFont(f) self.w.options.progress.stop() self._resizeWindow(enlarge=True) time1 = time.time() print u'Touché: finished checking %d glyphs in %.2f seconds' % ( len(glyphList), time1 - time0) else: Message(u'Touché: Can’t find a font to check')
def OpenFont(path=None, note=None): """Open a font from a path. If path is not given, present the user with a dialog.""" if not note: note = 'select a .ufo directory' if not path: from robofab.interface.all.dialogs import GetFolder path = GetFolder(note) if path: try: return RFont(path) except OSError: from robofab.interface.all.dialogs import Message Message( "%s is not a valid .UFO font. But considering it's all XML, why don't you have a look inside with a simple text editor." % (path)) else: return None
def checkFont(self, useSelection=False, excludeZeroWidth=True): f = CurrentFont() if f is not None: # initialize things self.w.options.progress.start() time0 = time.time() self.excludeZeroWidth = excludeZeroWidth self.f = f glyphNames = f.selection if useSelection else f.keys() glyphList = [f[x] for x in glyphNames] glyphList = self._trimGlyphList(glyphList) self.touchingPairs = Touche(f).findTouchingPairs(glyphList) # display output self.w.results.stats.set("%d glyphs checked" % len(glyphList)) self.w.results.result.set("%d touching pairs found" % len(self.touchingPairs)) self.w.results.show(True) outputList = [{"left glyph": g1, "right glyph": g2} for (g1, g2) in self.touchingPairs] outputStringList = [ "/%s/%s " % (g1, g2) for (g1, g2) in self.touchingPairs ] outputStringMetalist = [outputStringList[i:i + 400] for i in range(0, len(outputStringList), 400)] ActiveFont = self.f._font ActiveFont.disableUpdateInterface() for eachList in outputStringMetalist: outputString = "".join(eachList) ActiveFont.newTab(outputString) self.w.outputList.set(outputList) if len(self.touchingPairs) > 0: self.w.outputList.setSelection([0]) ActiveFont.enableUpdateInterface() #self.w.preview.setFont(f) self.w.options.progress.stop() self._resizeWindow(enlarge=True) time1 = time.time() print u'Touché: finished checking %d glyphs in %.2f seconds' % (len(glyphList), time1-time0) else: Message(u'Touché: Can’t find a font to check')
#MenuTitle: Swap Glyphs # ################################################################### # # Swaps 2 Characters (basically just renaming each other) # # --> let me know if you have ideas for improving # --> Mark Froemberg aka DeutschMark @ GitHub <-- # # ToDo: - # # ################################################################### Doc = Glyphs.currentDocument Font = Glyphs.font Selection = Font.selectedLayers listOfGlyphNames = [x.parent.name for x in Selection] if len(listOfGlyphNames) == 2: Selection[1].parent.name = "Temp" print listOfGlyphNames Selection[0].parent.name = listOfGlyphNames[1] Selection[1].parent.name = listOfGlyphNames[0] else: #pass from robofab.interface.all.dialogs import Message Message("Select only TWO glyphs")
return 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)
print "selection", todo if g is not None: todo.append(g.name) for f in AllFonts(): ufoPath = None print "f.path", f, f.path if f.path is None: # huh, in case there is a ghost font. print "skipping", f continue ufoPath = f.path.replace(".vfb", ".ufo") if not os.path.exists(ufoPath): ufoPath = GetFolder("Select a UFO to save the GLIF in:") if ufoPath.find(".ufo") == -1: Message("You need to select an UFO. Quitting.") ufoPath = None if ufoPath is None: continue for c in todo: if c not in f: print "font is missing", c continue g = f[c] path = os.path.join(os.path.dirname(ufoPath), os.path.basename(ufoPath), "glyphs") print "saving glyph %s in %s"%(g.name, path) gs = GlyphSet(path, glyphNameToFileNameFunc=glyphNameToShortFileName) gs.writeGlyph(g.name, g, g.drawPoints) gs.writeContents() print 'done'
if buildSmallCap == 1: buildAccents(font, smallCapList, 'Building small cap accents', overwrite) #Build a couple of accents that would be missed #font.newGlyph('uni021B', clear=True) #font.newGlyph('uni021A', clear=True) #font.newGlyph('Dotlessi.sc', clear=True) #dotlessisc = font['I.sc'].copy() #duplicatetcommaaccent = font['tcommaaccent'].copy() #duplicateTcommaaccent = font['Tcommaaccent'].copy() #font['Dotlessi.sc'].appendGlyph(dotlessisc) #font['uni021B'].appendGlyph(duplicatetcommaaccent) #font['uni021A'].appendGlyph(duplicateTcommaaccent) #font['uni021B'].width = duplicatetcommaaccent.width #font['uni021B'].leftMargin = duplicatetcommaaccent.leftMargin #font['uni021B'].rightMargin = duplicatetcommaaccent.rightMargin #font['uni021B'].mark = 200 #font['uni021A'].width = duplicateTcommaaccent.width #font['uni021A'].leftMargin = duplicateTcommaaccent.leftMargin #font['uni021A'].rightMargin = duplicateTcommaaccent.rightMargin #font['uni021A'].mark = 200 #font['Dotlessi.sc'].width = dotlessisc.width #font['Dotlessi.sc'].leftMargin = dotlessisc.leftMargin #font['Dotlessi.sc'].rightMargin = dotlessisc.rightMargin #font['Dotlessi.sc'].mark = 200 font.update() Message('Listo!')
# # # demo of the RoboFab glyph object # # import robofab from robofab.world import CurrentFont, CurrentGlyph from robofab.interface.all.dialogs import Message # (make sure you have a font opened in FontLab) # this code starts out the same as intro_FontObject f = CurrentFont() if f == None: Message("You should open a font first, there's nothing to look at now!") else: for g in f: print "glyphname:", g.name, ", glyph width:", g.width # so now g is a RoboFab Glyph object print "this glyph has %d contours" % len(g.contours) print "this glyph has %d components" % len(g.components) print "this glyph has %d anchors" % len(g.anchors) print # easy huh? # There are many more attributes and methods. # Most of these can be used to edit the font data. # Which makes them not suited for a simple intro as this # because we don't want to mess up your font.
font = CurrentFont() filePath = PutFile() file = open(filePath, 'w') 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)) outDictionary = dict(outList) outKeys = outDictionary.keys() outKeys.sort() keyCount = 0 while keyCount < len(outKeys): file.write(outDictionary[outKeys[keyCount]]) keyCount = keyCount + 1 bar.close() file.close() Message('Dump file written')
# or Glyph object respectively. It will be the # front most font or the front most glyph. from robofab.world import CurrentFont, CurrentGlyph # This is a brief intro into Robofabs all singing and # dancing dialog class. It will produce simple # dialogs in almost any environment, FontLab, Python IDE, W. from robofab.interface.all.dialogs import Message # (make sure you have a font opened in FontLab) f = CurrentFont() # so now f is the name of a font object for the current font. if f == None: # let's see what dialog can do, a warning Message("You should open a font first, there's nothing to look at now!") else: # and another dialog. Message("The current font is %s" % (f.info.postscriptFullName)) # let's have a look at some of the attributes a RoboFab Font object has print "the number of glyphs:", len(f) # some of the attributes map straight to the FontLab Font class # We just straightened the camelCase here and there print "full name of this font:", f.info.postscriptFullName print "list of glyph names:", f.keys() print 'ascender:', f.info.ascender print 'descender:', f.info.descender
def exportUFO(font, newFile=True, doInfo=True, doKerning=True, doGroups=True, doLib=True, doFeatures=True, doHints=False, doMarks=True, doMasks=True, glyphs=None, formatVersion=2): # get the UFO path ufoPath = os.path.splitext(font.path)[0] + ".ufo" if not newFile: if not os.path.exists(ufoPath): Message("Could not find the UFO file \"%s\"." % os.path.basename(ufoPath)) return else: if os.path.exists(ufoPath): ufoPath = _findAvailablePathName(ufoPath) # make sure no bogus glyph names are coming in if glyphs is not None: glyphs = [glyphName for glyphName in glyphs if font.has_key(glyphName)] # make the font the top font in FL fl.ifont = font.fontIndex # add the masks and marks to the glyph.lib if doMasks or doMarks: if glyphs is None: glyphNames = font.keys() else: glyphNames = glyphs for glyphName in glyphNames: glyph = font[glyphName] if doMarks: mark = glyph.mark glyph.lib[MARK_LIB_KEY] = mark if doMasks: # open a glyph window fl.EditGlyph(glyph.index) # switch to the mask layer fl.CallCommand(fl_cmd.ViewEditMask) # if the mask is empty, skip this step if not len(glyph): # switch back to the edit layer fl.CallCommand(fl_cmd.ViewEditMask) continue # get the mask data pen = InstructionPointPen() glyph.drawPoints(pen) # switch back to the edit layer fl.CallCommand(fl_cmd.ViewEditMask) # write the mask data to the glyph lib instructions = pen.getInstructions() if instructions: glyph.lib[MASK_LIB_KEY] = instructions # close all glyph windows. sometimes this actually works. fl.CallCommand(fl_cmd.WindowCloseAllGlyphWindows) # remove WWS names from the lib wwsStorage = {} if "openTypeNameWWSFamilyName" in font.lib: wwsStorage["openTypeNameWWSFamilyName"] = font.lib.pop(WWS_FAMILY_KEY) if "openTypeNameWWSSubfamilyName" in font.lib: wwsStorage["openTypeNameWWSSubfamilyName"] = font.lib.pop( WWS_SUBFAMILY_KEY) # write the UFO font.writeUFO(path=ufoPath, doHints=doHints, doInfo=doInfo, doKerning=doKerning, doGroups=doGroups, doLib=doLib, doFeatures=doFeatures, glyphs=glyphs, formatVersion=formatVersion) # add the WWS names to the info if doInfo: infoPath = os.path.join(ufoPath, "fontinfo.plist") info = readPlist(infoPath) newInfo = deepcopy(info) newInfo.update(wwsStorage) if info != newInfo: writePlist(newInfo, infoPath) # put the WWS names back in the lib font.lib.update(wwsStorage) # remove the masks and marks from the glyph.lib if doMasks or doMarks: if glyphs is None: glyphNames = font.keys() else: glyphNames = glyphs for glyphName in glyphNames: glyph = font[glyphName] lib = glyph.lib if lib.has_key(MASK_LIB_KEY): del lib[MASK_LIB_KEY] if lib.has_key(MARK_LIB_KEY): del lib[MARK_LIB_KEY]
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()
page_width = page_format[0] page_height = page_format[1] page_num = 0 scale_round = 0 #Chooing Fonts current_font = Glyphs.font #print(current_font) #print current_font.familyName current_font_filepath = current_font.filepath #fontname = current_font.info.postscriptFullName #postscript name as string #if fontname is None: #Message("No postscript name given!") #alert if font info is not complete if current_font is None: Message("Open fonts you want to test first." ) #gives error message if no font is currently open #First Page def firstPage(): newPage(page_format[0], page_format[1]) #General Info Page fontSize(50) font("System Font Regular") #font used to display info text("Font Family:", (75, 420)) text(current_font.familyName, (75, 360)) def MasterInfo(): for i in range(0, 30): try: print "Name" + ":" + " " + current_font.masters[i].name
from robofab.interface.all.dialogs import AskString, Message font = CurrentFont() text = AskString("A height") try: height = int(text) except: Message("Hey! A number please!") for name in font.selection: glyph = font[name] center = glyph.width/2 glyph.appendAnchor('_top', (center,height))
from robofab.interface.all.dialogs import AskString, Message font = CurrentFont() change = AskString("How much?") try: change = int(change) except: Message("Number Please!") for name in font.selection: glyph = font[name] for c in glyph: for p in c.bPoints: y = p.anchor[1] if y < -15: p.move((0, -change)) glyph.update()
# Select tolerance level in the variable below # Credits: # Pablo Impallari # http://www.impallari.com tolerancia = 30; from robofab.world import CurrentFont from robofab.interface.all.dialogs import Message f = CurrentFont() glyphs = f.glyphs # Se fija que haya 1 solo seleccionado y toma el ancho del mismo if fl.count_selected != 1: Message("Select 1 Glyph") else: source = f.selection[0] ancho = f[source].width # Limpia todos los colores for g in glyphs: g.mark = 0 # pinta todos los glyphs for g in glyphs: este = int(g.width) #Iguales if este == ancho:
from robofab.interface.all.dialogs import SearchList, AskString, Message #asks for a number. if allowZeroOrLess is 0 it will not allow a number that is zero or less def getNumber(message, allowZeroOrLess): userInput = AskString(message) if userInput is not None: try: int(userInput) except ValueError: userInput = getNumber('Please enter a number', allowZeroOrLess) if (userInput <= 0) and (allowZeroOrLess == 0): userInput = getNumber('Please enter a number greater than 0', 0) return int(userInput) def getGlyphWidth(glyph): box = glyph.box width = box[2] - box[0] return width #Program font = CurrentFont() glyphs = font.selection y = getNumber('Vertical Position?', 1) name = AskString('Name of anchors') for glyph in glyphs: x = int(getGlyphWidth(font[glyph])/2) + font[glyph].leftMargin font[glyph].appendAnchor(name, (x,y)) font.update() Message('All done!')