xmlReader.py revision 180ace6a5ff1399ec53bc696e8bef7cce6eef39a
1from fontTools import ttLib 2from fontTools.misc.textTools import safeEval 3from fontTools.ttLib.tables.DefaultTable import DefaultTable 4import os 5 6 7class TTXParseError(Exception): pass 8 9BUFSIZE = 0x4000 10 11 12class XMLReader: 13 14 def __init__(self, fileName, ttFont, progress=None, quiet=False): 15 self.ttFont = ttFont 16 self.fileName = fileName 17 self.progress = progress 18 self.quiet = quiet 19 self.root = None 20 self.contentStack = [] 21 self.stackSize = 0 22 23 def read(self): 24 if self.progress: 25 import stat 26 self.progress.set(0, os.stat(fileName)[stat.ST_SIZE] / 100 or 1) 27 file = open(self.fileName) 28 self._parseFile(file) 29 file.close() 30 31 def _parseFile(self, file): 32 from xml.parsers.expat import ParserCreate 33 parser = ParserCreate() 34 parser.returns_unicode = 0 35 parser.StartElementHandler = self._startElementHandler 36 parser.EndElementHandler = self._endElementHandler 37 parser.CharacterDataHandler = self._characterDataHandler 38 39 pos = 0 40 while 1: 41 chunk = file.read(BUFSIZE) 42 if not chunk: 43 parser.Parse(chunk, 1) 44 break 45 pos = pos + len(chunk) 46 if self.progress: 47 self.progress.set(pos / 100) 48 parser.Parse(chunk, 0) 49 50 def _startElementHandler(self, name, attrs): 51 stackSize = self.stackSize 52 self.stackSize = stackSize + 1 53 if not stackSize: 54 if name != "ttFont": 55 raise TTXParseError, "illegal root tag: %s" % name 56 sfntVersion = attrs.get("sfntVersion") 57 if sfntVersion is not None: 58 if len(sfntVersion) != 4: 59 sfntVersion = safeEval('"' + sfntVersion + '"') 60 self.ttFont.sfntVersion = sfntVersion 61 self.contentStack.append([]) 62 elif stackSize == 1: 63 subFile = attrs.get("src") 64 if subFile is not None: 65 subFile = os.path.join(os.path.dirname(self.fileName), subFile) 66 subReader = XMLReader(subFile, self.ttFont, self.progress, self.quiet) 67 subReader.read() 68 self.contentStack.append([]) 69 return 70 tag = ttLib.xmlToTag(name) 71 msg = "Parsing '%s' table..." % tag 72 if self.progress: 73 self.progress.setlabel(msg) 74 elif self.ttFont.verbose: 75 ttLib.debugmsg(msg) 76 else: 77 if not self.quiet: 78 print msg 79 if tag == "GlyphOrder": 80 tableClass = ttLib.GlyphOrder 81 elif "ERROR" in attrs: 82 tableClass = DefaultTable 83 else: 84 tableClass = ttLib.getTableClass(tag) 85 if tableClass is None: 86 tableClass = DefaultTable 87 if tag == 'loca' and tag in self.ttFont: 88 # Special-case the 'loca' table as we need the 89 # original if the 'glyf' table isn't recompiled. 90 self.currentTable = self.ttFont[tag] 91 else: 92 self.currentTable = tableClass(tag) 93 self.ttFont[tag] = self.currentTable 94 self.contentStack.append([]) 95 elif stackSize == 2: 96 self.contentStack.append([]) 97 self.root = (name, attrs, self.contentStack[-1]) 98 else: 99 list = [] 100 self.contentStack[-1].append((name, attrs, list)) 101 self.contentStack.append(list) 102 103 def _characterDataHandler(self, data): 104 if self.stackSize > 1: 105 self.contentStack[-1].append(data) 106 107 def _endElementHandler(self, name): 108 self.stackSize = self.stackSize - 1 109 del self.contentStack[-1] 110 if self.stackSize == 1: 111 self.root = None 112 elif self.stackSize == 2: 113 self.currentTable.fromXML(self.root, self.ttFont) 114 self.root = None 115 116 117class ProgressPrinter: 118 119 def __init__(self, title, maxval=100): 120 print title 121 122 def set(self, val, maxval=None): 123 pass 124 125 def increment(self, val=1): 126 pass 127 128 def setLabel(self, text): 129 print text 130 131