Merge pull request #1130 from anthrotype/temp-revert-split-glyphs

Temporarily revert PR #1035 bamidei/split_g_l_y_f_to_one_per_file
This commit is contained in:
Cosimo Lupo 2017-12-18 12:21:47 +00:00 committed by GitHub
commit 060f856f92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 160 deletions

View File

@ -17,8 +17,7 @@ BUFSIZE = 0x4000
class XMLReader(object):
def __init__(self, fileOrPath, ttFont, progress=None, quiet=None, contentOnly=False):
def __init__(self, fileOrPath, ttFont, progress=None, quiet=None):
if fileOrPath == '-':
fileOrPath = sys.stdin
if not hasattr(fileOrPath, "read"):
@ -36,7 +35,6 @@ class XMLReader(object):
self.quiet = quiet
self.root = None
self.contentStack = []
self.contentOnly = contentOnly
self.stackSize = 0
def read(self, rootless=False):
@ -75,24 +73,8 @@ class XMLReader(object):
parser.Parse(chunk, 0)
def _startElementHandler(self, name, attrs):
if self.stackSize == 1 and self.contentOnly:
# We already know the table we're parsing, skip
# parsing the table tag and continue to
# stack '2' which begins parsing content
self.contentStack.append([])
self.stackSize = 2
return
stackSize = self.stackSize
self.stackSize = stackSize + 1
subFile = attrs.get("src")
if subFile is not None:
if hasattr(self.file, 'name'):
# if file has a name, get its parent directory
dirname = os.path.dirname(self.file.name)
else:
# else fall back to using the current working directory
dirname = os.getcwd()
subFile = os.path.join(dirname, subFile)
if not stackSize:
if name != "ttFont":
raise TTXParseError("illegal root tag: %s" % name)
@ -103,7 +85,15 @@ class XMLReader(object):
self.ttFont.sfntVersion = sfntVersion
self.contentStack.append([])
elif stackSize == 1:
subFile = attrs.get("src")
if subFile is not None:
if hasattr(self.file, 'name'):
# if file has a name, get its parent directory
dirname = os.path.dirname(self.file.name)
else:
# else fall back to using the current working directory
dirname = os.getcwd()
subFile = os.path.join(dirname, subFile)
subReader = XMLReader(subFile, self.ttFont, self.progress)
subReader.read()
self.contentStack.append([])
@ -129,11 +119,6 @@ class XMLReader(object):
self.currentTable = tableClass(tag)
self.ttFont[tag] = self.currentTable
self.contentStack.append([])
elif stackSize == 2 and subFile is not None:
subReader = XMLReader(subFile, self.ttFont, self.progress, contentOnly=True)
subReader.read()
self.contentStack.append([])
self.root = subReader.root
elif stackSize == 2:
self.contentStack.append([])
self.root = (name, attrs, self.contentStack[-1])
@ -149,13 +134,12 @@ class XMLReader(object):
def _endElementHandler(self, name):
self.stackSize = self.stackSize - 1
del self.contentStack[-1]
if not self.contentOnly:
if self.stackSize == 1:
self.root = None
elif self.stackSize == 2:
name, attrs, content = self.root
self.currentTable.fromXML(name, attrs, content, self.ttFont)
self.root = None
if self.stackSize == 1:
self.root = None
elif self.stackSize == 2:
name, attrs, content = self.root
self.currentTable.fromXML(name, attrs, content, self.ttFont)
self.root = None
class ProgressPrinter(object):

View File

