#!/usr/bin/env python from __future__ import print_function """ Adds an SVG table to a TTF or OTF font. The file names of the SVG glyphs need to match their corresponding glyph final names. """ import os import sys import re try: from fontTools import ttLib, version except ImportError: print("ERROR: FontTools Python module is not installed.", file=sys.stderr) sys.exit(1) TABLE_TAG = 'SVG ' # Regexp patterns reSVGelement = re.compile(r".+?", re.DOTALL) reIDvalue = re.compile(r"]+?(id=\".*?\").+?>", re.DOTALL) reViewBox = re.compile(r"", re.DOTALL) reWhiteSpace = re.compile(r">\s+<", re.DOTALL) def readFile(filePath): f = open(filePath, "rt") data = f.read() f.close() return data def setIDvalue(data, gid): id = reIDvalue.search(data) if id: newData = re.sub(id.group(1), 'id="glyph{}"'.format(gid), data) else: newData = re.sub('<') svgItemsList.append(svgItemData.strip()) svgItemsList.extend([gid, gid]) svgDocsDict[gid] = svgItemsList # don't do any changes to the source OTF/TTF font if there's no SVG data if not svgDocsDict: print( "ERROR: Could not find any artwork files " "that can be added to the font.", file=sys.stderr ) return svgDocsList = [svgDocsDict[index] for index in sorted(svgDocsDict.keys())] svgTable = ttLib.newTable(TABLE_TAG) svgTable.compressed = False # GZIP the SVG docs svgTable.docList = svgDocsList font[TABLE_TAG] = svgTable font.save(fontFilePath) font.close() print( "SVG table successfully added to {}".format(fontFilePath), file=sys.stderr ) def validateSVGfiles(svgFilePathsList): """ Light validation of SVG files. Checks that there is an element. """ validatedPaths = [] for filePath in svgFilePathsList: # skip hidden files (filenames that start with period) fileName = os.path.basename(filePath) if fileName[0] == '.': continue # read file data = readFile(filePath) # find blob svg = reSVGelement.search(data) if not svg: print( "WARNING: Could not find element in the file. " "Skiping {}".format(filePath) ) continue validatedPaths.append(filePath) return validatedPaths def getFontFormat(fontFilePath): # these lines were scavenged from fontTools f = open(fontFilePath, "rb") header = f.read(256) head = header[:4] f.close() if head == "OTTO": return "OTF" elif head in ("\0\1\0\0", "true"): return "TTF" return None def run(): fontFilePath = os.path.realpath(sys.argv[1]) svgFolderPath = os.path.realpath(sys.argv[2]) # Font file path if os.path.isfile(fontFilePath): if getFontFormat(fontFilePath) not in ["OTF", "TTF"]: print("ERROR: The path is not a valid OTF or TTF font.", file=sys.stderr) return else: print("ERROR: The path to the font is invalid.", file=sys.stderr) return # SVG folder path if os.path.isdir(svgFolderPath): svgFilePathsList = [] for dirName, subdirList, fileList in os.walk( svgFolderPath): # Support nested folders for file in fileList: svgFilePathsList.append(os.path.join(dirName, file)) # Assemble the full paths, not just file names else: print( "ERROR: The path to the folder " "containing the SVG files is invalid.", file=sys.stderr ) return # validate the SVGs svgFilePathsList = validateSVGfiles(svgFilePathsList) if not svgFilePathsList: print("WARNING: No SVG files were found.", file=sys.stderr) return processFontFile(fontFilePath, svgFilePathsList) if __name__ == "__main__": if len(sys.argv) != 3: print("To run this script type:\n " "python {} " "".format(sys.argv[0])) else: run()