psCharStrings.py revision 586345b7c1c0aa97b06f1597b67c3bb4c4e97be1
17842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""psCharStrings.py -- module implementing various kinds of CharStrings:
27842e56b97ce677b83bdab09cda48bc2d89ac75aJustCFF dictionary data and Type1/Type2 CharStrings.
37842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
47842e56b97ce677b83bdab09cda48bc2d89ac75aJust
57842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport types
67842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport struct
77842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport string
87842e56b97ce677b83bdab09cda48bc2d89ac75aJust
97842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10455af6592bffbd6f2fc9f56fbfe083022a8353d4jvrDEBUG = 0
11455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr
12455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr
137842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1OperandEncoding = [None] * 256
147842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1OperandEncoding[0:32] = (32) * ["do_operator"]
157842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1OperandEncoding[32:247] = (247 - 32) * ["read_byte"]
167842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1OperandEncoding[247:251] = (251 - 247) * ["read_smallInt1"]
177842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1OperandEncoding[251:255] = (255 - 251) * ["read_smallInt2"]
187842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1OperandEncoding[255] = "read_longInt"
197842e56b97ce677b83bdab09cda48bc2d89ac75aJustassert len(t1OperandEncoding) == 256
207842e56b97ce677b83bdab09cda48bc2d89ac75aJust
217842e56b97ce677b83bdab09cda48bc2d89ac75aJustt2OperandEncoding = t1OperandEncoding[:]
227842e56b97ce677b83bdab09cda48bc2d89ac75aJustt2OperandEncoding[28] = "read_shortInt"
237842e56b97ce677b83bdab09cda48bc2d89ac75aJust
247842e56b97ce677b83bdab09cda48bc2d89ac75aJustcffDictOperandEncoding = t2OperandEncoding[:]
257842e56b97ce677b83bdab09cda48bc2d89ac75aJustcffDictOperandEncoding[29] = "read_longInt"
267842e56b97ce677b83bdab09cda48bc2d89ac75aJustcffDictOperandEncoding[30] = "read_realNumber"
277842e56b97ce677b83bdab09cda48bc2d89ac75aJustcffDictOperandEncoding[255] = "reserved"
287842e56b97ce677b83bdab09cda48bc2d89ac75aJust
297842e56b97ce677b83bdab09cda48bc2d89ac75aJust
307842e56b97ce677b83bdab09cda48bc2d89ac75aJustrealNibbles = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		'.', 'E', 'E-', None, '-']
327842e56b97ce677b83bdab09cda48bc2d89ac75aJust
337842e56b97ce677b83bdab09cda48bc2d89ac75aJust
347842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass ByteCodeDecompilerBase:
357842e56b97ce677b83bdab09cda48bc2d89ac75aJust
367842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_byte(self, b0, data, index):
377842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return b0 - 139, index
387842e56b97ce677b83bdab09cda48bc2d89ac75aJust
397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_smallInt1(self, b0, data, index):
407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		b1 = ord(data[index])
417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return (b0-247)*256 + b1 + 108, index+1
427842e56b97ce677b83bdab09cda48bc2d89ac75aJust
437842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_smallInt2(self, b0, data, index):
447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		b1 = ord(data[index])
457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return -(b0-251)*256 - b1 - 108, index+1
467842e56b97ce677b83bdab09cda48bc2d89ac75aJust
477842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_shortInt(self, b0, data, index):
487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bin = data[index] + data[index+1]
497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value, = struct.unpack(">h", bin)
507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value, index+2
517842e56b97ce677b83bdab09cda48bc2d89ac75aJust
527842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_longInt(self, b0, data, index):
537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bin = data[index] + data[index+1] + data[index+2] + data[index+3]
547842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value, = struct.unpack(">l", bin)
557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value, index+4
567842e56b97ce677b83bdab09cda48bc2d89ac75aJust
577842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_realNumber(self, b0, data, index):
587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		number = ''
597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while 1:
607842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b = ord(data[index])
617842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
627842e56b97ce677b83bdab09cda48bc2d89ac75aJust			nibble0 = (b & 0xf0) >> 4
637842e56b97ce677b83bdab09cda48bc2d89ac75aJust			nibble1 = b & 0x0f
647842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if nibble0 == 0xf:
657842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break
667842e56b97ce677b83bdab09cda48bc2d89ac75aJust			number = number + realNibbles[nibble0]
677842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if nibble1 == 0xf:
687842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break
697842e56b97ce677b83bdab09cda48bc2d89ac75aJust			number = number + realNibbles[nibble1]
70455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		return float(number), index
717842e56b97ce677b83bdab09cda48bc2d89ac75aJust
727842e56b97ce677b83bdab09cda48bc2d89ac75aJust
73dbc2c173b35360386c907a3c70cb931ae4c3fac9jvrdef buildOperatorDict(operatorList):
74455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	oper = {}
75455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	opc = {}
767842e56b97ce677b83bdab09cda48bc2d89ac75aJust	for item in operatorList:
777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(item) == 2:
78455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			oper[item[0]] = item[1]
79455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		else:
80455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			oper[item[0]] = item[1:]
81455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		if type(item[0]) == types.TupleType:
82455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			opc[item[1]] = item[0]
837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
84455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			opc[item[1]] = (item[0],)
85455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	return oper, opc
867842e56b97ce677b83bdab09cda48bc2d89ac75aJust
877842e56b97ce677b83bdab09cda48bc2d89ac75aJust
887842e56b97ce677b83bdab09cda48bc2d89ac75aJustt2Operators = [
897842e56b97ce677b83bdab09cda48bc2d89ac75aJust#	opcode     name
907842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(1,        'hstem'),
917842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(3,        'vstem'),
927842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(4,        'vmoveto'),
937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(5,        'rlineto'),
947842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(6,        'hlineto'),
957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(7,        'vlineto'),
967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(8,        'rrcurveto'),
977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(10,       'callsubr'),
987842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(11,       'return'),
997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(14,       'endchar'),
1007842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(16,       'blend'),
1017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(18,       'hstemhm'),
1027842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(19,       'hintmask'),
1037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(20,       'cntrmask'),
1047842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(21,       'rmoveto'),
1057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(22,       'hmoveto'),
1067842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(23,       'vstemhm'),
1077842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(24,       'rcurveline'),
1087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(25,       'rlinecurve'),
1097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(26,       'vvcurveto'),
1107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(27,       'hhcurveto'),
1117842e56b97ce677b83bdab09cda48bc2d89ac75aJust#	(28,       'shortint'),  # not really an operator
1127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(29,       'callgsubr'),
1137842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(30,       'vhcurveto'),
1147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(31,       'hvcurveto'),
1157842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 3),  'and'),
1167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 4),  'or'),
1177842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 5),  'not'),
1187842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 8),  'store'),
1197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 9),  'abs'),
1207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 10), 'add'),
1217842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 11), 'sub'),
1227842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 12), 'div'),
1237842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 13), 'load'),
1247842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 14), 'neg'),
1257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 15), 'eq'),
1267842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 18), 'drop'),
1277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 20), 'put'),
1287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 21), 'get'),
1297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 22), 'ifelse'),
1307842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 23), 'random'),
1317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 24), 'mul'),
1327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 26), 'sqrt'),
1337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 27), 'dup'),
1347842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 28), 'exch'),
1357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 29), 'index'),
1367842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 30), 'roll'),
1377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 34), 'hflex'),
1387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 35), 'flex'),
1397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 36), 'hflex1'),
1407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 37), 'flex1'),
1417842e56b97ce677b83bdab09cda48bc2d89ac75aJust]
1427842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1437842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T2CharString(ByteCodeDecompilerBase):
1447842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = t2OperandEncoding
146455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	operators, opcodes = buildOperatorDict(t2Operators)
1477842e56b97ce677b83bdab09cda48bc2d89ac75aJust
148586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def __init__(self, bytecode=None, program=None, subrs=None, globalSubrs=None):
1497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if program is None:
1507842e56b97ce677b83bdab09cda48bc2d89ac75aJust			program = []
1517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.bytecode = bytecode
1527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.program = program
153586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.subrs = subrs
154586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.globalSubrs = globalSubrs
1557842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1567842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __repr__(self):
1577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is None:
1587842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return "<%s (source) at %x>" % (self.__class__.__name__, id(self))
1597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
1607842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return "<%s (bytecode) at %x>" % (self.__class__.__name__, id(self))
1617842e56b97ce677b83bdab09cda48bc2d89ac75aJust
162586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def decompile(self):
163586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		if not self.needsDecompilation():
164586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr			return
165586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		decompiler = SimpleT2Decompiler(self.subrs, self.globalSubrs)
166586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		decompiler.reset()
167586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		decompiler.execute(self)
168586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr
169455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	def compile(self):
170455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		if self.bytecode is not None:
171455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			return
172455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		bytecode = []
173455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		opcodes = self.opcodes
174455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		for token in self.program:
175455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			tp = type(token)
176455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			if tp == types.StringType:
177455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr				if opcodes.has_key(token):
178455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					bytecode.extend(map(chr, opcodes[token]))
179455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr				else:
180455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					bytecode.append(token)  # hint mask
181455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			elif tp == types.FloatType:
182455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr				# only in CFF
183455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr				raise NotImplementedError
184455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			elif tp == types.IntType:
185455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr				# XXX factor out, is largely OK for CFF dicts, too.
186455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr				if -107 <= token <= 107:
187455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					code = chr(token + 139)
188455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr				elif 108 <= token <= 1131:
189455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					token = token - 108
190455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					code = chr((token >> 8) + 247) + chr(token & 0xFF)
191455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr				elif -1131 <= token <= -108:
192455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					token = -token - 108
193455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					code = chr((token >> 8) + 251) + chr(token & 0xFF)
194455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr				elif -32768 <= token <= 32767:
195455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					# XXX T2/CFF-specific: doesn't exist in T1
196455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					code = chr(28) + struct.pack(">h", token)
197455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr				else:
198455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					# XXX T1/T2-specific: different opcode in CFF
199455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					code = chr(255) + struct.pack(">l", token)
200455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr				bytecode.append(code)
201455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			else:
202455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr				assert 0
203455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		bytecode = "".join(bytecode)
204455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		if DEBUG:
205455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			assert bytecode == self.__bytecode
206455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr
2077842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def needsDecompilation(self):
2087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.bytecode is not None
2097842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def setProgram(self, program):
2117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.program = program
212455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		if DEBUG:
213455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			self.__bytecode = self.bytecode
2147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.bytecode = None
2157842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getToken(self, index,
2177842e56b97ce677b83bdab09cda48bc2d89ac75aJust			len=len, ord=ord, getattr=getattr, type=type, StringType=types.StringType):
2187842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is not None:
2197842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if index >= len(self.bytecode):
2207842e56b97ce677b83bdab09cda48bc2d89ac75aJust				return None, 0, 0
2217842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b0 = ord(self.bytecode[index])
2227842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
2237842e56b97ce677b83bdab09cda48bc2d89ac75aJust			code = self.operandEncoding[b0]
2247842e56b97ce677b83bdab09cda48bc2d89ac75aJust			handler = getattr(self, code)
2257842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token, index = handler(b0, self.bytecode, index)
2267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
2277842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if index >= len(self.program):
2287842e56b97ce677b83bdab09cda48bc2d89ac75aJust				return None, 0, 0
2297842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token = self.program[index]
2307842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
2317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		isOperator = type(token) == StringType
2327842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return token, isOperator, index
2337842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2347842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getBytes(self, index, nBytes):
2357842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is not None:
2367842e56b97ce677b83bdab09cda48bc2d89ac75aJust			newIndex = index + nBytes
2377842e56b97ce677b83bdab09cda48bc2d89ac75aJust			bytes = self.bytecode[index:newIndex]
2387842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = newIndex
2397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
2407842e56b97ce677b83bdab09cda48bc2d89ac75aJust			bytes = self.program[index]
2417842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
2427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		assert len(bytes) == nBytes
2437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return bytes, index
2447842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def do_operator(self, b0, data, index):
2467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if b0 == 12:
2477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = (b0, ord(data[index]))
2487842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index+1
2497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
2507842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = b0
2517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		operator = self.operators[op]
2527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return operator, index
2537842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2547842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def toXML(self, xmlWriter):
255dab433233bd4024ede9ad27c6c61ea0072c2edafJust		from fontTools.misc.textTools import num2binary
2567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is not None:
2577842e56b97ce677b83bdab09cda48bc2d89ac75aJust			xmlWriter.dumphex(self.bytecode)
2587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
2597842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = 0
2607842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
2617842e56b97ce677b83bdab09cda48bc2d89ac75aJust			while 1:
2627842e56b97ce677b83bdab09cda48bc2d89ac75aJust				token, isOperator, index = self.getToken(index)
2637842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if token is None:
2647842e56b97ce677b83bdab09cda48bc2d89ac75aJust					break
2657842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if isOperator:
2667842e56b97ce677b83bdab09cda48bc2d89ac75aJust					args = map(str, args)
2677842e56b97ce677b83bdab09cda48bc2d89ac75aJust					if token in ('hintmask', 'cntrmask'):
2687842e56b97ce677b83bdab09cda48bc2d89ac75aJust						hintMask, isOperator, index = self.getToken(index)
2697842e56b97ce677b83bdab09cda48bc2d89ac75aJust						bits = []
2707842e56b97ce677b83bdab09cda48bc2d89ac75aJust						for byte in hintMask:
2717842e56b97ce677b83bdab09cda48bc2d89ac75aJust							bits.append(num2binary(ord(byte), 8))
272586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr						hintMask = string.join(bits, "")
2737842e56b97ce677b83bdab09cda48bc2d89ac75aJust						line = string.join(args + [token, hintMask], " ")
2747842e56b97ce677b83bdab09cda48bc2d89ac75aJust					else:
2757842e56b97ce677b83bdab09cda48bc2d89ac75aJust						line = string.join(args + [token], " ")
2767842e56b97ce677b83bdab09cda48bc2d89ac75aJust					xmlWriter.write(line)
2777842e56b97ce677b83bdab09cda48bc2d89ac75aJust					xmlWriter.newline()
2787842e56b97ce677b83bdab09cda48bc2d89ac75aJust					args = []
2797842e56b97ce677b83bdab09cda48bc2d89ac75aJust				else:
2807842e56b97ce677b83bdab09cda48bc2d89ac75aJust					args.append(token)
2817842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2827842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2837842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1Operators = [
2847842e56b97ce677b83bdab09cda48bc2d89ac75aJust#	opcode     name
2857842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(1,        'hstem'),
2867842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(3,        'vstem'),
2877842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(4,        'vmoveto'),
2887842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(5,        'rlineto'),
2897842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(6,        'hlineto'),
2907842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(7,        'vlineto'),
2917842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(8,        'rrcurveto'),
2927842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(9,        'closepath'),
2937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(10,       'callsubr'),
2947842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(11,       'return'),
2957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(13,       'hsbw'),
2967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(14,       'endchar'),
2977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(21,       'rmoveto'),
2987842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(22,       'hmoveto'),
2997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(30,       'vhcurveto'),
3007842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(31,       'hvcurveto'),
3017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 0),  'dotsection'),
3027842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 1),  'vstem3'),
3037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 2),  'hstem3'),
3047842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 6),  'seac'),
3057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 7),  'sbw'),
3067842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 12), 'div'),
3077842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 16), 'callothersubr'),
3087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 17), 'pop'),
3097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 33), 'setcurrentpoint'),
3107842e56b97ce677b83bdab09cda48bc2d89ac75aJust]
3117842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3127842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T1CharString(T2CharString):
3137842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = t1OperandEncoding
315455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	operators, opcodes = buildOperatorDict(t1Operators)
3167842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3177842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self):
318b68a700595ff730c29d3d4b7abf92ee287678745Just		if self.program is not None:
3197842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
3207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		program = []
3217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
3227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while 1:
3237842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token, isOperator, index = self.getToken(index)
3247842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if token is None:
3257842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break
3267842e56b97ce677b83bdab09cda48bc2d89ac75aJust			program.append(token)
3277842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.setProgram(program)
3287842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3297842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3307842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass SimpleT2Decompiler:
3317842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __init__(self, localSubrs, globalSubrs):
3337842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.localSubrs = localSubrs
3347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.localBias = calcSubrBias(localSubrs)
3357842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.globalSubrs = globalSubrs
3367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.globalBias = calcSubrBias(globalSubrs)
3377842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.reset()
3387842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
3407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.callingStack = []
3417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.operandStack = []
3427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = 0
3437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintMaskBytes = 0
3447842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def execute(self, charString):
3467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.callingStack.append(charString)
3477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		needsDecompilation = charString.needsDecompilation()
3487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if needsDecompilation:
3497842e56b97ce677b83bdab09cda48bc2d89ac75aJust			program = []
3507842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pushToProgram = program.append
3517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
3527842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pushToProgram = lambda x: None
3537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pushToStack = self.operandStack.append
3547842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
3557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while 1:
3567842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token, isOperator, index = charString.getToken(index)
3577842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if token is None:
3587842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break  # we're done!
3597842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pushToProgram(token)
3607842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if isOperator:
3617842e56b97ce677b83bdab09cda48bc2d89ac75aJust				handlerName = "op_" + token
3627842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if hasattr(self, handlerName):
3637842e56b97ce677b83bdab09cda48bc2d89ac75aJust					handler = getattr(self, handlerName)
3647842e56b97ce677b83bdab09cda48bc2d89ac75aJust					rv = handler(index)
3657842e56b97ce677b83bdab09cda48bc2d89ac75aJust					if rv:
3667842e56b97ce677b83bdab09cda48bc2d89ac75aJust						hintMaskBytes, index = rv
3677842e56b97ce677b83bdab09cda48bc2d89ac75aJust						pushToProgram(hintMaskBytes)
3687842e56b97ce677b83bdab09cda48bc2d89ac75aJust				else:
3697842e56b97ce677b83bdab09cda48bc2d89ac75aJust					self.popall()
3707842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
3717842e56b97ce677b83bdab09cda48bc2d89ac75aJust				pushToStack(token)
3727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if needsDecompilation:
3737842e56b97ce677b83bdab09cda48bc2d89ac75aJust			charString.setProgram(program)
3747842e56b97ce677b83bdab09cda48bc2d89ac75aJust			assert program[-1] in ("endchar", "return", "callsubr", "callgsubr", "seac")
3757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.callingStack[-1]
3767842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3777842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def pop(self):
3787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value = self.operandStack[-1]
3797842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.operandStack[-1]
3807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value
3817842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3827842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popall(self):
3837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack = self.operandStack[:]
3847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.operandStack[:] = []
3857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return stack
3867842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3877842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def push(self, value):
3887842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.operandStack.append(value)
3897842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3907842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_return(self, index):
3917842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.operandStack:
3927842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pass
3937842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3947842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
3957842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pass
3967842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callsubr(self, index):
3987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
3997842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.localSubrs[subrIndex+self.localBias]
4007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
4017842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4027842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callgsubr(self, index):
4037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
4047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.globalSubrs[subrIndex+self.globalBias]
4057842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
4067842e56b97ce677b83bdab09cda48bc2d89ac75aJust
407586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def op_hstem(self, index):
408586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.countHints()
409586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def op_vstem(self, index):
410586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.countHints()
4117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hstemhm(self, index):
4127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.countHints()
413586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def op_vstemhm(self, index):
414586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.countHints()
4157842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hintmask(self, index):
4177842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if not self.hintMaskBytes:
4187842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.countHints()
4197842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.hintMaskBytes = (self.hintCount + 7) / 8
4207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		hintMaskBytes, index = self.callingStack[-1].getBytes(index, self.hintMaskBytes)
4217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return hintMaskBytes, index
4227842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4237842e56b97ce677b83bdab09cda48bc2d89ac75aJust	op_cntrmask = op_hintmask
4247842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def countHints(self):
4267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
4277842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = self.hintCount + len(args) / 2
4287842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4297842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4307842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T2OutlineExtractor(SimpleT2Decompiler):
4317842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __init__(self, localSubrs, globalSubrs, nominalWidthX, defaultWidthX):
4337842e56b97ce677b83bdab09cda48bc2d89ac75aJust		SimpleT2Decompiler.__init__(self, localSubrs, globalSubrs)
4347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.nominalWidthX = nominalWidthX
4357842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.defaultWidthX = defaultWidthX
4367842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
4387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		import Numeric
4397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		SimpleT2Decompiler.reset(self)
4407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hints = []
4417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.gotWidth = 0
4427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = 0
4437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.currentPoint = Numeric.array((0, 0), Numeric.Int16)
4447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.contours = []
4457842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4467842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getContours(self):
4477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.contours
4487842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4497842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def newPath(self):
4507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.contours.append([[], [], 0])
4517842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4527842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def closePath(self):
4537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.contours and self.contours[-1][2] == 0:
4547842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.contours[-1][2] = 1
4557842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4567842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def appendPoint(self, point, isPrimary):
4577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		import Numeric
4587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		point = self.currentPoint + Numeric.array(point, Numeric.Int16)
459aa00a279aee4fb40429fbcf874f61d26a9978973jvr		if not self.contours or self.contours[-1][2]:
460aa00a279aee4fb40429fbcf874f61d26a9978973jvr			# The subpath doesn't start with a moveto. Not sure whether
461239498a49628ea09ee3ac8ead586022b775237f1jvr			# this is legal, but apparently it usually works.
462239498a49628ea09ee3ac8ead586022b775237f1jvr			self.newPath()
463aa00a279aee4fb40429fbcf874f61d26a9978973jvr			self.appendPoint((0, 0), 1)
4647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.currentPoint = point
4657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		points, flags, isClosed = self.contours[-1]
4667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		points.append(point)
4677842e56b97ce677b83bdab09cda48bc2d89ac75aJust		flags.append(isPrimary)
4687842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4697842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popallWidth(self, evenOdd=0):
4707842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
4717842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if not self.gotWidth:
4727842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if evenOdd ^ (len(args) % 2):
4737842e56b97ce677b83bdab09cda48bc2d89ac75aJust				self.width = self.nominalWidthX + args[0]
4747842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = args[1:]
4757842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
4767842e56b97ce677b83bdab09cda48bc2d89ac75aJust				self.width = self.defaultWidthX
4777842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.gotWidth = 1
4787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
4797842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4807842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def countHints(self):
4817842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popallWidth()
4827842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = self.hintCount + len(args) / 2
4837842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4847842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
4857842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# hint operators
4867842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
487586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_hstem(self, index):
488586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
489586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_vstem(self, index):
490586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
491586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_hstemhm(self, index):
492586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
493586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_vstemhm(self, index):
494586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
4957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#def op_hintmask(self, index):
4967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#	self.countHints()
4977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#def op_cntrmask(self, index):
4987842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#	self.countHints()
4997842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5007842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
5017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, moveto
5027842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
5037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rmoveto(self, index):
5047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
5057842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.newPath()
5067842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.appendPoint(self.popallWidth(), 1)
5077842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hmoveto(self, index):
5087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
5097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.newPath()
5107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.appendPoint((self.popallWidth(1)[0], 0), 1)
5117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vmoveto(self, index):
5127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
5137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.newPath()
5147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.appendPoint((0, self.popallWidth(1)[0]), 1)
5157842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
5167842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
5177842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5187842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
5197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, lines
5207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
5217842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rlineto(self, index):
5227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
5237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 2):
5247842e56b97ce677b83bdab09cda48bc2d89ac75aJust			point = args[i:i+2]
5257842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.appendPoint(point, 1)
5267842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hlineto(self, index):
5287842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.alternatingLineto(1)
5297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vlineto(self, index):
5307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.alternatingLineto(0)
5317842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
5337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, curves
5347842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
5357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rrcurveto(self, index):
5367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya dxb dyb dxc dyc}+ rrcurveto"""
5377842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
5387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 6):
5397842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxa, dya, dxb, dyb, dxc, dyc, = args[i:i+6]
5407842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.rrcurveto((dxa, dya), (dxb, dyb), (dxc, dyc))
5417842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rcurveline(self, index):
5437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya dxb dyb dxc dyc}+ dxd dyd rcurveline"""
5447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
5457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args)-2, 6):
5467842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxb, dyb, dxc, dyc, dxd, dyd = args[i:i+6]
5477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.rrcurveto((dxb, dyb), (dxc, dyc), (dxd, dyd))
5487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.appendPoint(args[-2:], 1)
5497842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5507842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rlinecurve(self, index):
5517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya}+ dxb dyb dxc dyc dxd dyd rlinecurve"""
5527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
5537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lineArgs = args[:-6]
5547842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(lineArgs), 2):
5557842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.appendPoint(lineArgs[i:i+2], 1)
5567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dxb, dyb, dxc, dyc, dxd, dyd = args[-6:]
5577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.rrcurveto((dxb, dyb), (dxc, dyc), (dxd, dyd))
5587842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5597842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vvcurveto(self, index):
5607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"dx1? {dya dxb dyb dyc}+ vvcurveto"
5617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
5627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) % 2:
5637842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = args[0]
5647842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = args[1:]
5657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
5667842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = 0
5677842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 4):
5687842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dya, dxb, dyb, dyc = args[i:i+4]
5697842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.rrcurveto((dx1, dya), (dxb, dyb), (0, dyc))
5707842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = 0
5717842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5727842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hhcurveto(self, index):
5737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dy1? {dxa dxb dyb dxc}+ hhcurveto"""
5747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
5757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) % 2:
5767842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = args[0]
5777842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = args[1:]
5787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
5797842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = 0
5807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 4):
5817842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxa, dxb, dyb, dxc = args[i:i+4]
5827842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.rrcurveto((dxa, dy1), (dxb, dyb), (dxc, 0))
5837842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = 0
5847842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5857842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vhcurveto(self, index):
5867842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? vhcurveto (30)
5877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		{dya dxb dyb dxc dxd dxe dye dyf}+ dxf? vhcurveto
5887842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""
5897842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
5907842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while args:
5917842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = self.vcurveto(args)
5927842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if args:
5937842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = self.hcurveto(args)
5947842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hvcurveto(self, index):
5967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf?
5977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		{dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?
5987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""
5997842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
6007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while args:
6017842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = self.hcurveto(args)
6027842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if args:
6037842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = self.vcurveto(args)
6047842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6067842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, flex
6077842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hflex(self, index):
6097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_flex(self, index):
6117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hflex1(self, index):
6137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_flex1(self, index):
6157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6167842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6177842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6187842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# MultipleMaster. Well...
6197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_blend(self, index):
6217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6227842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6237842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# misc
6247842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_and(self, index):
6257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6267842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_or(self, index):
6277842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_not(self, index):
6297842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6307842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_store(self, index):
6317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_abs(self, index):
6337842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6347842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_add(self, index):
6357842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6367842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sub(self, index):
6377842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_div(self, index):
6397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		num2 = self.pop()
6407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		num1 = self.pop()
6417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		d1 = num1/num2
6427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		d2 = float(num1)/num2
6437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if d1 == d2:
6447842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(d1)
6457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
6467842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(d2)
6477842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_load(self, index):
6487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6497842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_neg(self, index):
6507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6517842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_eq(self, index):
6527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6537842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_drop(self, index):
6547842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6557842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_put(self, index):
6567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6577842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_get(self, index):
6587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6597842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_ifelse(self, index):
6607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6617842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_random(self, index):
6627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6637842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_mul(self, index):
6647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6657842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sqrt(self, index):
6667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6677842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_dup(self, index):
6687842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6697842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_exch(self, index):
6707842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6717842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_index(self, index):
6727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6737842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_roll(self, index):
6747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
6757842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6767842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6777842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# miscelaneous helpers
6787842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6797842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def alternatingLineto(self, isHorizontal):
6807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
6817842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for arg in args:
6827842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if isHorizontal:
6837842e56b97ce677b83bdab09cda48bc2d89ac75aJust				point = (arg, 0)
6847842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
6857842e56b97ce677b83bdab09cda48bc2d89ac75aJust				point = (0, arg)
6867842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.appendPoint(point, 1)
6877842e56b97ce677b83bdab09cda48bc2d89ac75aJust			isHorizontal = not isHorizontal
6887842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6897842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def rrcurveto(self, p1, p2, p3):
6907842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.appendPoint(p1, 0)
6917842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.appendPoint(p2, 0)
6927842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.appendPoint(p3, 1)
6937842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6947842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def vcurveto(self, args):
6957842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dya, dxb, dyb, dxc = args[:4]
6967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = args[4:]
6977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) == 1:
6987842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dyc = args[0]
6997842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
7007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
7017842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dyc = 0
7027842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.rrcurveto((0, dya), (dxb, dyb), (dxc, dyc))
7037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
7047842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def hcurveto(self, args):
7067842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dxa, dxb, dyb, dyc = args[:4]
7077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = args[4:]
7087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) == 1:
7097842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxc = args[0]
7107842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
7117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
7127842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxc = 0
7137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.rrcurveto((dxa, 0), (dxb, dyb), (dxc, dyc))
7147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
7157842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7167842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7177842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T1OutlineExtractor(T2OutlineExtractor):
7187842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __init__(self, subrs):
7207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.subrs = subrs
7217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.reset()
7227842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7237842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
7247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.flexing = 0
7257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = 0
7267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.sbx = 0
7277842e56b97ce677b83bdab09cda48bc2d89ac75aJust		T2OutlineExtractor.reset(self)
7287842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popallWidth(self, evenOdd=0):
7307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.popall()
7317842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def exch(self):
7337842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack = self.operandStack
7347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack[-1], stack[-2] = stack[-2], stack[-1]
7357842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7367842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors
7387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rmoveto(self, index):
7407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
7417842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
7427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.newPath()
7437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.appendPoint(self.popall(), 1)
7447842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hmoveto(self, index):
7457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
7467842e56b97ce677b83bdab09cda48bc2d89ac75aJust			# We must add a parameter to the stack if we are flexing
7477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(0)
7487842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
7497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.newPath()
7507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.appendPoint((self.popall()[0], 0), 1)
7517842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vmoveto(self, index):
7527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
7537842e56b97ce677b83bdab09cda48bc2d89ac75aJust			# We must add a parameter to the stack if we are flexing
7547842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(0)
7557842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.exch()
7567842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
7577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.newPath()
7587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.appendPoint((0, self.popall()[0]), 1)
7597842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_closepath(self, index):
7607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
7617842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_setcurrentpoint(self, index):
7627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7637842e56b97ce677b83bdab09cda48bc2d89ac75aJust		x, y = args
7647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.currentPoint[0] = x
7657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.currentPoint[1] = y
7667842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7677842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
7687842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
7697842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7707842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hsbw(self, index):
7717842e56b97ce677b83bdab09cda48bc2d89ac75aJust		sbx, wx = self.popall()
7727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = wx
7737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.sbx = sbx
7747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.currentPoint[0] = sbx
7757842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sbw(self, index):
7767842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
7777842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7787842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7797842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callsubr(self, index):
7807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
7817842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.subrs[subrIndex]
7827842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
7837842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callothersubr(self, index):
7847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
7857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		nArgs = self.pop()
7867842e56b97ce677b83bdab09cda48bc2d89ac75aJust		#print nArgs, subrIndex, "callothersubr"
7877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if subrIndex == 0 and nArgs == 3:
7887842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.doFlex()
7897842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.flexing = 0
7907842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif subrIndex == 1 and nArgs == 0:
7917842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.flexing = 1
7927842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# ignore...
7937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_pop(self, index):
7947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pass  # ignore...
7957842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def doFlex(self):
7977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		finaly = self.pop()
7987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		finalx = self.pop()
7997842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.pop()	# flex height is unused
8007842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p3y = self.pop()
8027842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p3x = self.pop()
8037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp4y = self.pop()
8047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp4x = self.pop()
8057842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp3y = self.pop()
8067842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp3x = self.pop()
8077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p2y = self.pop()
8087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p2x = self.pop()
8097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp2y = self.pop()
8107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp2x = self.pop()
8117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp1y = self.pop()
8127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp1x = self.pop()
8137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		rpy = self.pop()
8147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		rpx = self.pop()
8157842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8167842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# call rrcurveto
8177842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp1x+rpx)
8187842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp1y+rpy)
8197842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp2x)
8207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp2y)
8217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p2x)
8227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p2y)
8237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.op_rrcurveto(None)
8247842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# call rrcurveto
8267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp3x)
8277842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp3y)
8287842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp4x)
8297842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp4y)
8307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p3x)
8317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p3y)
8327842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.op_rrcurveto(None)
8337842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# Push back final coords so subr 0 can find them
8357842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(finalx)
8367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(finaly)
8377842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_dotsection(self, index):
8397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
8407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hstem3(self, index):
8417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
8427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_seac(self, index):
8437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"asb adx ady bchar achar seac"
8447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		asb, adx, ady, bchar, achar = self.popall()  # XXX
8457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.contours.append([(asb, adx, ady, bchar, achar), None, -1])
8467842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vstem3(self, index):
8477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
8487842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8497842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8507842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass DictDecompiler(ByteCodeDecompilerBase):
8517842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8527842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = cffDictOperandEncoding
8537842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8547842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __init__(self, strings):
8557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.stack = []
8567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.strings = strings
8577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.dict = {}
8587842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8597842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getDict(self):
8607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		assert len(self.stack) == 0, "non-empty stack"
8617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.dict
8627842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8637842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self, data):
8647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
8657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lenData = len(data)
8667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		push = self.stack.append
8677842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while index < lenData:
8687842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b0 = ord(data[index])
8697842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
8707842e56b97ce677b83bdab09cda48bc2d89ac75aJust			code = self.operandEncoding[b0]
8717842e56b97ce677b83bdab09cda48bc2d89ac75aJust			handler = getattr(self, code)
8727842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value, index = handler(b0, data, index)
8737842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if value is not None:
8747842e56b97ce677b83bdab09cda48bc2d89ac75aJust				push(value)
8757842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8767842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def pop(self):
8777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value = self.stack[-1]
8787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.stack[-1]
8797842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value
8807842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8817842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popall(self):
8827842e56b97ce677b83bdab09cda48bc2d89ac75aJust		all = self.stack[:]
8837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.stack[:]
8847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return all
8857842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8867842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def do_operator(self, b0, data, index):
8877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if b0 == 12:
8887842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = (b0, ord(data[index]))
8897842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index+1
8907842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
8917842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = b0
8927842e56b97ce677b83bdab09cda48bc2d89ac75aJust		operator, argType = self.operators[op]
8937842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.handle_operator(operator, argType)
8947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return None, index
8957842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def handle_operator(self, operator, argType):
8977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if type(argType) == type(()):
8987842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = ()
899bf2f402913a2706dfa92190e60cba7acbf01c9d7jvr			for i in range(len(argType)-1, -1, -1):
900bf2f402913a2706dfa92190e60cba7acbf01c9d7jvr				arg = argType[i]
9017842e56b97ce677b83bdab09cda48bc2d89ac75aJust				arghandler = getattr(self, "arg_" + arg)
9027842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value = (arghandler(operator),) + value
9037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
9047842e56b97ce677b83bdab09cda48bc2d89ac75aJust			arghandler = getattr(self, "arg_" + argType)
9057842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = arghandler(operator)
9067842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.dict[operator] = value
9077842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_number(self, name):
9097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.pop()
9107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_SID(self, name):
9117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.strings[self.pop()]
9127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_array(self, name):
9137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.popall()
914dc18128aa9b3f6b98a623c294ac615195159025ejvr	def arg_delta(self, name):
915dc18128aa9b3f6b98a623c294ac615195159025ejvr		out = []
916dc18128aa9b3f6b98a623c294ac615195159025ejvr		current = 0
917dc18128aa9b3f6b98a623c294ac615195159025ejvr		for v in self.popall():
9186f03a58f59fb20662602e3d4bb153d7db2f778d3jvr			current = current + v
919dc18128aa9b3f6b98a623c294ac615195159025ejvr			out.append(current)
920dc18128aa9b3f6b98a623c294ac615195159025ejvr		return out
9217842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9227842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9237842e56b97ce677b83bdab09cda48bc2d89ac75aJustdef calcSubrBias(subrs):
9247842e56b97ce677b83bdab09cda48bc2d89ac75aJust	nSubrs = len(subrs)
9257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	if nSubrs < 1240:
9267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 107
9277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	elif nSubrs < 33900:
9287842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 1131
9297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	else:
9307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 32768
9317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	return bias
9327842e56b97ce677b83bdab09cda48bc2d89ac75aJust
933