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

This reverts commit 060f856f92e0fb2d8e60f6be080c89c08528bacb, reversing
changes made to 1e42224af741fac73e20f7193d8115cfda7d3594.
This commit is contained in:
Cosimo Lupo 2017-12-18 12:26:20 +00:00
parent 0459aaacdf
commit 232e2b8467
No known key found for this signature in database
GPG Key ID: 59D54DB0C9976482
5 changed files with 148 additions and 40 deletions

View File

@ -17,7 +17,8 @@ BUFSIZE = 0x4000
class XMLReader(object):
def __init__(self, fileOrPath, ttFont, progress=None, quiet=None):
def __init__(self, fileOrPath, ttFont, progress=None, quiet=None, contentOnly=False):
if fileOrPath == '-':
fileOrPath = sys.stdin
if not hasattr(fileOrPath, "read"):
@ -35,6 +36,7 @@ class XMLReader(object):
self.quiet = quiet
self.root = None
self.contentStack = []
self.contentOnly = contentOnly
self.stackSize = 0
def read(self, rootless=False):
@ -73,8 +75,24 @@ 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)
@ -85,15 +103,7 @@ 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([])
@ -119,6 +129,11 @@ 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])
@ -134,12 +149,13 @@ class XMLReader(object):
def _endElementHandler(self, name):
self.stackSize = self.stackSize - 1
del self.contentStack[-1]
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 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
class ProgressPrinter(object):

View File

@ -5,6 +5,7 @@ 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
@ -16,10 +17,17 @@ import sys
import struct
import array
import logging
import os
from fontTools.misc import xmlWriter
from fontTools.misc.filenames import userNameToFileName
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
@ -110,31 +118,64 @@ class table__g_l_y_f(DefaultTable.DefaultTable):
ttFont['maxp'].numGlyphs = len(self.glyphs)
return data
def toXML(self, writer, ttFont):
writer.newline()
def toXML(self, writer, ttFont, splitGlyphs=False):
notice = (
"The xMin, yMin, xMax and yMax values\n"
"will be recalculated by the compiler.")
glyphNames = ttFont.getGlyphNames()
writer.comment("The xMin, yMin, xMax and yMax values\nwill be recalculated by the compiler.")
writer.newline()
writer.newline()
if not splitGlyphs:
writer.newline()
writer.comment(notice)
writer.newline()
writer.newline()
numGlyphs = len(glyphNames)
if splitGlyphs:
path, ext = os.path.splitext(writer.file.name)
existingGlyphFiles = set()
for glyphName in glyphNames:
glyph = self[glyphName]
if glyph.numberOfContours:
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()
if splitGlyphs:
glyphPath = userNameToFileName(
tounicode(glyphName, 'utf-8'),
existingGlyphFiles,
prefix=("%s%s"%(path, "_")),
suffix=ext)
existingGlyphFiles.add(glyphPath.lower())
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()
else:
writer.simpletag('TTGlyph', name=glyphName)
writer.comment("contains no outline data")
writer.newline()
if not splitGlyphs:
writer.newline()
writer.newline()
def fromXML(self, name, attrs, content, ttFont):

View File

@ -224,8 +224,8 @@ class TTFont(object):
def _saveXML(self, writer,
writeVersion=True,
quiet=None, tables=None, skipTables=None, splitTables=False,
disassembleInstructions=True, bitmapGlyphDataFormat='raw'):
splitGlyphs=False, disassembleInstructions=True,
bitmapGlyphDataFormat='raw'):
if quiet is not None:
deprecateArgument("quiet", "configure logging instead")
@ -251,6 +251,9 @@ class TTFont(object):
writer.begintag("ttFont", sfntVersion=repr(tostr(self.sfntVersion))[1:-1])
writer.newline()
# always splitTables if splitGlyphs is enabled
splitTables = splitTables or splitGlyphs
if not splitTables:
writer.newline()
else:
@ -270,7 +273,7 @@ class TTFont(object):
writer.newline()
else:
tableWriter = writer
self._tableToXML(tableWriter, tag)
self._tableToXML(tableWriter, tag, splitGlyphs=splitGlyphs)
if splitTables:
tableWriter.endtag("ttFont")
tableWriter.newline()
@ -278,7 +281,7 @@ class TTFont(object):
writer.endtag("ttFont")
writer.newline()
def _tableToXML(self, writer, tag, quiet=None):
def _tableToXML(self, writer, tag, quiet=None, splitGlyphs=False):
if quiet is not None:
deprecateArgument("quiet", "configure logging instead")
if tag in self:
@ -298,8 +301,8 @@ class TTFont(object):
attrs['raw'] = True
writer.begintag(xmlTag, **attrs)
writer.newline()
if tag in ("glyf", "CFF "):
table.toXML(writer, self)
if tag == "glyf":
table.toXML(writer, self, splitGlyphs=splitGlyphs)
else:
table.toXML(writer, self)
writer.endtag(xmlTag)

View File

@ -38,6 +38,9 @@ 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
@ -110,6 +113,7 @@ class Options(object):
verbose = False
quiet = False
splitTables = False
splitGlyphs = False
disassembleInstructions = True
mergeFile = None
recalcBBoxes = True
@ -160,6 +164,8 @@ 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":
@ -255,6 +261,7 @@ 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)
@ -318,7 +325,7 @@ def guessFileType(fileName):
def parseOptions(args):
rawOptions, files = getopt.getopt(args, "ld:o:fvqht:x:sim:z:baey:",
rawOptions, files = getopt.getopt(args, "ld:o:fvqht:x:sgim:z:baey:",
['unicodedata=', "recalc-timestamp", 'flavor=', 'version',
'with-zopfli', 'newline='])

View File

@ -142,7 +142,48 @@ 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