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