@ -247,8 +247,7 @@ class TTFont(object):
def saveXML(self, fileOrPath, progress=None, quiet=None,
tables=None, skipTables=None, splitTables=False, disassembleInstructions=True,
splitGlyphs=False, bitmapGlyphDataFormat='raw', newlinestr=None):
bitmapGlyphDataFormat='raw', newlinestr=None):
"""Export the font as TTX (an XML-based text file), or as a series of text
files when splitTables is true. In the latter case, the 'fileOrPath'
argument should be a path to a directory.
@ -291,7 +290,7 @@ class TTFont(object):
if not splitTables:
writer.newline()
if splitTables or splitGlyphs:
else:
# 'fileOrPath' must now be a path
path, ext = os.path.splitext(fileOrPath)
fileNameTemplate = path + ".%s" + ext
@ -300,11 +299,8 @@ class TTFont(object):
if progress:
progress.set(i)
tag = tables[i]
if splitTables or (splitGlyphs and tag == 'glyf'):
tablePath = fileNameTemplate % tagToIdentifier(tag)
else:
tablePath = None
if splitTables:
tablePath = fileNameTemplate % tagToIdentifier(tag)
tableWriter = xmlWriter.XMLWriter(tablePath, idlefunc=idlefunc,
newlinestr=newlinestr)
tableWriter.begintag("ttFont", ttLibVersion=version)
@ -314,7 +310,7 @@ class TTFont(object):
writer.newline()
else:
tableWriter = writer
self._tableToXML(tableWriter, tag, progress, splitGlyphs=splitGlyphs)
self._tableToXML(tableWriter, tag, progress)
if splitTables:
tableWriter.endtag("ttFont")
tableWriter.newline()
@ -328,7 +324,7 @@ class TTFont(object):
if not hasattr(fileOrPath, "write") and fileOrPath != "-":
writer.close()
def _tableToXML(self, writer, tag, progress, splitGlyphs=False, quiet=None):
def _tableToXML(self, writer, tag, progress, quiet=None):
if quiet is not None:
deprecateArgument("quiet", "configure logging instead")
if tag in self:
@ -350,9 +346,7 @@ class TTFont(object):
attrs['raw'] = True
writer.begintag(xmlTag, **attrs)
writer.newline()
if tag == "glyf":
table.toXML(writer, self, progress, splitGlyphs)
elif tag == "CFF ":
if tag in ("glyf", "CFF "):
table.toXML(writer, self, progress)
else:
table.toXML(writer, self)
@ -879,8 +873,8 @@ def _escapechar(c):
return hex(byteord(c))[2:]
def nameToIdentifier(name):
"""Convert a name to a valid (but UGLY) python identifier,
def tagToIdentifier(tag):
"""Convert a table tag to a valid (but UGLY) python identifier,
as well as a filename that's guaranteed to be unique even on a
caseless file system. Each character is mapped to two characters.
Lowercase letters get an underscore before the letter, uppercase
@ -893,25 +887,19 @@ def nameToIdentifier(name):
'OS/2' -> 'O_S_2f_2'
"""
import re
while len(name) > 1 and name[-1] == ' ':
name = name[:-1]
tag = Tag(tag)
if tag == "GlyphOrder":
return tag
assert len(tag) == 4, "tag should be 4 characters long"
while len(tag) > 1 and tag[-1] == ' ':
tag = tag[:-1]
ident = ""
for c in name:
for c in tag:
ident = ident + _escapechar(c)
if re.match("[0-9]", ident):
ident = "_" + ident
return ident
def tagToIdentifier(tag):
"""This performs the same conversion which nameToIdentifiier does
with the additional assertion that the source tag is 4 characters
long which is criteria for a valid tag name.
"""
if tag == "GlyphOrder":
return tag
ret = nameToIdentifier(tag)
assert len(tag) == 4, "tag should be 4 characters long"
return ret
def identifierToTag(ident):
"""the opposite of tagToIdentifier()"""

View File

@ -5,7 +5,6 @@ from collections import namedtuple
from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools import ttLib
from fontTools import version
from fontTools.misc.textTools import safeEval, pad
from fontTools.misc.arrayTools import calcBounds, calcIntBounds, pointInRect
from fontTools.misc.bezierTools import calcQuadraticBounds
@ -17,17 +16,10 @@ import sys
import struct
import array
import logging
import os
from fontTools.misc import xmlWriter
from fontTools.ttLib import nameToIdentifier
log = logging.getLogger(__name__)
# We compute the version the same as is computed in ttlib/__init__
# so that we can write 'ttLibVersion' attribute of the glyf TTX files
# when glyf is written to separate files.
version = ".".join(version.split('.')[:2])
#
# The Apple and MS rasterizers behave differently for
# scaled composite components: one does scale first and then translate
@ -118,16 +110,12 @@ class table__g_l_y_f(DefaultTable.DefaultTable):
ttFont['maxp'].numGlyphs = len(self.glyphs)
return data
def toXML(self, writer, ttFont, progress=None, splitGlyphs=False):
notice = (
"The xMin, yMin, xMax and yMax values\n"
"will be recalculated by the compiler.")
def toXML(self, writer, ttFont, progress=None):
writer.newline()
glyphNames = ttFont.getGlyphNames()
if not splitGlyphs:
writer.newline()
writer.comment(notice)
writer.newline()
writer.newline()
writer.comment("The xMin, yMin, xMax and yMax values\nwill be recalculated by the compiler.")
writer.newline()
writer.newline()
counter = 0
progressStep = 10
numGlyphs = len(glyphNames)
@ -138,44 +126,21 @@ class table__g_l_y_f(DefaultTable.DefaultTable):
counter = counter + 1
glyph = self[glyphName]
if glyph.numberOfContours:
if splitGlyphs:
path, ext = os.path.splitext(writer.file.name)
fileNameTemplate = path + ".%s" + ext
glyphPath = fileNameTemplate % nameToIdentifier(glyphName)
glyphWriter = xmlWriter.XMLWriter(
glyphPath, idlefunc=writer.idlefunc,
newlinestr=writer.newlinestr)
glyphWriter.begintag("ttFont", ttLibVersion=version)
glyphWriter.newline()
glyphWriter.begintag("glyf")
glyphWriter.newline()
glyphWriter.comment(notice)
glyphWriter.newline()
writer.simpletag("TTGlyph", src=os.path.basename(glyphPath))
else:
glyphWriter = writer
glyphWriter.begintag('TTGlyph', [
("name", glyphName),
("xMin", glyph.xMin),
("yMin", glyph.yMin),
("xMax", glyph.xMax),
("yMax", glyph.yMax),
])
glyphWriter.newline()
glyph.toXML(glyphWriter, ttFont)
glyphWriter.endtag('TTGlyph')
glyphWriter.newline()
if splitGlyphs:
glyphWriter.endtag("glyf")
glyphWriter.newline()
glyphWriter.endtag("ttFont")
glyphWriter.newline()
glyphWriter.close()
writer.begintag('TTGlyph', [
("name", glyphName),
("xMin", glyph.xMin),
("yMin", glyph.yMin),
("xMax", glyph.xMax),
("yMax", glyph.yMax),
])
writer.newline()
glyph.toXML(writer, ttFont)
writer.endtag('TTGlyph')
writer.newline()
else:
writer.simpletag('TTGlyph', name=glyphName)
writer.comment("contains no outline data")
if not splitGlyphs:
writer.newline()
writer.newline()
writer.newline()
def fromXML(self, name, attrs, content, ttFont):

