diff options
Diffstat (limited to 'misc/pylib/robofab/tools/toolsFL.py')
-rwxr-xr-x | misc/pylib/robofab/tools/toolsFL.py | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/misc/pylib/robofab/tools/toolsFL.py b/misc/pylib/robofab/tools/toolsFL.py new file mode 100755 index 000000000..c8aff19a1 --- /dev/null +++ b/misc/pylib/robofab/tools/toolsFL.py @@ -0,0 +1,339 @@ +""" +T.O.O.L.S.: Things Other Objects Lack (Sometimes) +-assorted raw tools. + +This is an assorted colection of raw tools that do +things inside of FontLab. Many of these functions +form the bedrock of objectsFL. In short, use these +tools only if you need the raw functions and they are +not supported by the objects. + +Object model: +Most of these tools were written before +objectsFL. Some of these tools are used by +objectsFL. That means that if you want to +use functions from robofab.tools you can always +feed them FontLab objects (like Font, Glyps, +etc.). If the functions also accept Robjects from +robofab.objects it is usually mentioned in the +doc string. + +This is a simple way to convert a robofab Font +object back to a FL Font object. Even if you don't +know which particular faith an object belongs to +you can use this: + +font = unwrapFont(font) +""" + + +from FL import * +from warnings import warn + +try: + from fl_cmd import * +except ImportError: + print "The fl_cmd module is not available here. toolsFL.py" + +import os + +from robofab import RoboFabError + +# local encoding +if os.name == "mac": + LOCAL_ENCODING = "macroman" +else: + LOCAL_ENCODING = "latin-1" + + +# +# +# +# stuff for fontlab app +# +# +# + +def AppFolderRenamer(): + """This function will rename the folder that contains the + FontLab application to a more specific name that includes + the version of the application + Warning: it messes with the paths of your app, if you have + items that hardwired to this path you'd be in trouble. + """ + if fl.count > 0: + warn("Close all fonts before running AppFolderRenamer") + return + old = fl.path[:-1] + root = os.path.dirname(old) + new = "FontLab " + fl.version.replace('/', '_') + path = os.path.join(root, new) + if path != old: + try: + os.rename(old, path) + except OSError: + pass + warn("Please quit and restart FontLab") + +# +# +# +# stuff for fonts +# +# +# + +def GetFont(full_name): + """Return fontobjects which match full_name. + Note: result is a list. + Returns: a list of FL Font objects + """ + found = [] + for f in AllFonts(): + if f.full_name == full_name: + found.append(f) + return found + +def AllFonts(): + """Collect a list of all open fonts. + Returns: a list of FL Font objects. + """ + fontcount = len(fl) + af = [] + for i in range(fontcount): + af.append(fl[i]) + return af + +def FontIndex(font): + """return the index of a specified FL Font""" + font = unwrapFont(font) + a = AllFonts() + p = [] + for f in a: + p.append(f.file_name) + if font.file_name in p: + return p.index(font.file_name) + else: + return None + +def unwrapFont(font): + """Unwrap the font if it happens to be a RoboFab Font""" + if hasattr(font, 'isRobofab'): + return font.naked() + return font + +def MakeTempFont(font, dupemark=None, removeOverlap=True, decompose=True): + """Save the current FL Font, + - close the file, + - duplicate the file in the finder (icon looks weird, but it works) + - open the duplicate + - decompose the glyphs + - remove overlaps + - return the fontobject + + font is either a FL Font or RF RFont object. + + Problems: doesn't check if the filename is getting too long. + Note: it will overwrite older files with the same name. + """ + import string + f = unwrapFont(font) + if not dupemark or dupemark == "": + dupemark = "_tmp_" + path = f.file_name + a = f.file_name.split('.') + a.insert(len(a)-1, dupemark) + newpath = string.join(a, '.') + f.Save(path) + fl.Close(FontIndex(f)) + file = open(path, 'rb') + data = file.read() + file.close() + file = open(newpath, 'wb') + file.write(data) + file.close() + fl.Open(newpath, 1) + nf = fl.font + if nf is None: + print 'uh oh, sup?' + return None + else: + for g in nf.glyphs: + if decompose: + g.Decompose() + if removeOverlap: + g.RemoveOverlap() + return nf + +def makePSFontName(name): + """Create a postscript filename out of a regular postscript fontname, + using the old fashioned macintosh 5:3:3 convention. + """ + import string + parts = [] + current = [] + final = [] + notAllowed = '-_+=,-' + index = 0 + for c in name: + if c in notAllowed: + continue + if c in string.uppercase or index == 0: + c = string.upper(c) + if current: + parts.append("".join(current)) + current = [c] + else: + current.append(c) + index = index + 1 + if current: + parts.append("".join(current)) + final.append(parts[0][:5]) + for p in parts[1:]: + final.append(p[:3]) + return "".join(final) + +# +# +# +# stuff for glyphs +# +# +# + +def NewGlyph(font, glyphName, clear=False, updateFont=True): + """Make a new glyph if it doesn't already exist, return the glyph. + font is either a FL Font or RF RFont object. If updateFont is True + the (very slow) fl.UpdateFont function will be called. + """ + font = unwrapFont(font) + if isinstance(glyphName, unicode): + glyphName = glyphName.encode(LOCAL_ENCODING) + glyph = font[glyphName] + if glyph is None: + new = Glyph() + new.name = glyphName + font.glyphs.append(new) + if updateFont: + fl.UpdateFont(FontIndex(font)) + glyph = font[glyphName] + elif clear: + glyph.Clear() + glyph.anchors.clean() + glyph.components.clean() + glyph.note = "" + return glyph + + +def AddToAlias(additions, sep='+'): + """additions is a dict with glyphnames as keys + and glyphConstruction as values. In order to make + a bunch of additions in one go rather than open + and close the file for each name. Add a glyph + to the alias.dat file if it doesn't already exist. + additions = {'Gcircumflex': ['G','circumflex'], } + Returns a list of only the added glyphnames.""" + import string + glyphs = {} + data = [] + new = [] + path = os.path.join(fl.path, 'Mapping', 'alias.dat') + if os.path.exists(path): + file = open(path, 'r') + data = file.read().split('\n') + file.close() + for i in data: + if len(i) == 0: continue + if i[0] != '%': + glyphs[i.split(' ')[0]] = i.split(' ')[1] + for glyphName, glyphConstruction in additions.items(): + if glyphName not in glyphs.keys(): + new.append(glyphName) + glyphs[glyphName] = string.join(glyphConstruction, sep) + newNames = ['%%FONTLAB ALIASES'] + l = glyphs.keys() + l.sort() + for i in l: + newNames.append(string.join([i, glyphs[i]], ' ')) + file = open(path, 'w') + file.write(string.join(newNames, '\n')) + file.close() + return new + + +def GlyphIndexTable(font): + """Make a glyph index table for font""" + font = unwrapFont(font) + idx = {} + for i in range(len(font)): + g = font.glyphs[i] + idx[g.name] = i + return idx + +def MakeReverseCompoMapping(font): + """Return a dict that maps glyph names to lists containing tuples + of the form: + (clientGlyphName, componentIndex) + """ + font = unwrapFont(font) + reverseCompoMapping = {} + for g in font.glyphs: + for i, c in zip(range(len(g.components)), g.components): + base = font[c.index].name + if not base in reverseCompoMapping: + reverseCompoMapping[base] = [] + reverseCompoMapping[base].append((g.name, i)) + return reverseCompoMapping + + +# +# +# +# stuff for text files +# +# +# + +def textPrinter(text, name=None, path=None): + """Write a string to a text file. If no name is given it becomes + Untitled_hour_minute_second.txt . If no path is given it goes + into the FontLab/RoboFab Data directory.""" + if not name: + import time + tm_year,tm_mon,tm_day,tm_hour,tm_min,tm_sec,tm_wday,tm_yday,tm_isdst = time.localtime() + now = '_'.join((`tm_hour`, `tm_min`, `tm_sec`)) + name = 'Untitled_%s.txt'%now + if not path: + path = os.path.join(makeDataFolder(), name) + f = open(path, 'wb') + f.write(text) + f.close() + +def makeDataFolder(): + """Make the RoboFab data folder""" + folderPath = os.path.join(fl.path, "RoboFab Data") + if not os.path.exists(folderPath): + try: + os.makedirs(folderPath) + except: + pass + return folderPath + + +def Log(text=None): + """Make an entry in the default log file.""" + now = str(time.asctime(time.localtime(time.time()))) + if not text: + text = "-" + entry = "%s: %s\r"%(now, text) + path = os.path.join(os.getcwd(), "Logs") + new = 0 + if not os.path.exists(path): + os.makedirs(path) + new = 1 + log = os.path.join(path, "log.txt") + f = open(log, 'a') + if new: + f.write("# log file for FL\r") + f.write(entry) + f.close() |