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