View File

@ -38,9 +38,6 @@ usage: ttx [options] inputfile1 [... inputfileN]
to the individual table dumps. This file can be used as
input to ttx, as long as the table files are in the
same directory.
-g Split glyf table: Save the glyf data into separate TTX files
per glyph and write a small TTX for the glyf table which
contains references to the individual TTGlyph elements.
-i Do NOT disassemble TT instructions: when this option is given,
all TrueType programs (glyph programs, the font program and the
pre-program) will be written to the TTX file as hex data
@ -113,7 +110,6 @@ class Options(object):
verbose = False
quiet = False
splitTables = False
splitGlyphs = False
disassembleInstructions = True
mergeFile = None
recalcBBoxes = True
@ -164,8 +160,6 @@ class Options(object):
self.skipTables.append(value)
elif option == "-s":
self.splitTables = True
elif option == "-g":
self.splitGlyphs = True
elif option == "-i":
self.disassembleInstructions = False
elif option == "-z":
@ -261,7 +255,6 @@ def ttDump(input, output, options):
tables=options.onlyTables,
skipTables=options.skipTables,
splitTables=options.splitTables,
splitGlyphs=options.splitGlyphs,
disassembleInstructions=options.disassembleInstructions,
bitmapGlyphDataFormat=options.bitmapGlyphDataFormat,
newlinestr=options.newlinestr)
@ -325,7 +318,7 @@ def guessFileType(fileName):
def parseOptions(args):
rawOptions, files = getopt.getopt(args, "ld:o:fvqht:x:sgim:z:baey:",
rawOptions, files = getopt.getopt(args, "ld:o:fvqht:x:sim:z:baey:",
['unicodedata=', "recalc-timestamp", 'flavor=', 'version',
'with-zopfli', 'newline='])

View File

@ -142,48 +142,7 @@ class TestXMLReader(unittest.TestCase):
self.assertTrue(reader.file.closed)
os.remove(tmp.name)
def test_read_sub_file(self):
# Verifies that sub-file content is able to be read to a table.
expectedContent = u'testContent'
expectedNameID = '1'
expectedPlatform = '3'
expectedLangId = '0x409'
with tempfile.NamedTemporaryFile(delete=False) as tmp:
subFileData = (
'<ttFont ttLibVersion="3.15">'
'<name>'
'<namerecord nameID="%s" platformID="%s" platEncID="1" langID="%s">'
'%s'
'</namerecord>'
'</name>'
'</ttFont>'
) % (expectedNameID, expectedPlatform, expectedLangId, expectedContent)
tmp.write(subFileData.encode("utf-8"))
with tempfile.NamedTemporaryFile(delete=False) as tmp2:
fileData = (
'<ttFont ttLibVersion="3.15">'
'<name>'
'<namerecord src="%s"/>'
'</name>'
'</ttFont>'
) % tmp.name
tmp2.write(fileData.encode('utf-8'))
ttf = TTFont()
with open(tmp2.name, "rb") as f:
reader = XMLReader(f, ttf)
reader.read()
reader.close()
nameTable = ttf['name']
self.assertTrue(int(expectedNameID) == nameTable.names[0].nameID)
self.assertTrue(int(expectedLangId, 16) == nameTable.names[0].langID)
self.assertTrue(int(expectedPlatform) == nameTable.names[0].platformID)
self.assertEqual(expectedContent, nameTable.names[0].string.decode(nameTable.names[0].getEncoding()))
os.remove(tmp.name)
os.remove(tmp2.name)
if __name__ == '__main__':
import sys