psCharStrings.py revision 382df6c42a7a6aecb690e07c6338e19f038f0543
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, '-']
32f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrrealNibblesDict = {}
33f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrfor _i in range(len(realNibbles)):
34f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	realNibblesDict[realNibbles[_i]] = _i
357842e56b97ce677b83bdab09cda48bc2d89ac75aJust
367842e56b97ce677b83bdab09cda48bc2d89ac75aJust
37f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrclass ByteCodeBase:
387842e56b97ce677b83bdab09cda48bc2d89ac75aJust
397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_byte(self, b0, data, index):
407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return b0 - 139, index
417842e56b97ce677b83bdab09cda48bc2d89ac75aJust
427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_smallInt1(self, b0, data, index):
437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		b1 = ord(data[index])
447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return (b0-247)*256 + b1 + 108, index+1
457842e56b97ce677b83bdab09cda48bc2d89ac75aJust
467842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_smallInt2(self, b0, data, index):
477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		b1 = ord(data[index])
487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return -(b0-251)*256 - b1 - 108, index+1
497842e56b97ce677b83bdab09cda48bc2d89ac75aJust
507842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_shortInt(self, b0, data, index):
517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bin = data[index] + data[index+1]
527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value, = struct.unpack(">h", bin)
537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value, index+2
547842e56b97ce677b83bdab09cda48bc2d89ac75aJust
557842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_longInt(self, b0, data, index):
567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bin = data[index] + data[index+1] + data[index+2] + data[index+3]
577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value, = struct.unpack(">l", bin)
587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value, index+4
597842e56b97ce677b83bdab09cda48bc2d89ac75aJust
607842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_realNumber(self, b0, data, index):
617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		number = ''
627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while 1:
637842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b = ord(data[index])
647842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
657842e56b97ce677b83bdab09cda48bc2d89ac75aJust			nibble0 = (b & 0xf0) >> 4
667842e56b97ce677b83bdab09cda48bc2d89ac75aJust			nibble1 = b & 0x0f
677842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if nibble0 == 0xf:
687842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break
697842e56b97ce677b83bdab09cda48bc2d89ac75aJust			number = number + realNibbles[nibble0]
707842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if nibble1 == 0xf:
717842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break
727842e56b97ce677b83bdab09cda48bc2d89ac75aJust			number = number + realNibbles[nibble1]
73455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		return float(number), index
747842e56b97ce677b83bdab09cda48bc2d89ac75aJust
757842e56b97ce677b83bdab09cda48bc2d89ac75aJust
76dbc2c173b35360386c907a3c70cb931ae4c3fac9jvrdef buildOperatorDict(operatorList):
77455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	oper = {}
78455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	opc = {}
797842e56b97ce677b83bdab09cda48bc2d89ac75aJust	for item in operatorList:
807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(item) == 2:
81455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			oper[item[0]] = item[1]
82455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		else:
83455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			oper[item[0]] = item[1:]
84455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		if type(item[0]) == types.TupleType:
85455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			opc[item[1]] = item[0]
867842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
87455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			opc[item[1]] = (item[0],)
88455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	return oper, opc
897842e56b97ce677b83bdab09cda48bc2d89ac75aJust
907842e56b97ce677b83bdab09cda48bc2d89ac75aJust
917842e56b97ce677b83bdab09cda48bc2d89ac75aJustt2Operators = [
927842e56b97ce677b83bdab09cda48bc2d89ac75aJust#	opcode     name
937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(1,        'hstem'),
947842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(3,        'vstem'),
957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(4,        'vmoveto'),
967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(5,        'rlineto'),
977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(6,        'hlineto'),
987842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(7,        'vlineto'),
997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(8,        'rrcurveto'),
1007842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(10,       'callsubr'),
1017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(11,       'return'),
1027842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(14,       'endchar'),
1037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(16,       'blend'),
1047842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(18,       'hstemhm'),
1057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(19,       'hintmask'),
1067842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(20,       'cntrmask'),
1077842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(21,       'rmoveto'),
1087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(22,       'hmoveto'),
1097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(23,       'vstemhm'),
1107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(24,       'rcurveline'),
1117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(25,       'rlinecurve'),
1127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(26,       'vvcurveto'),
1137842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(27,       'hhcurveto'),
1147842e56b97ce677b83bdab09cda48bc2d89ac75aJust#	(28,       'shortint'),  # not really an operator
1157842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(29,       'callgsubr'),
1167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(30,       'vhcurveto'),
1177842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(31,       'hvcurveto'),
1187842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 3),  'and'),
1197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 4),  'or'),
1207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 5),  'not'),
1217842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 8),  'store'),
1227842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 9),  'abs'),
1237842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 10), 'add'),
1247842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 11), 'sub'),
1257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 12), 'div'),
1267842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 13), 'load'),
1277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 14), 'neg'),
1287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 15), 'eq'),
1297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 18), 'drop'),
1307842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 20), 'put'),
1317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 21), 'get'),
1327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 22), 'ifelse'),
1337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 23), 'random'),
1347842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 24), 'mul'),
1357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 26), 'sqrt'),
1367842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 27), 'dup'),
1377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 28), 'exch'),
1387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 29), 'index'),
1397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 30), 'roll'),
1407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 34), 'hflex'),
1417842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 35), 'flex'),
1427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 36), 'hflex1'),
1437842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 37), 'flex1'),
1447842e56b97ce677b83bdab09cda48bc2d89ac75aJust]
1457842e56b97ce677b83bdab09cda48bc2d89ac75aJust
146f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
147f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrdef getIntEncoder(format):
148f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	fourByteOp = chr(255)
149f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	isT1 = 0
150f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	if format == "cff":
151f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		fourByteOp = chr(29)
152f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	elif format == "t1":
153f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		isT1 = 1
154f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	else:
155f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		assert format == "t2"
156f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
157f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	def encodeInt(value, fourByteOp=fourByteOp, isT1=isT1,
158f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			chr=chr, pack=struct.pack, unpack=struct.unpack):
159f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		if -107 <= value <= 107:
160f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = chr(value + 139)
161f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		elif 108 <= value <= 1131:
162f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			value = value - 108
163f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = chr((value >> 8) + 247) + chr(value & 0xFF)
164f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		elif -1131 <= value <= -108:
165f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			value = -value - 108
166f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = chr((value >> 8) + 251) + chr(value & 0xFF)
167f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		elif not isT1 and -32768 <= value <= 32767:
168f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = chr(28) + pack(">h", value)
169f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		else:
170f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = fourByteOp + pack(">l", value)
171f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		return code
172f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
173f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	return encodeInt
174f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
175f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
176f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrencodeIntCFF = getIntEncoder("cff")
177f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrencodeIntT1 = getIntEncoder("t1")
178f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrencodeIntT2 = getIntEncoder("t2")
179f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
180f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrdef encodeFloat(f):
181f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	s = str(f).upper()
182f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	if s[:2] == "0.":
183f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		s = s[1:]
184f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	elif s[:3] == "-0.":
185f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		s = "-" + s[2:]
186f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	nibbles = []
187f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	while s:
188f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		c = s[0]
189f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		s = s[1:]
190f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		if c == "E" and s[:1] == "-":
191f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			s = s[1:]
192f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			c = "E-"
193f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		nibbles.append(realNibblesDict[c])
194f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	nibbles.append(0xf)
195f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	if len(nibbles) % 2:
196f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		nibbles.append(0xf)
197f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	d = chr(30)
198f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	for i in range(0, len(nibbles), 2):
199f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		d = d + chr(nibbles[i] << 4 | nibbles[i+1])
200f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	return d
201f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
202f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
2034e5af60930726d06a58a30bae45bb27ae50aea77jvrclass CharStringCompileError(Exception): pass
2044e5af60930726d06a58a30bae45bb27ae50aea77jvr
2054e5af60930726d06a58a30bae45bb27ae50aea77jvr
206f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrclass T2CharString(ByteCodeBase):
2077842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = t2OperandEncoding
209455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	operators, opcodes = buildOperatorDict(t2Operators)
2107842e56b97ce677b83bdab09cda48bc2d89ac75aJust
211489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, bytecode=None, program=None, private=None, globalSubrs=None):
2127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if program is None:
2137842e56b97ce677b83bdab09cda48bc2d89ac75aJust			program = []
2147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.bytecode = bytecode
2157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.program = program
216489d76a340845361def6af9ab7d9152f8e66f417jvr		self.private = private
217586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.globalSubrs = globalSubrs
2187842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __repr__(self):
2207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is None:
2217842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return "<%s (source) at %x>" % (self.__class__.__name__, id(self))
2227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
2237842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return "<%s (bytecode) at %x>" % (self.__class__.__name__, id(self))
2247842e56b97ce677b83bdab09cda48bc2d89ac75aJust
225586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def decompile(self):
226586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		if not self.needsDecompilation():
227586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr			return
228489d76a340845361def6af9ab7d9152f8e66f417jvr		subrs = getattr(self.private, "Subrs", [])
229489d76a340845361def6af9ab7d9152f8e66f417jvr		decompiler = SimpleT2Decompiler(subrs, self.globalSubrs)
230586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		decompiler.execute(self)
231586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr
232489d76a340845361def6af9ab7d9152f8e66f417jvr	def draw(self, pen):
233489d76a340845361def6af9ab7d9152f8e66f417jvr		subrs = getattr(self.private, "Subrs", [])
234489d76a340845361def6af9ab7d9152f8e66f417jvr		extractor = T2OutlineExtractor(pen, subrs, self.globalSubrs,
235489d76a340845361def6af9ab7d9152f8e66f417jvr				self.private.nominalWidthX, self.private.defaultWidthX)
236489d76a340845361def6af9ab7d9152f8e66f417jvr		extractor.execute(self)
237489d76a340845361def6af9ab7d9152f8e66f417jvr		self.width = extractor.width
238489d76a340845361def6af9ab7d9152f8e66f417jvr
239455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	def compile(self):
240455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		if self.bytecode is not None:
241455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			return
2429920ad5286b6e61d67f07f908107d65f7fa817acjvr		assert self.program, "illegal CharString: decompiled to empty program"
2439920ad5286b6e61d67f07f908107d65f7fa817acjvr		assert self.program[-1] in ("endchar", "return", "callsubr", "callgsubr",
2449920ad5286b6e61d67f07f908107d65f7fa817acjvr				"seac"), "illegal CharString"
245455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		bytecode = []
246455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		opcodes = self.opcodes
2474e5af60930726d06a58a30bae45bb27ae50aea77jvr		program = self.program
2484e5af60930726d06a58a30bae45bb27ae50aea77jvr		i = 0
2494e5af60930726d06a58a30bae45bb27ae50aea77jvr		end = len(program)
2504e5af60930726d06a58a30bae45bb27ae50aea77jvr		while i < end:
2514e5af60930726d06a58a30bae45bb27ae50aea77jvr			token = program[i]
2524e5af60930726d06a58a30bae45bb27ae50aea77jvr			i = i + 1
253455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			tp = type(token)
254455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			if tp == types.StringType:
2554e5af60930726d06a58a30bae45bb27ae50aea77jvr				try:
256455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					bytecode.extend(map(chr, opcodes[token]))
2574e5af60930726d06a58a30bae45bb27ae50aea77jvr				except KeyError:
2584e5af60930726d06a58a30bae45bb27ae50aea77jvr					raise CharStringCompileError, "illegal operator: %s" % token
2594e5af60930726d06a58a30bae45bb27ae50aea77jvr				if token in ('hintmask', 'cntrmask'):
2604e5af60930726d06a58a30bae45bb27ae50aea77jvr					bytecode.append(program[i])  # hint mask
2614e5af60930726d06a58a30bae45bb27ae50aea77jvr					i = i + 1
262455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			elif tp == types.IntType:
263f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr				bytecode.append(encodeIntT2(token))
264455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			else:
265f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr				assert 0, "unsupported type: %s" % tp
2664e5af60930726d06a58a30bae45bb27ae50aea77jvr		try:
2674e5af60930726d06a58a30bae45bb27ae50aea77jvr			bytecode = "".join(bytecode)
2684e5af60930726d06a58a30bae45bb27ae50aea77jvr		except TypeError:
2694e5af60930726d06a58a30bae45bb27ae50aea77jvr			print bytecode
2704e5af60930726d06a58a30bae45bb27ae50aea77jvr			raise
271f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		self.setBytecode(bytecode)
272f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
2737842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def needsDecompilation(self):
2747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.bytecode is not None
2757842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2767842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def setProgram(self, program):
2777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.program = program
2787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.bytecode = None
2797842e56b97ce677b83bdab09cda48bc2d89ac75aJust
280f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	def setBytecode(self, bytecode):
281f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		self.bytecode = bytecode
282f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		self.program = None
283f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
2847842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getToken(self, index,
2857842e56b97ce677b83bdab09cda48bc2d89ac75aJust			len=len, ord=ord, getattr=getattr, type=type, StringType=types.StringType):
2867842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is not None:
2877842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if index >= len(self.bytecode):
2887842e56b97ce677b83bdab09cda48bc2d89ac75aJust				return None, 0, 0
2897842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b0 = ord(self.bytecode[index])
2907842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
2917842e56b97ce677b83bdab09cda48bc2d89ac75aJust			code = self.operandEncoding[b0]
2927842e56b97ce677b83bdab09cda48bc2d89ac75aJust			handler = getattr(self, code)
2937842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token, index = handler(b0, self.bytecode, index)
2947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
2957842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if index >= len(self.program):
2967842e56b97ce677b83bdab09cda48bc2d89ac75aJust				return None, 0, 0
2977842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token = self.program[index]
2987842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
2997842e56b97ce677b83bdab09cda48bc2d89ac75aJust		isOperator = type(token) == StringType
3007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return token, isOperator, index
3017842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3027842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getBytes(self, index, nBytes):
3037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is not None:
3047842e56b97ce677b83bdab09cda48bc2d89ac75aJust			newIndex = index + nBytes
3057842e56b97ce677b83bdab09cda48bc2d89ac75aJust			bytes = self.bytecode[index:newIndex]
3067842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = newIndex
3077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
3087842e56b97ce677b83bdab09cda48bc2d89ac75aJust			bytes = self.program[index]
3097842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
3107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		assert len(bytes) == nBytes
3117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return bytes, index
3127842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3137842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def do_operator(self, b0, data, index):
3147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if b0 == 12:
3157842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = (b0, ord(data[index]))
3167842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index+1
3177842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
3187842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = b0
3197842e56b97ce677b83bdab09cda48bc2d89ac75aJust		operator = self.operators[op]
3207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return operator, index
3217842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3227842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def toXML(self, xmlWriter):
323dab433233bd4024ede9ad27c6c61ea0072c2edafJust		from fontTools.misc.textTools import num2binary
3247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is not None:
3257842e56b97ce677b83bdab09cda48bc2d89ac75aJust			xmlWriter.dumphex(self.bytecode)
3267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
3277842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = 0
3287842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
3297842e56b97ce677b83bdab09cda48bc2d89ac75aJust			while 1:
3307842e56b97ce677b83bdab09cda48bc2d89ac75aJust				token, isOperator, index = self.getToken(index)
3317842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if token is None:
3327842e56b97ce677b83bdab09cda48bc2d89ac75aJust					break
3337842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if isOperator:
3347842e56b97ce677b83bdab09cda48bc2d89ac75aJust					args = map(str, args)
3357842e56b97ce677b83bdab09cda48bc2d89ac75aJust					if token in ('hintmask', 'cntrmask'):
3367842e56b97ce677b83bdab09cda48bc2d89ac75aJust						hintMask, isOperator, index = self.getToken(index)
3377842e56b97ce677b83bdab09cda48bc2d89ac75aJust						bits = []
3387842e56b97ce677b83bdab09cda48bc2d89ac75aJust						for byte in hintMask:
3397842e56b97ce677b83bdab09cda48bc2d89ac75aJust							bits.append(num2binary(ord(byte), 8))
340586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr						hintMask = string.join(bits, "")
3417842e56b97ce677b83bdab09cda48bc2d89ac75aJust						line = string.join(args + [token, hintMask], " ")
3427842e56b97ce677b83bdab09cda48bc2d89ac75aJust					else:
3437842e56b97ce677b83bdab09cda48bc2d89ac75aJust						line = string.join(args + [token], " ")
3447842e56b97ce677b83bdab09cda48bc2d89ac75aJust					xmlWriter.write(line)
3457842e56b97ce677b83bdab09cda48bc2d89ac75aJust					xmlWriter.newline()
3467842e56b97ce677b83bdab09cda48bc2d89ac75aJust					args = []
3477842e56b97ce677b83bdab09cda48bc2d89ac75aJust				else:
3487842e56b97ce677b83bdab09cda48bc2d89ac75aJust					args.append(token)
3494e5af60930726d06a58a30bae45bb27ae50aea77jvr
3504e5af60930726d06a58a30bae45bb27ae50aea77jvr	def fromXML(self, (name, attrs, content)):
351b58176e5ac4d1e0b0e6a6c71c3020f5e85bd4dfejvr		from fontTools.misc.textTools import binary2num, readHex
352b58176e5ac4d1e0b0e6a6c71c3020f5e85bd4dfejvr		if attrs.get("raw"):
353b58176e5ac4d1e0b0e6a6c71c3020f5e85bd4dfejvr			self.setBytecode(readHex(content))
354b58176e5ac4d1e0b0e6a6c71c3020f5e85bd4dfejvr			return
3554e5af60930726d06a58a30bae45bb27ae50aea77jvr		content = "".join(content)
3564e5af60930726d06a58a30bae45bb27ae50aea77jvr		content = content.split()
3574e5af60930726d06a58a30bae45bb27ae50aea77jvr		program = []
3584e5af60930726d06a58a30bae45bb27ae50aea77jvr		end = len(content)
3594e5af60930726d06a58a30bae45bb27ae50aea77jvr		i = 0
3604e5af60930726d06a58a30bae45bb27ae50aea77jvr		while i < end:
3614e5af60930726d06a58a30bae45bb27ae50aea77jvr			token = content[i]
3624e5af60930726d06a58a30bae45bb27ae50aea77jvr			i = i + 1
3634e5af60930726d06a58a30bae45bb27ae50aea77jvr			try:
3644e5af60930726d06a58a30bae45bb27ae50aea77jvr				token = int(token)
3654e5af60930726d06a58a30bae45bb27ae50aea77jvr			except ValueError:
3664e5af60930726d06a58a30bae45bb27ae50aea77jvr				program.append(token)
3674e5af60930726d06a58a30bae45bb27ae50aea77jvr				if token in ('hintmask', 'cntrmask'):
3684e5af60930726d06a58a30bae45bb27ae50aea77jvr					mask = content[i]
3694e5af60930726d06a58a30bae45bb27ae50aea77jvr					maskBytes = ""
3704e5af60930726d06a58a30bae45bb27ae50aea77jvr					for j in range(0, len(mask), 8):
3714e5af60930726d06a58a30bae45bb27ae50aea77jvr						maskBytes = maskBytes + chr(binary2num(mask[j:j+8]))
3724e5af60930726d06a58a30bae45bb27ae50aea77jvr					program.append(maskBytes)
3734e5af60930726d06a58a30bae45bb27ae50aea77jvr					i = i + 1
3744e5af60930726d06a58a30bae45bb27ae50aea77jvr			else:
3754e5af60930726d06a58a30bae45bb27ae50aea77jvr				program.append(token)
3764e5af60930726d06a58a30bae45bb27ae50aea77jvr		self.setProgram(program)
3777842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3787842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3797842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1Operators = [
3807842e56b97ce677b83bdab09cda48bc2d89ac75aJust#	opcode     name
3817842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(1,        'hstem'),
3827842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(3,        'vstem'),
3837842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(4,        'vmoveto'),
3847842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(5,        'rlineto'),
3857842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(6,        'hlineto'),
3867842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(7,        'vlineto'),
3877842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(8,        'rrcurveto'),
3887842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(9,        'closepath'),
3897842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(10,       'callsubr'),
3907842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(11,       'return'),
3917842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(13,       'hsbw'),
3927842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(14,       'endchar'),
3937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(21,       'rmoveto'),
3947842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(22,       'hmoveto'),
3957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(30,       'vhcurveto'),
3967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(31,       'hvcurveto'),
3977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 0),  'dotsection'),
3987842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 1),  'vstem3'),
3997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 2),  'hstem3'),
4007842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 6),  'seac'),
4017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 7),  'sbw'),
4027842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 12), 'div'),
4037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 16), 'callothersubr'),
4047842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 17), 'pop'),
4057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 33), 'setcurrentpoint'),
4067842e56b97ce677b83bdab09cda48bc2d89ac75aJust]
4077842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4087842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T1CharString(T2CharString):
4097842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = t1OperandEncoding
411455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	operators, opcodes = buildOperatorDict(t1Operators)
4127842e56b97ce677b83bdab09cda48bc2d89ac75aJust
413489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, bytecode=None, program=None, subrs=None):
414489d76a340845361def6af9ab7d9152f8e66f417jvr		if program is None:
415489d76a340845361def6af9ab7d9152f8e66f417jvr			program = []
416489d76a340845361def6af9ab7d9152f8e66f417jvr		self.bytecode = bytecode
417489d76a340845361def6af9ab7d9152f8e66f417jvr		self.program = program
418489d76a340845361def6af9ab7d9152f8e66f417jvr		self.subrs = subrs
419489d76a340845361def6af9ab7d9152f8e66f417jvr
4207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self):
421b68a700595ff730c29d3d4b7abf92ee287678745Just		if self.program is not None:
4227842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
4237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		program = []
4247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
4257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while 1:
4267842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token, isOperator, index = self.getToken(index)
4277842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if token is None:
4287842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break
4297842e56b97ce677b83bdab09cda48bc2d89ac75aJust			program.append(token)
4307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.setProgram(program)
4317842e56b97ce677b83bdab09cda48bc2d89ac75aJust
432489d76a340845361def6af9ab7d9152f8e66f417jvr	def draw(self, pen):
433489d76a340845361def6af9ab7d9152f8e66f417jvr		extractor = T1OutlineExtractor(pen, self.subrs)
434489d76a340845361def6af9ab7d9152f8e66f417jvr		extractor.execute(self)
435489d76a340845361def6af9ab7d9152f8e66f417jvr		self.width = extractor.width
436489d76a340845361def6af9ab7d9152f8e66f417jvr
4377842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4387842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass SimpleT2Decompiler:
4397842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __init__(self, localSubrs, globalSubrs):
4417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.localSubrs = localSubrs
4427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.localBias = calcSubrBias(localSubrs)
4437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.globalSubrs = globalSubrs
4447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.globalBias = calcSubrBias(globalSubrs)
4457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.reset()
4467842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4477842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
4487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.callingStack = []
4497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.operandStack = []
4507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = 0
4517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintMaskBytes = 0
4527842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4537842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def execute(self, charString):
4547842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.callingStack.append(charString)
4557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		needsDecompilation = charString.needsDecompilation()
4567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if needsDecompilation:
4577842e56b97ce677b83bdab09cda48bc2d89ac75aJust			program = []
4587842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pushToProgram = program.append
4597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
4607842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pushToProgram = lambda x: None
4617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pushToStack = self.operandStack.append
4627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
4637842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while 1:
4647842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token, isOperator, index = charString.getToken(index)
4657842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if token is None:
4667842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break  # we're done!
4677842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pushToProgram(token)
4687842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if isOperator:
4697842e56b97ce677b83bdab09cda48bc2d89ac75aJust				handlerName = "op_" + token
4707842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if hasattr(self, handlerName):
4717842e56b97ce677b83bdab09cda48bc2d89ac75aJust					handler = getattr(self, handlerName)
4727842e56b97ce677b83bdab09cda48bc2d89ac75aJust					rv = handler(index)
4737842e56b97ce677b83bdab09cda48bc2d89ac75aJust					if rv:
4747842e56b97ce677b83bdab09cda48bc2d89ac75aJust						hintMaskBytes, index = rv
4757842e56b97ce677b83bdab09cda48bc2d89ac75aJust						pushToProgram(hintMaskBytes)
4767842e56b97ce677b83bdab09cda48bc2d89ac75aJust				else:
4777842e56b97ce677b83bdab09cda48bc2d89ac75aJust					self.popall()
4787842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
4797842e56b97ce677b83bdab09cda48bc2d89ac75aJust				pushToStack(token)
4807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if needsDecompilation:
4819920ad5286b6e61d67f07f908107d65f7fa817acjvr			assert program, "illegal CharString: decompiled to empty program"
4829920ad5286b6e61d67f07f908107d65f7fa817acjvr			assert program[-1] in ("endchar", "return", "callsubr", "callgsubr",
4839920ad5286b6e61d67f07f908107d65f7fa817acjvr					"seac"), "illegal CharString"
4847842e56b97ce677b83bdab09cda48bc2d89ac75aJust			charString.setProgram(program)
4857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.callingStack[-1]
4867842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4877842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def pop(self):
4887842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value = self.operandStack[-1]
4897842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.operandStack[-1]
4907842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value
4917842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4927842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popall(self):
4937842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack = self.operandStack[:]
4947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.operandStack[:] = []
4957842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return stack
4967842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def push(self, value):
4987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.operandStack.append(value)
4997842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5007842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_return(self, index):
5017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.operandStack:
5027842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pass
5037842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5047842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
5057842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pass
5067842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5077842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callsubr(self, index):
5087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
5097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.localSubrs[subrIndex+self.localBias]
5107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
5117842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callgsubr(self, index):
5137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
5147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.globalSubrs[subrIndex+self.globalBias]
5157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
5167842e56b97ce677b83bdab09cda48bc2d89ac75aJust
517586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def op_hstem(self, index):
518586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.countHints()
519586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def op_vstem(self, index):
520586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.countHints()
5217842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hstemhm(self, index):
5227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.countHints()
523586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def op_vstemhm(self, index):
524586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.countHints()
5257842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5267842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hintmask(self, index):
5277842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if not self.hintMaskBytes:
5287842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.countHints()
5297842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.hintMaskBytes = (self.hintCount + 7) / 8
5307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		hintMaskBytes, index = self.callingStack[-1].getBytes(index, self.hintMaskBytes)
5317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return hintMaskBytes, index
5327842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	op_cntrmask = op_hintmask
5347842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def countHints(self):
5367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
5377842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = self.hintCount + len(args) / 2
5387842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5397842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5407842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T2OutlineExtractor(SimpleT2Decompiler):
5417842e56b97ce677b83bdab09cda48bc2d89ac75aJust
542489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, pen, localSubrs, globalSubrs, nominalWidthX, defaultWidthX):
5437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		SimpleT2Decompiler.__init__(self, localSubrs, globalSubrs)
544489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen = pen
5457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.nominalWidthX = nominalWidthX
5467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.defaultWidthX = defaultWidthX
5477842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5487842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
5497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		SimpleT2Decompiler.reset(self)
5507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hints = []
5517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.gotWidth = 0
5527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = 0
553489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = (0, 0)
554489d76a340845361def6af9ab7d9152f8e66f417jvr		self.sawMoveTo = 0
5557842e56b97ce677b83bdab09cda48bc2d89ac75aJust
556489d76a340845361def6af9ab7d9152f8e66f417jvr	def _nextPoint(self, point):
557489d76a340845361def6af9ab7d9152f8e66f417jvr		x, y = self.currentPoint
558489d76a340845361def6af9ab7d9152f8e66f417jvr		point = x + point[0], y + point[1]
559489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = point
560489d76a340845361def6af9ab7d9152f8e66f417jvr		return point
5617842e56b97ce677b83bdab09cda48bc2d89ac75aJust
562489d76a340845361def6af9ab7d9152f8e66f417jvr	def rMoveTo(self, point):
563489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.moveTo(self._nextPoint(point))
564489d76a340845361def6af9ab7d9152f8e66f417jvr		self.sawMoveTo = 1
565489d76a340845361def6af9ab7d9152f8e66f417jvr
566489d76a340845361def6af9ab7d9152f8e66f417jvr	def rLineTo(self, point):
567489d76a340845361def6af9ab7d9152f8e66f417jvr		if not self.sawMoveTo:
568489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rMoveTo((0, 0))
569489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.lineTo(self._nextPoint(point))
570489d76a340845361def6af9ab7d9152f8e66f417jvr
571489d76a340845361def6af9ab7d9152f8e66f417jvr	def rCurveTo(self, pt1, pt2, pt3):
572489d76a340845361def6af9ab7d9152f8e66f417jvr		if not self.sawMoveTo:
573489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rMoveTo((0, 0))
574489d76a340845361def6af9ab7d9152f8e66f417jvr		nextPoint = self._nextPoint
575489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.curveTo(nextPoint(pt1), nextPoint(pt2), nextPoint(pt3))
5767842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5777842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def closePath(self):
578489d76a340845361def6af9ab7d9152f8e66f417jvr		if self.sawMoveTo:
579489d76a340845361def6af9ab7d9152f8e66f417jvr			self.pen.closePath()
580489d76a340845361def6af9ab7d9152f8e66f417jvr		self.sawMoveTo = 0
5817842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5827842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popallWidth(self, evenOdd=0):
5837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
5847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if not self.gotWidth:
5857842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if evenOdd ^ (len(args) % 2):
5867842e56b97ce677b83bdab09cda48bc2d89ac75aJust				self.width = self.nominalWidthX + args[0]
5877842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = args[1:]
5887842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
5897842e56b97ce677b83bdab09cda48bc2d89ac75aJust				self.width = self.defaultWidthX
5907842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.gotWidth = 1
5917842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
5927842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def countHints(self):
5947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popallWidth()
5957842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = self.hintCount + len(args) / 2
5967842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
5987842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# hint operators
5997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
600586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_hstem(self, index):
601586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
602586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_vstem(self, index):
603586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
604586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_hstemhm(self, index):
605586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
606586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_vstemhm(self, index):
607586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
6087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#def op_hintmask(self, index):
6097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#	self.countHints()
6107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#def op_cntrmask(self, index):
6117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#	self.countHints()
6127842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6137842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, moveto
6157842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rmoveto(self, index):
6177842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
618489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo(self.popallWidth())
6197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hmoveto(self, index):
6207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
621489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((self.popallWidth(1)[0], 0))
6227842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vmoveto(self, index):
6237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
624489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((0, self.popallWidth(1)[0]))
6257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
626382df6c42a7a6aecb690e07c6338e19f038f0543jvr		args = self.popallWidth()
627382df6c42a7a6aecb690e07c6338e19f038f0543jvr		if args:
628382df6c42a7a6aecb690e07c6338e19f038f0543jvr			from fontTools.encodings.StandardEncoding import StandardEncoding
629382df6c42a7a6aecb690e07c6338e19f038f0543jvr			# endchar can do seac accent bulding; The T2 spec says it's deprecated,
630382df6c42a7a6aecb690e07c6338e19f038f0543jvr			# but recent software that shall remain nameless does output it.
631382df6c42a7a6aecb690e07c6338e19f038f0543jvr			adx, ady, bchar, achar = args
632382df6c42a7a6aecb690e07c6338e19f038f0543jvr			baseGlyph = StandardEncoding[bchar]
633382df6c42a7a6aecb690e07c6338e19f038f0543jvr			self.pen.addComponent(baseGlyph, (1, 0, 0, 1, 0, 0))
634382df6c42a7a6aecb690e07c6338e19f038f0543jvr			accentGlyph = StandardEncoding[achar]
635382df6c42a7a6aecb690e07c6338e19f038f0543jvr			self.pen.addComponent(accentGlyph, (1, 0, 0, 1, adx, ady))
6367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
6377842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, lines
6407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6417842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rlineto(self, index):
6427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
6437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 2):
6447842e56b97ce677b83bdab09cda48bc2d89ac75aJust			point = args[i:i+2]
645489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rLineTo(point)
6467842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6477842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hlineto(self, index):
6487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.alternatingLineto(1)
6497842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vlineto(self, index):
6507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.alternatingLineto(0)
6517842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6527842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6537842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, curves
6547842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6557842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rrcurveto(self, index):
6567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya dxb dyb dxc dyc}+ rrcurveto"""
6577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
6587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 6):
6597842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxa, dya, dxb, dyb, dxc, dyc, = args[i:i+6]
660489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dxa, dya), (dxb, dyb), (dxc, dyc))
6617842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6627842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rcurveline(self, index):
6637842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya dxb dyb dxc dyc}+ dxd dyd rcurveline"""
6647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
6657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args)-2, 6):
6667842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxb, dyb, dxc, dyc, dxd, dyd = args[i:i+6]
667489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dxb, dyb), (dxc, dyc), (dxd, dyd))
668489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rLineTo(args[-2:])
6697842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6707842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rlinecurve(self, index):
6717842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya}+ dxb dyb dxc dyc dxd dyd rlinecurve"""
6727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
6737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lineArgs = args[:-6]
6747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(lineArgs), 2):
675489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rLineTo(lineArgs[i:i+2])
6767842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dxb, dyb, dxc, dyc, dxd, dyd = args[-6:]
677489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rCurveTo((dxb, dyb), (dxc, dyc), (dxd, dyd))
6787842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6797842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vvcurveto(self, index):
6807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"dx1? {dya dxb dyb dyc}+ vvcurveto"
6817842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
6827842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) % 2:
6837842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = args[0]
6847842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = args[1:]
6857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
6867842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = 0
6877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 4):
6887842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dya, dxb, dyb, dyc = args[i:i+4]
689489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dx1, dya), (dxb, dyb), (0, dyc))
6907842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = 0
6917842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6927842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hhcurveto(self, index):
6937842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dy1? {dxa dxb dyb dxc}+ hhcurveto"""
6947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
6957842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) % 2:
6967842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = args[0]
6977842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = args[1:]
6987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
6997842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = 0
7007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 4):
7017842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxa, dxb, dyb, dxc = args[i:i+4]
702489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dxa, dy1), (dxb, dyb), (dxc, 0))
7037842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = 0
7047842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vhcurveto(self, index):
7067842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? vhcurveto (30)
7077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		{dya dxb dyb dxc dxd dxe dye dyf}+ dxf? vhcurveto
7087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""
7097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while args:
7117842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = self.vcurveto(args)
7127842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if args:
7137842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = self.hcurveto(args)
7147842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7157842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hvcurveto(self, index):
7167842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf?
7177842e56b97ce677b83bdab09cda48bc2d89ac75aJust		{dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?
7187842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""
7197842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while args:
7217842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = self.hcurveto(args)
7227842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if args:
7237842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = self.vcurveto(args)
7247842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7267842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, flex
7277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hflex(self, index):
7297842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7307842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_flex(self, index):
7317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hflex1(self, index):
7337842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7347842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_flex1(self, index):
7357842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7367842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# MultipleMaster. Well...
7397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_blend(self, index):
7417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7427842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7437842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# misc
7447842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_and(self, index):
7457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7467842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_or(self, index):
7477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7487842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_not(self, index):
7497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7507842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_store(self, index):
7517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7527842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_abs(self, index):
7537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7547842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_add(self, index):
7557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7567842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sub(self, index):
7577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7587842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_div(self, index):
7597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		num2 = self.pop()
7607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		num1 = self.pop()
7617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		d1 = num1/num2
7627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		d2 = float(num1)/num2
7637842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if d1 == d2:
7647842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(d1)
7657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
7667842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(d2)
7677842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_load(self, index):
7687842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7697842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_neg(self, index):
7707842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7717842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_eq(self, index):
7727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7737842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_drop(self, index):
7747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7757842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_put(self, index):
7767842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7777842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_get(self, index):
7787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7797842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_ifelse(self, index):
7807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7817842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_random(self, index):
7827842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7837842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_mul(self, index):
7847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7857842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sqrt(self, index):
7867842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7877842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_dup(self, index):
7887842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7897842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_exch(self, index):
7907842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7917842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_index(self, index):
7927842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_roll(self, index):
7947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		XXX
7957842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# miscelaneous helpers
7987842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def alternatingLineto(self, isHorizontal):
8007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
8017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for arg in args:
8027842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if isHorizontal:
8037842e56b97ce677b83bdab09cda48bc2d89ac75aJust				point = (arg, 0)
8047842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
8057842e56b97ce677b83bdab09cda48bc2d89ac75aJust				point = (0, arg)
806489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rLineTo(point)
8077842e56b97ce677b83bdab09cda48bc2d89ac75aJust			isHorizontal = not isHorizontal
8087842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def vcurveto(self, args):
8107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dya, dxb, dyb, dxc = args[:4]
8117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = args[4:]
8127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) == 1:
8137842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dyc = args[0]
8147842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
8157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
8167842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dyc = 0
817489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rCurveTo((0, dya), (dxb, dyb), (dxc, dyc))
8187842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
8197842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def hcurveto(self, args):
8217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dxa, dxb, dyb, dyc = args[:4]
8227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = args[4:]
8237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) == 1:
8247842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxc = args[0]
8257842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
8267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
8277842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxc = 0
828489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rCurveTo((dxa, 0), (dxb, dyb), (dxc, dyc))
8297842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
8307842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8317842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8327842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T1OutlineExtractor(T2OutlineExtractor):
8337842e56b97ce677b83bdab09cda48bc2d89ac75aJust
834489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, pen, subrs):
835489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen = pen
8367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.subrs = subrs
8377842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.reset()
8387842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
8407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.flexing = 0
8417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = 0
8427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.sbx = 0
8437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		T2OutlineExtractor.reset(self)
8447842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popallWidth(self, evenOdd=0):
8467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.popall()
8477842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8487842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def exch(self):
8497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack = self.operandStack
8507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack[-1], stack[-2] = stack[-2], stack[-1]
8517842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8527842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8537842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors
8547842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8557842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rmoveto(self, index):
8567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
8577842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
858489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo(self.popall())
8597842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hmoveto(self, index):
8607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
8617842e56b97ce677b83bdab09cda48bc2d89ac75aJust			# We must add a parameter to the stack if we are flexing
8627842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(0)
8637842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
864489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((self.popall()[0], 0))
8657842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vmoveto(self, index):
8667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
8677842e56b97ce677b83bdab09cda48bc2d89ac75aJust			# We must add a parameter to the stack if we are flexing
8687842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(0)
8697842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.exch()
8707842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
871489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((0, self.popall()[0]))
8727842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_closepath(self, index):
8737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
8747842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_setcurrentpoint(self, index):
8757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
8767842e56b97ce677b83bdab09cda48bc2d89ac75aJust		x, y = args
877489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = x, y
8787842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8797842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
8807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
8817842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8827842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hsbw(self, index):
8837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		sbx, wx = self.popall()
8847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = wx
8857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.sbx = sbx
886489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = sbx, self.currentPoint[1]
8877842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sbw(self, index):
8887842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
8897842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8907842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8917842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callsubr(self, index):
8927842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
8937842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.subrs[subrIndex]
8947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
8957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callothersubr(self, index):
8967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
8977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		nArgs = self.pop()
8987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		#print nArgs, subrIndex, "callothersubr"
8997842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if subrIndex == 0 and nArgs == 3:
9007842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.doFlex()
9017842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.flexing = 0
9027842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif subrIndex == 1 and nArgs == 0:
9037842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.flexing = 1
9047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# ignore...
9057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_pop(self, index):
9067842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pass  # ignore...
9077842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def doFlex(self):
9097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		finaly = self.pop()
9107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		finalx = self.pop()
9117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.pop()	# flex height is unused
9127842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p3y = self.pop()
9147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p3x = self.pop()
9157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp4y = self.pop()
9167842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp4x = self.pop()
9177842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp3y = self.pop()
9187842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp3x = self.pop()
9197842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p2y = self.pop()
9207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p2x = self.pop()
9217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp2y = self.pop()
9227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp2x = self.pop()
9237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp1y = self.pop()
9247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp1x = self.pop()
9257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		rpy = self.pop()
9267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		rpx = self.pop()
9277842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9287842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# call rrcurveto
9297842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp1x+rpx)
9307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp1y+rpy)
9317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp2x)
9327842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp2y)
9337842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p2x)
9347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p2y)
9357842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.op_rrcurveto(None)
9367842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9377842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# call rrcurveto
9387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp3x)
9397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp3y)
9407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp4x)
9417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp4y)
9427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p3x)
9437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p3y)
9447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.op_rrcurveto(None)
9457842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# Push back final coords so subr 0 can find them
9477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(finalx)
9487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(finaly)
9497842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9507842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_dotsection(self, index):
9517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
9527842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hstem3(self, index):
9537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
9547842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_seac(self, index):
9557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"asb adx ady bchar achar seac"
956489d76a340845361def6af9ab7d9152f8e66f417jvr		from fontTools.encodings.StandardEncoding import StandardEncoding
957489d76a340845361def6af9ab7d9152f8e66f417jvr		asb, adx, ady, bchar, achar = self.popall()
958489d76a340845361def6af9ab7d9152f8e66f417jvr		baseGlyph = StandardEncoding[bchar]
959489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.addComponent(baseGlyph, (1, 0, 0, 1, 0, 0))
960489d76a340845361def6af9ab7d9152f8e66f417jvr		accentGlyph = StandardEncoding[achar]
961489d76a340845361def6af9ab7d9152f8e66f417jvr		adx = adx + self.sbx - asb  # seac weirdness
962489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.addComponent(accentGlyph, (1, 0, 0, 1, adx, ady))
9637842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vstem3(self, index):
9647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
9657842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9667842e56b97ce677b83bdab09cda48bc2d89ac75aJust
967f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrclass DictDecompiler(ByteCodeBase):
9687842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9697842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = cffDictOperandEncoding
9707842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9717842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __init__(self, strings):
9727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.stack = []
9737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.strings = strings
9747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.dict = {}
9757842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9767842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getDict(self):
9777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		assert len(self.stack) == 0, "non-empty stack"
9787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.dict
9797842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9807842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self, data):
9817842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
9827842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lenData = len(data)
9837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		push = self.stack.append
9847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while index < lenData:
9857842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b0 = ord(data[index])
9867842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
9877842e56b97ce677b83bdab09cda48bc2d89ac75aJust			code = self.operandEncoding[b0]
9887842e56b97ce677b83bdab09cda48bc2d89ac75aJust			handler = getattr(self, code)
9897842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value, index = handler(b0, data, index)
9907842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if value is not None:
9917842e56b97ce677b83bdab09cda48bc2d89ac75aJust				push(value)
9927842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def pop(self):
9947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value = self.stack[-1]
9957842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.stack[-1]
9967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value
9977842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9987842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popall(self):
9997842e56b97ce677b83bdab09cda48bc2d89ac75aJust		all = self.stack[:]
10007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.stack[:]
10017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return all
10027842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def do_operator(self, b0, data, index):
10047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if b0 == 12:
10057842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = (b0, ord(data[index]))
10067842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index+1
10077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
10087842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = b0
10097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		operator, argType = self.operators[op]
10107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.handle_operator(operator, argType)
10117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return None, index
10127842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10137842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def handle_operator(self, operator, argType):
10147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if type(argType) == type(()):
10157842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = ()
1016bf2f402913a2706dfa92190e60cba7acbf01c9d7jvr			for i in range(len(argType)-1, -1, -1):
1017bf2f402913a2706dfa92190e60cba7acbf01c9d7jvr				arg = argType[i]
10187842e56b97ce677b83bdab09cda48bc2d89ac75aJust				arghandler = getattr(self, "arg_" + arg)
10197842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value = (arghandler(operator),) + value
10207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
10217842e56b97ce677b83bdab09cda48bc2d89ac75aJust			arghandler = getattr(self, "arg_" + argType)
10227842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = arghandler(operator)
10237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.dict[operator] = value
10247842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_number(self, name):
10267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.pop()
10277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_SID(self, name):
10287842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.strings[self.pop()]
10297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_array(self, name):
10307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.popall()
1031dc18128aa9b3f6b98a623c294ac615195159025ejvr	def arg_delta(self, name):
1032dc18128aa9b3f6b98a623c294ac615195159025ejvr		out = []
1033dc18128aa9b3f6b98a623c294ac615195159025ejvr		current = 0
1034dc18128aa9b3f6b98a623c294ac615195159025ejvr		for v in self.popall():
10356f03a58f59fb20662602e3d4bb153d7db2f778d3jvr			current = current + v
1036dc18128aa9b3f6b98a623c294ac615195159025ejvr			out.append(current)
1037dc18128aa9b3f6b98a623c294ac615195159025ejvr		return out
10387842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10397842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10407842e56b97ce677b83bdab09cda48bc2d89ac75aJustdef calcSubrBias(subrs):
10417842e56b97ce677b83bdab09cda48bc2d89ac75aJust	nSubrs = len(subrs)
10427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	if nSubrs < 1240:
10437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 107
10447842e56b97ce677b83bdab09cda48bc2d89ac75aJust	elif nSubrs < 33900:
10457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 1131
10467842e56b97ce677b83bdab09cda48bc2d89ac75aJust	else:
10477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 32768
10487842e56b97ce677b83bdab09cda48bc2d89ac75aJust	return bias
1049