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