diff options
Diffstat (limited to 'Lib/fontTools/misc/xmlReader.py')
-rw-r--r-- | Lib/fontTools/misc/xmlReader.py | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/Lib/fontTools/misc/xmlReader.py b/Lib/fontTools/misc/xmlReader.py new file mode 100644 index 00000000..85dd4410 --- /dev/null +++ b/Lib/fontTools/misc/xmlReader.py @@ -0,0 +1,132 @@ +from __future__ import print_function, division, absolute_import +from fontTools.misc.py23 import * +from fontTools import ttLib +from fontTools.misc.textTools import safeEval +from fontTools.ttLib.tables.DefaultTable import DefaultTable +import os + + +class TTXParseError(Exception): pass + +BUFSIZE = 0x4000 + + +class XMLReader(object): + + def __init__(self, fileName, ttFont, progress=None, quiet=False): + self.ttFont = ttFont + self.fileName = fileName + self.progress = progress + self.quiet = quiet + self.root = None + self.contentStack = [] + self.stackSize = 0 + + def read(self): + if self.progress: + import stat + self.progress.set(0, os.stat(self.fileName)[stat.ST_SIZE] // 100 or 1) + file = open(self.fileName) + self._parseFile(file) + file.close() + + def _parseFile(self, file): + from xml.parsers.expat import ParserCreate + parser = ParserCreate() + parser.StartElementHandler = self._startElementHandler + parser.EndElementHandler = self._endElementHandler + parser.CharacterDataHandler = self._characterDataHandler + + pos = 0 + while True: + chunk = file.read(BUFSIZE) + if not chunk: + parser.Parse(chunk, 1) + break + pos = pos + len(chunk) + if self.progress: + self.progress.set(pos // 100) + parser.Parse(chunk, 0) + + def _startElementHandler(self, name, attrs): + stackSize = self.stackSize + self.stackSize = stackSize + 1 + if not stackSize: + if name != "ttFont": + raise TTXParseError("illegal root tag: %s" % name) + sfntVersion = attrs.get("sfntVersion") + if sfntVersion is not None: + if len(sfntVersion) != 4: + sfntVersion = safeEval('"' + sfntVersion + '"') + self.ttFont.sfntVersion = sfntVersion + self.contentStack.append([]) + elif stackSize == 1: + subFile = attrs.get("src") + if subFile is not None: + subFile = os.path.join(os.path.dirname(self.fileName), subFile) + subReader = XMLReader(subFile, self.ttFont, self.progress, self.quiet) + subReader.read() + self.contentStack.append([]) + return + tag = ttLib.xmlToTag(name) + msg = "Parsing '%s' table..." % tag + if self.progress: + self.progress.setlabel(msg) + elif self.ttFont.verbose: + ttLib.debugmsg(msg) + else: + if not self.quiet: + print(msg) + if tag == "GlyphOrder": + tableClass = ttLib.GlyphOrder + elif "ERROR" in attrs or ('raw' in attrs and safeEval(attrs['raw'])): + tableClass = DefaultTable + else: + tableClass = ttLib.getTableClass(tag) + if tableClass is None: + tableClass = DefaultTable + if tag == 'loca' and tag in self.ttFont: + # Special-case the 'loca' table as we need the + # original if the 'glyf' table isn't recompiled. + self.currentTable = self.ttFont[tag] + else: + self.currentTable = tableClass(tag) + self.ttFont[tag] = self.currentTable + self.contentStack.append([]) + elif stackSize == 2: + self.contentStack.append([]) + self.root = (name, attrs, self.contentStack[-1]) + else: + l = [] + self.contentStack[-1].append((name, attrs, l)) + self.contentStack.append(l) + + def _characterDataHandler(self, data): + if self.stackSize > 1: + self.contentStack[-1].append(data) + + 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 + + +class ProgressPrinter(object): + + def __init__(self, title, maxval=100): + print(title) + + def set(self, val, maxval=None): + pass + + def increment(self, val=1): + pass + + def setLabel(self, text): + print(text) + |