1
1
mirror of https://github.com/i-tu/Hasklig.git synced 2024-09-11 10:36:46 +03:00

Merge pull request #170 from Curzy/python3-compatible

Make addSVGtable python 2/3 compatible
This commit is contained in:
Miguel Sousa 2017-10-02 16:24:53 -07:00 committed by GitHub
commit e672095ae9

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
from __future__ import print_function
""" """
Adds an SVG table to a TTF or OTF font. Adds an SVG table to a TTF or OTF font.
@ -10,10 +11,10 @@ import sys
import re import re
try: try:
from fontTools import ttLib, version from fontTools import ttLib, version
except ImportError: except ImportError:
print >> sys.stderr, "ERROR: FontTools Python module is not installed." print("ERROR: FontTools Python module is not installed.", file=sys.stderr)
sys.exit(1) sys.exit(1)
TABLE_TAG = 'SVG ' TABLE_TAG = 'SVG '
@ -25,165 +26,191 @@ reWhiteSpace = re.compile(r">\s+<", re.DOTALL)
def readFile(filePath): def readFile(filePath):
f = open(filePath, "rt") f = open(filePath, "rt")
data = f.read() data = f.read()
f.close() f.close()
return data return data
def setIDvalue(data, gid): def setIDvalue(data, gid):
id = reIDvalue.search(data) id = reIDvalue.search(data)
if id: if id:
newData = re.sub(id.group(1), 'id="glyph%s"' % gid, data) newData = re.sub(id.group(1), 'id="glyph{}"'.format(gid), data)
else: else:
newData = re.sub('<svg', '<svg id="glyph%s"' % gid, data) newData = re.sub('<svg', '<svg id="glyph{}"'.format(gid), data)
return newData return newData
def fixViewBox(data): def fixViewBox(data):
viewBox = reViewBox.search(data) viewBox = reViewBox.search(data)
if not viewBox: if not viewBox:
return data return data
fixedViewBox = 'viewBox=\"0 1000 1000 1000\"' fixedViewBox = 'viewBox=\"0 1000 1000 1000\"'
fixedData = re.sub(viewBox.group(1), fixedViewBox, data) fixedData = re.sub(viewBox.group(1), fixedViewBox, data)
return fixedData return fixedData
def getGlyphNameFromFileName(filePath): def getGlyphNameFromFileName(filePath):
folderPath, fontFileName = os.path.split(filePath) folderPath, fontFileName = os.path.split(filePath)
fileNameNoExtension, fileExtension = os.path.splitext(fontFileName) fileNameNoExtension, fileExtension = os.path.splitext(fontFileName)
return fileNameNoExtension return fileNameNoExtension
def processFontFile(fontFilePath, svgFilePathsList): def processFontFile(fontFilePath, svgFilePathsList):
font = ttLib.TTFont(fontFilePath) font = ttLib.TTFont(fontFilePath)
# first create a dictionary because the SVG glyphs need to be sorted in the table # first create a dictionary because the SVG glyphs need to be sorted in the table
svgDocsDict = {} svgDocsDict = {}
for svgFilePath in svgFilePathsList: for svgFilePath in svgFilePathsList:
gName = getGlyphNameFromFileName(svgFilePath) gName = getGlyphNameFromFileName(svgFilePath)
try: try:
gid = font.getGlyphID(gName) gid = font.getGlyphID(gName)
except KeyError: except KeyError:
print >> sys.stderr, "ERROR: Could not find a glyph named %s in the font %s." % (gName, os.path.split(fontFilePath)[1]) print(
continue "ERROR: Could not find a glyph named {} in the font {}.".format(
gName, os.path.split(fontFilePath)[1]
),
file=sys.stderr
)
continue
svgItemsList = [] svgItemsList = []
svgItemData = readFile(svgFilePath) svgItemData = readFile(svgFilePath)
svgItemData = setIDvalue(svgItemData, gid) svgItemData = setIDvalue(svgItemData, gid)
svgItemData = fixViewBox(svgItemData) svgItemData = fixViewBox(svgItemData)
# Remove all white space between elements # Remove all white space between elements
for whiteSpace in set(reWhiteSpace.findall(svgItemData)): for whiteSpace in set(reWhiteSpace.findall(svgItemData)):
svgItemData = svgItemData.replace(whiteSpace, '><') svgItemData = svgItemData.replace(whiteSpace, '><')
svgItemsList.append(svgItemData.strip()) svgItemsList.append(svgItemData.strip())
svgItemsList.extend([gid, gid]) svgItemsList.extend([gid, gid])
svgDocsDict[gid] = svgItemsList svgDocsDict[gid] = svgItemsList
# don't do any changes to the source OTF/TTF font if there's no SVG data # don't do any changes to the source OTF/TTF font if there's no SVG data
if not svgDocsDict: if not svgDocsDict:
print >> sys.stderr, "ERROR: Could not find any artwork files that can be added to the font." print(
return "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())] svgDocsList = [svgDocsDict[index] for index in sorted(svgDocsDict.keys())]
svgTable = ttLib.newTable(TABLE_TAG) svgTable = ttLib.newTable(TABLE_TAG)
svgTable.compressed = False # GZIP the SVG docs svgTable.compressed = False # GZIP the SVG docs
svgTable.docList = svgDocsList svgTable.docList = svgDocsList
font[TABLE_TAG] = svgTable font[TABLE_TAG] = svgTable
# FontTools can't overwrite a font on save, # FontTools can't overwrite a font on save,
# so save to a hidden file, and then rename it # so save to a hidden file, and then rename it
# https://github.com/behdad/fonttools/issues/302 # https://github.com/behdad/fonttools/issues/302
folderPath, fontFileName = os.path.split(fontFilePath) folderPath, fontFileName = os.path.split(fontFilePath)
fileNameNoExtension, fileExtension = os.path.splitext(fontFileName) fileNameNoExtension, fileExtension = os.path.splitext(fontFileName)
newFontFilePath = os.path.join(folderPath, "%s%s%s" % ('.', fileNameNoExtension, fileExtension)) newFontFilePath = os.path.join(folderPath, "{}{}{}".format(
'.', fileNameNoExtension, fileExtension))
font.save(newFontFilePath) font.save(newFontFilePath)
font.close() font.close()
# On Windows a file can't be renamed to a file that already exists # On Windows a file can't be renamed to a file that already exists
os.remove(fontFilePath) os.remove(fontFilePath)
os.rename(newFontFilePath, fontFilePath) os.rename(newFontFilePath, fontFilePath)
print >> sys.stdout, "SVG table successfully added to %s" % fontFilePath print(
"SVG table successfully added to {}".format(fontFilePath),
file=sys.stderr
)
def validateSVGfiles(svgFilePathsList): def validateSVGfiles(svgFilePathsList):
""" """
Light validation of SVG files. Light validation of SVG files.
Checks that there is an <svg> element. Checks that there is an <svg> element.
""" """
validatedPaths = [] validatedPaths = []
for filePath in svgFilePathsList: for filePath in svgFilePathsList:
# skip hidden files (filenames that start with period) # skip hidden files (filenames that start with period)
fileName = os.path.basename(filePath) fileName = os.path.basename(filePath)
if fileName[0] == '.': if fileName[0] == '.':
continue continue
# read file # read file
data = readFile(filePath) data = readFile(filePath)
# find <svg> blob # find <svg> blob
svg = reSVGelement.search(data) svg = reSVGelement.search(data)
if not svg: if not svg:
print "WARNING: Could not find <svg> element in the file. Skiping %s" % (filePath) print(
continue "WARNING: Could not find <svg> element in the file. "
"Skiping {}".format(filePath)
)
continue
validatedPaths.append(filePath) validatedPaths.append(filePath)
return validatedPaths return validatedPaths
def getFontFormat(fontFilePath): def getFontFormat(fontFilePath):
# these lines were scavenged from fontTools # these lines were scavenged from fontTools
f = open(fontFilePath, "rb") f = open(fontFilePath, "rb")
header = f.read(256) header = f.read(256)
head = header[:4] head = header[:4]
f.close() f.close()
if head == "OTTO": if head == "OTTO":
return "OTF" return "OTF"
elif head in ("\0\1\0\0", "true"): elif head in ("\0\1\0\0", "true"):
return "TTF" return "TTF"
return None return None
def run(): def run():
fontFilePath = os.path.realpath(sys.argv[1]) fontFilePath = os.path.realpath(sys.argv[1])
svgFolderPath = os.path.realpath(sys.argv[2]) svgFolderPath = os.path.realpath(sys.argv[2])
# Font file path # Font file path
if os.path.isfile(fontFilePath): if os.path.isfile(fontFilePath):
if getFontFormat(fontFilePath) not in ["OTF", "TTF"]: if getFontFormat(fontFilePath) not in ["OTF", "TTF"]:
print >> sys.stderr, "ERROR: The path is not a valid OTF or TTF font." print("ERROR: The path is not a valid OTF or TTF font.",
return file=sys.stderr)
else: return
print >> sys.stderr, "ERROR: The path to the font is invalid." else:
return print("ERROR: The path to the font is invalid.",
file=sys.stderr)
return
# SVG folder path # SVG folder path
if os.path.isdir(svgFolderPath): if os.path.isdir(svgFolderPath):
svgFilePathsList = [] svgFilePathsList = []
for dirName, subdirList, fileList in os.walk(svgFolderPath): # Support nested folders for dirName, subdirList, fileList in os.walk(
for file in fileList: svgFolderPath): # Support nested folders
svgFilePathsList.append(os.path.join(dirName, file)) # Assemble the full paths, not just file names for file in fileList:
else: svgFilePathsList.append(os.path.join(dirName,
print >> sys.stderr, "ERROR: The path to the folder containing the SVG files is invalid." file)) # Assemble the full paths, not just file names
return else:
print(
"ERROR: The path to the folder "
"containing the SVG files is invalid.",
file=sys.stderr
)
return
# validate the SVGs # validate the SVGs
svgFilePathsList = validateSVGfiles(svgFilePathsList) svgFilePathsList = validateSVGfiles(svgFilePathsList)
if not svgFilePathsList: if not svgFilePathsList:
print >> sys.stderr, "WARNING: No SVG files were found." print("WARNING: No SVG files were found.", file=sys.stderr)
return return
processFontFile(fontFilePath, svgFilePathsList) processFontFile(fontFilePath, svgFilePathsList)
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv) != 3: if len(sys.argv) != 3:
print "To run this script type:\n python %s <path to input OTF/TTF file> <path to folder tree containing SVG files>" % sys.argv[0] print("To run this script type:\n "
else: "python {} <path to input OTF/TTF file> "
run() "<path to folder tree containing SVG files>".format(sys.argv[0]))
else:
run()