xmlReader.py revision 30e691edd056ba22fa8970280e986747817bec3d
130e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom __future__ import print_function 230e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom fontTools.misc.py23 import * 37842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools import ttLib 47842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools.misc.textTools import safeEval 5f8fd4777d273836a1222b72f6761cb6fdf9ec87aJustfrom fontTools.ttLib.tables.DefaultTable import DefaultTable 64bb05c6ad4b112de40642d77663aa87d145f863fjvrimport os 77842e56b97ce677b83bdab09cda48bc2d89ac75aJust 87842e56b97ce677b83bdab09cda48bc2d89ac75aJust 9ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvrclass TTXParseError(Exception): pass 107842e56b97ce677b83bdab09cda48bc2d89ac75aJust 119b7b8e0f5b5f968acb95f8c3a484ea8d42924d65jvrBUFSIZE = 0x4000 129b7b8e0f5b5f968acb95f8c3a484ea8d42924d65jvr 137842e56b97ce677b83bdab09cda48bc2d89ac75aJust 143ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbodclass XMLReader: 157842e56b97ce677b83bdab09cda48bc2d89ac75aJust 163ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod def __init__(self, fileName, ttFont, progress=None, quiet=False): 177842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.ttFont = ttFont 184bb05c6ad4b112de40642d77663aa87d145f863fjvr self.fileName = fileName 197842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.progress = progress 2085af40e7d8c4f4f4a3df3562a5ec9e5731cfe43fDave Crossland self.quiet = quiet 217842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.root = None 22ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.contentStack = [] 23ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.stackSize = 0 24ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr 253ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod def read(self): 263ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod if self.progress: 273ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod import stat 283ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod self.progress.set(0, os.stat(fileName)[stat.ST_SIZE] / 100 or 1) 2956bfea43176d03cede26f8de51638c4ab9f4bd64jvr file = open(self.fileName) 303ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod self._parseFile(file) 3156bfea43176d03cede26f8de51638c4ab9f4bd64jvr file.close() 3256bfea43176d03cede26f8de51638c4ab9f4bd64jvr 333ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod def _parseFile(self, file): 34e493669d196f292f24d4c09ce340c3e67749bce5jvr from xml.parsers.expat import ParserCreate 354b3df49b5b70b3618e91e3ab954cedca773831d6Behdad Esfahbod parser = ParserCreate() 36e493669d196f292f24d4c09ce340c3e67749bce5jvr parser.returns_unicode = 0 373ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod parser.StartElementHandler = self._startElementHandler 383ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod parser.EndElementHandler = self._endElementHandler 393ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod parser.CharacterDataHandler = self._characterDataHandler 40e493669d196f292f24d4c09ce340c3e67749bce5jvr 419b7b8e0f5b5f968acb95f8c3a484ea8d42924d65jvr pos = 0 42ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod while True: 439b7b8e0f5b5f968acb95f8c3a484ea8d42924d65jvr chunk = file.read(BUFSIZE) 449b7b8e0f5b5f968acb95f8c3a484ea8d42924d65jvr if not chunk: 459b7b8e0f5b5f968acb95f8c3a484ea8d42924d65jvr parser.Parse(chunk, 1) 469b7b8e0f5b5f968acb95f8c3a484ea8d42924d65jvr break 479b7b8e0f5b5f968acb95f8c3a484ea8d42924d65jvr pos = pos + len(chunk) 489b7b8e0f5b5f968acb95f8c3a484ea8d42924d65jvr if self.progress: 499b7b8e0f5b5f968acb95f8c3a484ea8d42924d65jvr self.progress.set(pos / 100) 509b7b8e0f5b5f968acb95f8c3a484ea8d42924d65jvr parser.Parse(chunk, 0) 51ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr 523ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod def _startElementHandler(self, name, attrs): 53ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr stackSize = self.stackSize 54e82b4d5658a7a38cf92b4b9392861257a2cfbb36jvr self.stackSize = stackSize + 1 55f8fd4777d273836a1222b72f6761cb6fdf9ec87aJust if not stackSize: 56180ace6a5ff1399ec53bc696e8bef7cce6eef39aBehdad Esfahbod if name != "ttFont": 57cd5aad92f23737ff93a110d5c73d624658a28da8Behdad Esfahbod raise TTXParseError("illegal root tag: %s" % name) 584bb05c6ad4b112de40642d77663aa87d145f863fjvr sfntVersion = attrs.get("sfntVersion") 594bb05c6ad4b112de40642d77663aa87d145f863fjvr if sfntVersion is not None: 60180ace6a5ff1399ec53bc696e8bef7cce6eef39aBehdad Esfahbod if len(sfntVersion) != 4: 614bb05c6ad4b112de40642d77663aa87d145f863fjvr sfntVersion = safeEval('"' + sfntVersion + '"') 624bb05c6ad4b112de40642d77663aa87d145f863fjvr self.ttFont.sfntVersion = sfntVersion 63ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.contentStack.append([]) 64f8fd4777d273836a1222b72f6761cb6fdf9ec87aJust elif stackSize == 1: 654bb05c6ad4b112de40642d77663aa87d145f863fjvr subFile = attrs.get("src") 664bb05c6ad4b112de40642d77663aa87d145f863fjvr if subFile is not None: 674bb05c6ad4b112de40642d77663aa87d145f863fjvr subFile = os.path.join(os.path.dirname(self.fileName), subFile) 683ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod subReader = XMLReader(subFile, self.ttFont, self.progress, self.quiet) 693ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod subReader.read() 704bb05c6ad4b112de40642d77663aa87d145f863fjvr self.contentStack.append([]) 714bb05c6ad4b112de40642d77663aa87d145f863fjvr return 720011bb691018c7feed1f8c3554d88b9ae096e127jvr tag = ttLib.xmlToTag(name) 730011bb691018c7feed1f8c3554d88b9ae096e127jvr msg = "Parsing '%s' table..." % tag 747842e56b97ce677b83bdab09cda48bc2d89ac75aJust if self.progress: 757842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.progress.setlabel(msg) 767842e56b97ce677b83bdab09cda48bc2d89ac75aJust elif self.ttFont.verbose: 777842e56b97ce677b83bdab09cda48bc2d89ac75aJust ttLib.debugmsg(msg) 787842e56b97ce677b83bdab09cda48bc2d89ac75aJust else: 7985af40e7d8c4f4f4a3df3562a5ec9e5731cfe43fDave Crossland if not self.quiet: 803ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod print(msg) 810011bb691018c7feed1f8c3554d88b9ae096e127jvr if tag == "GlyphOrder": 820011bb691018c7feed1f8c3554d88b9ae096e127jvr tableClass = ttLib.GlyphOrder 83bc5e1cb195c0bfa1c8e7507326d5a9ad05aecb4bBehdad Esfahbod elif "ERROR" in attrs: 84f8fd4777d273836a1222b72f6761cb6fdf9ec87aJust tableClass = DefaultTable 85f8fd4777d273836a1222b72f6761cb6fdf9ec87aJust else: 86f8fd4777d273836a1222b72f6761cb6fdf9ec87aJust tableClass = ttLib.getTableClass(tag) 87f8fd4777d273836a1222b72f6761cb6fdf9ec87aJust if tableClass is None: 88f8fd4777d273836a1222b72f6761cb6fdf9ec87aJust tableClass = DefaultTable 89bc5e1cb195c0bfa1c8e7507326d5a9ad05aecb4bBehdad Esfahbod if tag == 'loca' and tag in self.ttFont: 90d57c4346e5725bbfe0e1b13067b292c3faaaeb8ejvr # Special-case the 'loca' table as we need the 91e82b4d5658a7a38cf92b4b9392861257a2cfbb36jvr # original if the 'glyf' table isn't recompiled. 92ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.currentTable = self.ttFont[tag] 931670f7af0edf5af2447f9fb157febe8cfb44b629Just else: 94ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.currentTable = tableClass(tag) 95ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.ttFont[tag] = self.currentTable 96ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.contentStack.append([]) 97f8fd4777d273836a1222b72f6761cb6fdf9ec87aJust elif stackSize == 2: 98ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.contentStack.append([]) 99ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.root = (name, attrs, self.contentStack[-1]) 1007842e56b97ce677b83bdab09cda48bc2d89ac75aJust else: 1017842e56b97ce677b83bdab09cda48bc2d89ac75aJust list = [] 102ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.contentStack[-1].append((name, attrs, list)) 103ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.contentStack.append(list) 1047842e56b97ce677b83bdab09cda48bc2d89ac75aJust 1053ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod def _characterDataHandler(self, data): 106ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr if self.stackSize > 1: 107ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.contentStack[-1].append(data) 1087842e56b97ce677b83bdab09cda48bc2d89ac75aJust 1093ebfea491ea795217e0f9649c23ee81df769a250Behdad Esfahbod def _endElementHandler(self, name): 110ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr self.stackSize = self.stackSize - 1 111ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr del self.contentStack[-1] 112ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr if self.stackSize == 1: 1137842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.root = None 114ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr elif self.stackSize == 2: 1153a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod name, attrs, content = self.root 1163a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod self.currentTable.fromXML(name, attrs, content, self.ttFont) 1177842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.root = None 1187842e56b97ce677b83bdab09cda48bc2d89ac75aJust 1197842e56b97ce677b83bdab09cda48bc2d89ac75aJust 1207842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass ProgressPrinter: 1217842e56b97ce677b83bdab09cda48bc2d89ac75aJust 1227842e56b97ce677b83bdab09cda48bc2d89ac75aJust def __init__(self, title, maxval=100): 1233ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod print(title) 1247842e56b97ce677b83bdab09cda48bc2d89ac75aJust 1257842e56b97ce677b83bdab09cda48bc2d89ac75aJust def set(self, val, maxval=None): 1267842e56b97ce677b83bdab09cda48bc2d89ac75aJust pass 1277842e56b97ce677b83bdab09cda48bc2d89ac75aJust 1287842e56b97ce677b83bdab09cda48bc2d89ac75aJust def increment(self, val=1): 1297842e56b97ce677b83bdab09cda48bc2d89ac75aJust pass 1307842e56b97ce677b83bdab09cda48bc2d89ac75aJust 1316ab979cacaa9c15666a526e05c669b7f87bb6de9jvr def setLabel(self, text): 1323ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod print(text) 1337842e56b97ce677b83bdab09cda48bc2d89ac75aJust 134