2014-01-14 15:07:50 +08:00
|
|
|
from __future__ import print_function, division, absolute_import
|
2013-11-27 17:27:45 -05:00
|
|
|
from fontTools.misc.py23 import *
|
1999-12-16 21:34:53 +00:00
|
|
|
from fontTools import ttLib
|
|
|
|
from fontTools.misc.textTools import safeEval
|
2000-01-03 23:00:10 +00:00
|
|
|
from fontTools.ttLib.tables.DefaultTable import DefaultTable
|
2002-05-11 21:38:26 +00:00
|
|
|
import os
|
1999-12-16 21:34:53 +00:00
|
|
|
|
|
|
|
|
2002-05-01 21:06:11 +00:00
|
|
|
class TTXParseError(Exception): pass
|
1999-12-16 21:34:53 +00:00
|
|
|
|
2002-05-02 15:16:45 +00:00
|
|
|
BUFSIZE = 0x4000
|
|
|
|
|
1999-12-16 21:34:53 +00:00
|
|
|
|
2013-11-28 14:26:58 -05:00
|
|
|
class XMLReader(object):
|
1999-12-16 21:34:53 +00:00
|
|
|
|
2013-11-24 19:00:59 -05:00
|
|
|
def __init__(self, fileName, ttFont, progress=None, quiet=False):
|
1999-12-16 21:34:53 +00:00
|
|
|
self.ttFont = ttFont
|
2002-05-11 21:38:26 +00:00
|
|
|
self.fileName = fileName
|
1999-12-16 21:34:53 +00:00
|
|
|
self.progress = progress
|
2013-09-04 13:30:21 +01:00
|
|
|
self.quiet = quiet
|
1999-12-16 21:34:53 +00:00
|
|
|
self.root = None
|
2002-05-01 21:06:11 +00:00
|
|
|
self.contentStack = []
|
|
|
|
self.stackSize = 0
|
|
|
|
|
2013-11-24 19:00:59 -05:00
|
|
|
def read(self):
|
|
|
|
if self.progress:
|
|
|
|
import stat
|
2013-12-04 01:15:46 -05:00
|
|
|
self.progress.set(0, os.stat(self.fileName)[stat.ST_SIZE] // 100 or 1)
|
2013-12-04 01:17:21 -05:00
|
|
|
file = open(self.fileName)
|
|
|
|
self._parseFile(file)
|
2002-05-11 21:44:06 +00:00
|
|
|
file.close()
|
|
|
|
|
2013-11-24 19:00:59 -05:00
|
|
|
def _parseFile(self, file):
|
2002-05-01 21:32:37 +00:00
|
|
|
from xml.parsers.expat import ParserCreate
|
2013-08-20 15:29:19 -04:00
|
|
|
parser = ParserCreate()
|
2013-11-24 19:00:59 -05:00
|
|
|
parser.StartElementHandler = self._startElementHandler
|
|
|
|
parser.EndElementHandler = self._endElementHandler
|
|
|
|
parser.CharacterDataHandler = self._characterDataHandler
|
2002-05-01 21:32:37 +00:00
|
|
|
|
2002-05-02 15:16:45 +00:00
|
|
|
pos = 0
|
2013-11-27 04:15:34 -05:00
|
|
|
while True:
|
2002-05-02 15:16:45 +00:00
|
|
|
chunk = file.read(BUFSIZE)
|
|
|
|
if not chunk:
|
|
|
|
parser.Parse(chunk, 1)
|
|
|
|
break
|
|
|
|
pos = pos + len(chunk)
|
|
|
|
if self.progress:
|
2013-11-27 17:46:17 -05:00
|
|
|
self.progress.set(pos // 100)
|
2002-05-02 15:16:45 +00:00
|
|
|
parser.Parse(chunk, 0)
|
2002-05-01 21:06:11 +00:00
|
|
|
|
2013-11-24 19:00:59 -05:00
|
|
|
def _startElementHandler(self, name, attrs):
|
2002-05-01 21:06:11 +00:00
|
|
|
stackSize = self.stackSize
|
2002-05-02 20:54:08 +00:00
|
|
|
self.stackSize = stackSize + 1
|
2000-01-03 23:00:10 +00:00
|
|
|
if not stackSize:
|
2013-11-27 02:40:30 -05:00
|
|
|
if name != "ttFont":
|
2013-11-27 02:42:28 -05:00
|
|
|
raise TTXParseError("illegal root tag: %s" % name)
|
2002-05-11 21:38:26 +00:00
|
|
|
sfntVersion = attrs.get("sfntVersion")
|
|
|
|
if sfntVersion is not None:
|
2013-11-27 02:40:30 -05:00
|
|
|
if len(sfntVersion) != 4:
|
2002-05-11 21:38:26 +00:00
|
|
|
sfntVersion = safeEval('"' + sfntVersion + '"')
|
|
|
|
self.ttFont.sfntVersion = sfntVersion
|
2002-05-01 21:06:11 +00:00
|
|
|
self.contentStack.append([])
|
2000-01-03 23:00:10 +00:00
|
|
|
elif stackSize == 1:
|
2002-05-11 21:38:26 +00:00
|
|
|
subFile = attrs.get("src")
|
|
|
|
if subFile is not None:
|
|
|
|
subFile = os.path.join(os.path.dirname(self.fileName), subFile)
|
2013-11-24 19:00:59 -05:00
|
|
|
subReader = XMLReader(subFile, self.ttFont, self.progress, self.quiet)
|
|
|
|
subReader.read()
|
2002-05-11 21:38:26 +00:00
|
|
|
self.contentStack.append([])
|
|
|
|
return
|
2002-05-23 09:42:45 +00:00
|
|
|
tag = ttLib.xmlToTag(name)
|
|
|
|
msg = "Parsing '%s' table..." % tag
|
1999-12-16 21:34:53 +00:00
|
|
|
if self.progress:
|
|
|
|
self.progress.setlabel(msg)
|
|
|
|
elif self.ttFont.verbose:
|
|
|
|
ttLib.debugmsg(msg)
|
|
|
|
else:
|
2013-09-04 13:30:21 +01:00
|
|
|
if not self.quiet:
|
2013-11-27 04:57:33 -05:00
|
|
|
print(msg)
|
2002-05-23 09:42:45 +00:00
|
|
|
if tag == "GlyphOrder":
|
|
|
|
tableClass = ttLib.GlyphOrder
|
2014-01-31 18:03:01 -05:00
|
|
|
elif "ERROR" in attrs or ('raw' in attrs and safeEval(attrs['raw'])):
|
2000-01-03 23:00:10 +00:00
|
|
|
tableClass = DefaultTable
|
|
|
|
else:
|
|
|
|
tableClass = ttLib.getTableClass(tag)
|
|
|
|
if tableClass is None:
|
|
|
|
tableClass = DefaultTable
|
2013-11-27 02:33:03 -05:00
|
|
|
if tag == 'loca' and tag in self.ttFont:
|
2002-05-25 15:28:48 +00:00
|
|
|
# Special-case the 'loca' table as we need the
|
2002-05-02 20:54:08 +00:00
|
|
|
# original if the 'glyf' table isn't recompiled.
|
2002-05-01 21:06:11 +00:00
|
|
|
self.currentTable = self.ttFont[tag]
|
1999-12-27 20:02:32 +00:00
|
|
|
else:
|
2002-05-01 21:06:11 +00:00
|
|
|
self.currentTable = tableClass(tag)
|
|
|
|
self.ttFont[tag] = self.currentTable
|
|
|
|
self.contentStack.append([])
|
2000-01-03 23:00:10 +00:00
|
|
|
elif stackSize == 2:
|
2002-05-01 21:06:11 +00:00
|
|
|
self.contentStack.append([])
|
|
|
|
self.root = (name, attrs, self.contentStack[-1])
|
1999-12-16 21:34:53 +00:00
|
|
|
else:
|
2013-12-04 01:15:46 -05:00
|
|
|
l = []
|
|
|
|
self.contentStack[-1].append((name, attrs, l))
|
|
|
|
self.contentStack.append(l)
|
1999-12-16 21:34:53 +00:00
|
|
|
|
2013-11-24 19:00:59 -05:00
|
|
|
def _characterDataHandler(self, data):
|
2002-05-01 21:06:11 +00:00
|
|
|
if self.stackSize > 1:
|
|
|
|
self.contentStack[-1].append(data)
|
1999-12-16 21:34:53 +00:00
|
|
|
|
2013-11-24 19:00:59 -05:00
|
|
|
def _endElementHandler(self, name):
|
2002-05-01 21:06:11 +00:00
|
|
|
self.stackSize = self.stackSize - 1
|
|
|
|
del self.contentStack[-1]
|
|
|
|
if self.stackSize == 1:
|
1999-12-16 21:34:53 +00:00
|
|
|
self.root = None
|
2002-05-01 21:06:11 +00:00
|
|
|
elif self.stackSize == 2:
|
2013-11-27 03:19:32 -05:00
|
|
|
name, attrs, content = self.root
|
|
|
|
self.currentTable.fromXML(name, attrs, content, self.ttFont)
|
1999-12-16 21:34:53 +00:00
|
|
|
self.root = None
|
|
|
|
|
|
|
|
|
2013-11-28 14:26:58 -05:00
|
|
|
class ProgressPrinter(object):
|
1999-12-16 21:34:53 +00:00
|
|
|
|
|
|
|
def __init__(self, title, maxval=100):
|
2013-11-27 04:57:33 -05:00
|
|
|
print(title)
|
1999-12-16 21:34:53 +00:00
|
|
|
|
|
|
|
def set(self, val, maxval=None):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def increment(self, val=1):
|
|
|
|
pass
|
|
|
|
|
2002-07-23 16:44:25 +00:00
|
|
|
def setLabel(self, text):
|
2013-11-27 04:57:33 -05:00
|
|
|
print(text)
|
1999-12-16 21:34:53 +00:00
|
|
|
|