psCharStrings.py revision 7099f4c0f9fbaf1a5c811113fdfd2404dee04361
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"
2395c9e9fc11dc028bd1747788f2b417f3936fc59bjvrt2OperandEncoding[255] = "read_fixed1616"
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, '-']
33f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrrealNibblesDict = {}
34f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrfor _i in range(len(realNibbles)):
35f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	realNibblesDict[realNibbles[_i]] = _i
367842e56b97ce677b83bdab09cda48bc2d89ac75aJust
377842e56b97ce677b83bdab09cda48bc2d89ac75aJust
38f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrclass ByteCodeBase:
397842e56b97ce677b83bdab09cda48bc2d89ac75aJust
407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_byte(self, b0, data, index):
417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return b0 - 139, index
427842e56b97ce677b83bdab09cda48bc2d89ac75aJust
437842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_smallInt1(self, b0, data, index):
447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		b1 = ord(data[index])
457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return (b0-247)*256 + b1 + 108, index+1
467842e56b97ce677b83bdab09cda48bc2d89ac75aJust
477842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_smallInt2(self, b0, data, index):
487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		b1 = ord(data[index])
497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return -(b0-251)*256 - b1 - 108, index+1
507842e56b97ce677b83bdab09cda48bc2d89ac75aJust
517842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_shortInt(self, b0, data, index):
527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bin = data[index] + data[index+1]
537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value, = struct.unpack(">h", bin)
547842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value, index+2
557842e56b97ce677b83bdab09cda48bc2d89ac75aJust
567842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_longInt(self, b0, data, index):
577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bin = data[index] + data[index+1] + data[index+2] + data[index+3]
587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value, = struct.unpack(">l", bin)
597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value, index+4
607842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6195c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	def read_fixed1616(self, b0, data, index):
6295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		bin = data[index] + data[index+1] + data[index+2] + data[index+3]
6395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		value, = struct.unpack(">l", bin)
6495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		return value / 65536.0, index+4
6595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr
667842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_realNumber(self, b0, data, index):
677842e56b97ce677b83bdab09cda48bc2d89ac75aJust		number = ''
687842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while 1:
697842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b = ord(data[index])
707842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
717842e56b97ce677b83bdab09cda48bc2d89ac75aJust			nibble0 = (b & 0xf0) >> 4
727842e56b97ce677b83bdab09cda48bc2d89ac75aJust			nibble1 = b & 0x0f
737842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if nibble0 == 0xf:
747842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break
757842e56b97ce677b83bdab09cda48bc2d89ac75aJust			number = number + realNibbles[nibble0]
767842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if nibble1 == 0xf:
777842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break
787842e56b97ce677b83bdab09cda48bc2d89ac75aJust			number = number + realNibbles[nibble1]
79455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		return float(number), index
807842e56b97ce677b83bdab09cda48bc2d89ac75aJust
817842e56b97ce677b83bdab09cda48bc2d89ac75aJust
82dbc2c173b35360386c907a3c70cb931ae4c3fac9jvrdef buildOperatorDict(operatorList):
83455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	oper = {}
84455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	opc = {}
857842e56b97ce677b83bdab09cda48bc2d89ac75aJust	for item in operatorList:
867842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(item) == 2:
87455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			oper[item[0]] = item[1]
88455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		else:
89455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			oper[item[0]] = item[1:]
90455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		if type(item[0]) == types.TupleType:
91455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			opc[item[1]] = item[0]
927842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
93455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			opc[item[1]] = (item[0],)
94455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	return oper, opc
957842e56b97ce677b83bdab09cda48bc2d89ac75aJust
967842e56b97ce677b83bdab09cda48bc2d89ac75aJust
977842e56b97ce677b83bdab09cda48bc2d89ac75aJustt2Operators = [
987842e56b97ce677b83bdab09cda48bc2d89ac75aJust#	opcode     name
997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(1,        'hstem'),
1007842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(3,        'vstem'),
1017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(4,        'vmoveto'),
1027842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(5,        'rlineto'),
1037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(6,        'hlineto'),
1047842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(7,        'vlineto'),
1057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(8,        'rrcurveto'),
1067842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(10,       'callsubr'),
1077842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(11,       'return'),
1087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(14,       'endchar'),
1097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(16,       'blend'),
1107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(18,       'hstemhm'),
1117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(19,       'hintmask'),
1127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(20,       'cntrmask'),
1137842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(21,       'rmoveto'),
1147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(22,       'hmoveto'),
1157842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(23,       'vstemhm'),
1167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(24,       'rcurveline'),
1177842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(25,       'rlinecurve'),
1187842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(26,       'vvcurveto'),
1197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(27,       'hhcurveto'),
1207842e56b97ce677b83bdab09cda48bc2d89ac75aJust#	(28,       'shortint'),  # not really an operator
1217842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(29,       'callgsubr'),
1227842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(30,       'vhcurveto'),
1237842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(31,       'hvcurveto'),
1247099f4c0f9fbaf1a5c811113fdfd2404dee04361jvr	((12, 0),  'ignore'),  # dotsection. Yes, there a few very early OTF/CFF
1257099f4c0f9fbaf1a5c811113fdfd2404dee04361jvr	                   # fonts with this deprecated operator. Just ignore it.
1267842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 3),  'and'),
1277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 4),  'or'),
1287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 5),  'not'),
1297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 8),  'store'),
1307842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 9),  'abs'),
1317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 10), 'add'),
1327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 11), 'sub'),
1337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 12), 'div'),
1347842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 13), 'load'),
1357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 14), 'neg'),
1367842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 15), 'eq'),
1377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 18), 'drop'),
1387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 20), 'put'),
1397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 21), 'get'),
1407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 22), 'ifelse'),
1417842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 23), 'random'),
1427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 24), 'mul'),
1437842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 26), 'sqrt'),
1447842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 27), 'dup'),
1457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 28), 'exch'),
1467842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 29), 'index'),
1477842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 30), 'roll'),
1487842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 34), 'hflex'),
1497842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 35), 'flex'),
1507842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 36), 'hflex1'),
1517842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 37), 'flex1'),
1527842e56b97ce677b83bdab09cda48bc2d89ac75aJust]
1537842e56b97ce677b83bdab09cda48bc2d89ac75aJust
154f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
155f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrdef getIntEncoder(format):
156f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	if format == "cff":
157f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		fourByteOp = chr(29)
158f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	elif format == "t1":
15995c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		fourByteOp = chr(255)
160f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	else:
161f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		assert format == "t2"
16295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		fourByteOp = None
163f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
16495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	def encodeInt(value, fourByteOp=fourByteOp, chr=chr,
16595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr			pack=struct.pack, unpack=struct.unpack):
166f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		if -107 <= value <= 107:
167f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = chr(value + 139)
168f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		elif 108 <= value <= 1131:
169f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			value = value - 108
170f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = chr((value >> 8) + 247) + chr(value & 0xFF)
171f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		elif -1131 <= value <= -108:
172f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			value = -value - 108
173f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = chr((value >> 8) + 251) + chr(value & 0xFF)
17495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		elif fourByteOp is None:
17595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr			# T2 only supports 2 byte ints
17695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr			if -32768 <= value <= 32767:
17795c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				code = chr(28) + pack(">h", value)
17895c9e9fc11dc028bd1747788f2b417f3936fc59bjvr			else:
17995c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# Backwards compatible hack: due to a previous bug in FontTools,
18095c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# 16.16 fixed numbers were written out as 4-byte ints. When
18195c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# these numbers were small, they were wrongly written back as
18295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# small ints instead of 4-byte ints, breaking round-tripping.
18395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# This here workaround doesn't do it any better, since we can't
18495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# distinguish anymore between small ints that were supposed to
18595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# be small fixed numbers and small ints that were just small
18695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# ints. Hence the warning.
18795c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				import sys
18895c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				sys.stderr.write("Warning: 4-byte T2 number got passed to the "
18995c9e9fc11dc028bd1747788f2b417f3936fc59bjvr					"IntType handler. This should happen only when reading in "
19095c9e9fc11dc028bd1747788f2b417f3936fc59bjvr					"old XML files.\n")
19195c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				code = chr(255) + pack(">l", value)
192f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		else:
193f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = fourByteOp + pack(">l", value)
194f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		return code
195f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
196f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	return encodeInt
197f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
198f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
199f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrencodeIntCFF = getIntEncoder("cff")
200f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrencodeIntT1 = getIntEncoder("t1")
201f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrencodeIntT2 = getIntEncoder("t2")
202f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
20395c9e9fc11dc028bd1747788f2b417f3936fc59bjvrdef encodeFixed(f, pack=struct.pack):
20495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	# For T2 only
20595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	return "\xff" + pack(">l", int(round(f * 65536)))
20695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr
207f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrdef encodeFloat(f):
20895c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	# For CFF only, used in cffLib
209f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	s = str(f).upper()
210f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	if s[:2] == "0.":
211f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		s = s[1:]
212f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	elif s[:3] == "-0.":
213f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		s = "-" + s[2:]
214f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	nibbles = []
215f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	while s:
216f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		c = s[0]
217f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		s = s[1:]
218f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		if c == "E" and s[:1] == "-":
219f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			s = s[1:]
220f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			c = "E-"
221f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		nibbles.append(realNibblesDict[c])
222f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	nibbles.append(0xf)
223f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	if len(nibbles) % 2:
224f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		nibbles.append(0xf)
225f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	d = chr(30)
226f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	for i in range(0, len(nibbles), 2):
227f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		d = d + chr(nibbles[i] << 4 | nibbles[i+1])
228f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	return d
229f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
230f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
2314e5af60930726d06a58a30bae45bb27ae50aea77jvrclass CharStringCompileError(Exception): pass
2324e5af60930726d06a58a30bae45bb27ae50aea77jvr
2334e5af60930726d06a58a30bae45bb27ae50aea77jvr
234f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrclass T2CharString(ByteCodeBase):
2357842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2367842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = t2OperandEncoding
237455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	operators, opcodes = buildOperatorDict(t2Operators)
2387842e56b97ce677b83bdab09cda48bc2d89ac75aJust
239489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, bytecode=None, program=None, private=None, globalSubrs=None):
2407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if program is None:
2417842e56b97ce677b83bdab09cda48bc2d89ac75aJust			program = []
2427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.bytecode = bytecode
2437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.program = program
244489d76a340845361def6af9ab7d9152f8e66f417jvr		self.private = private
245586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.globalSubrs = globalSubrs
2467842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2477842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __repr__(self):
2487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is None:
2497842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return "<%s (source) at %x>" % (self.__class__.__name__, id(self))
2507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
2517842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return "<%s (bytecode) at %x>" % (self.__class__.__name__, id(self))
2527842e56b97ce677b83bdab09cda48bc2d89ac75aJust
25395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	def getIntEncoder(self):
25495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		return encodeIntT2
25595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr
25695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	def getFixedEncoder(self):
25795c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		return encodeFixed
25895c9e9fc11dc028bd1747788f2b417f3936fc59bjvr
259586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def decompile(self):
260586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		if not self.needsDecompilation():
261586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr			return
262489d76a340845361def6af9ab7d9152f8e66f417jvr		subrs = getattr(self.private, "Subrs", [])
263489d76a340845361def6af9ab7d9152f8e66f417jvr		decompiler = SimpleT2Decompiler(subrs, self.globalSubrs)
264586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		decompiler.execute(self)
265586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr
266489d76a340845361def6af9ab7d9152f8e66f417jvr	def draw(self, pen):
267489d76a340845361def6af9ab7d9152f8e66f417jvr		subrs = getattr(self.private, "Subrs", [])
268489d76a340845361def6af9ab7d9152f8e66f417jvr		extractor = T2OutlineExtractor(pen, subrs, self.globalSubrs,
269489d76a340845361def6af9ab7d9152f8e66f417jvr				self.private.nominalWidthX, self.private.defaultWidthX)
270489d76a340845361def6af9ab7d9152f8e66f417jvr		extractor.execute(self)
271489d76a340845361def6af9ab7d9152f8e66f417jvr		self.width = extractor.width
272489d76a340845361def6af9ab7d9152f8e66f417jvr
273455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	def compile(self):
274455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		if self.bytecode is not None:
275455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			return
2769920ad5286b6e61d67f07f908107d65f7fa817acjvr		assert self.program, "illegal CharString: decompiled to empty program"
2779920ad5286b6e61d67f07f908107d65f7fa817acjvr		assert self.program[-1] in ("endchar", "return", "callsubr", "callgsubr",
2789920ad5286b6e61d67f07f908107d65f7fa817acjvr				"seac"), "illegal CharString"
279455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		bytecode = []
280455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		opcodes = self.opcodes
2814e5af60930726d06a58a30bae45bb27ae50aea77jvr		program = self.program
28295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		encodeInt = self.getIntEncoder()
28395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		encodeFixed = self.getFixedEncoder()
2844e5af60930726d06a58a30bae45bb27ae50aea77jvr		i = 0
2854e5af60930726d06a58a30bae45bb27ae50aea77jvr		end = len(program)
2864e5af60930726d06a58a30bae45bb27ae50aea77jvr		while i < end:
2874e5af60930726d06a58a30bae45bb27ae50aea77jvr			token = program[i]
2884e5af60930726d06a58a30bae45bb27ae50aea77jvr			i = i + 1
289455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			tp = type(token)
290455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			if tp == types.StringType:
2914e5af60930726d06a58a30bae45bb27ae50aea77jvr				try:
292455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr					bytecode.extend(map(chr, opcodes[token]))
2934e5af60930726d06a58a30bae45bb27ae50aea77jvr				except KeyError:
2944e5af60930726d06a58a30bae45bb27ae50aea77jvr					raise CharStringCompileError, "illegal operator: %s" % token
2954e5af60930726d06a58a30bae45bb27ae50aea77jvr				if token in ('hintmask', 'cntrmask'):
2964e5af60930726d06a58a30bae45bb27ae50aea77jvr					bytecode.append(program[i])  # hint mask
2974e5af60930726d06a58a30bae45bb27ae50aea77jvr					i = i + 1
298455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			elif tp == types.IntType:
29995c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				bytecode.append(encodeInt(token))
30095c9e9fc11dc028bd1747788f2b417f3936fc59bjvr			elif tp == types.FloatType:
30195c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				bytecode.append(encodeFixed(token))
302455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			else:
303f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr				assert 0, "unsupported type: %s" % tp
3044e5af60930726d06a58a30bae45bb27ae50aea77jvr		try:
3054e5af60930726d06a58a30bae45bb27ae50aea77jvr			bytecode = "".join(bytecode)
3064e5af60930726d06a58a30bae45bb27ae50aea77jvr		except TypeError:
3074e5af60930726d06a58a30bae45bb27ae50aea77jvr			print bytecode
3084e5af60930726d06a58a30bae45bb27ae50aea77jvr			raise
309f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		self.setBytecode(bytecode)
310f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
3117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def needsDecompilation(self):
3127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.bytecode is not None
3137842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def setProgram(self, program):
3157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.program = program
3167842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.bytecode = None
3177842e56b97ce677b83bdab09cda48bc2d89ac75aJust
318f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	def setBytecode(self, bytecode):
319f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		self.bytecode = bytecode
320f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		self.program = None
321f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
3227842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getToken(self, index,
3237842e56b97ce677b83bdab09cda48bc2d89ac75aJust			len=len, ord=ord, getattr=getattr, type=type, StringType=types.StringType):
3247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is not None:
3257842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if index >= len(self.bytecode):
3267842e56b97ce677b83bdab09cda48bc2d89ac75aJust				return None, 0, 0
3277842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b0 = ord(self.bytecode[index])
3287842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
3297842e56b97ce677b83bdab09cda48bc2d89ac75aJust			code = self.operandEncoding[b0]
3307842e56b97ce677b83bdab09cda48bc2d89ac75aJust			handler = getattr(self, code)
3317842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token, index = handler(b0, self.bytecode, index)
3327842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
3337842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if index >= len(self.program):
3347842e56b97ce677b83bdab09cda48bc2d89ac75aJust				return None, 0, 0
3357842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token = self.program[index]
3367842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
3377842e56b97ce677b83bdab09cda48bc2d89ac75aJust		isOperator = type(token) == StringType
3387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return token, isOperator, index
3397842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getBytes(self, index, nBytes):
3417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is not None:
3427842e56b97ce677b83bdab09cda48bc2d89ac75aJust			newIndex = index + nBytes
3437842e56b97ce677b83bdab09cda48bc2d89ac75aJust			bytes = self.bytecode[index:newIndex]
3447842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = newIndex
3457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
3467842e56b97ce677b83bdab09cda48bc2d89ac75aJust			bytes = self.program[index]
3477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
3487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		assert len(bytes) == nBytes
3497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return bytes, index
3507842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3517842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def do_operator(self, b0, data, index):
3527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if b0 == 12:
3537842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = (b0, ord(data[index]))
3547842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index+1
3557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
3567842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = b0
3577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		operator = self.operators[op]
3587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return operator, index
3597842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3607842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def toXML(self, xmlWriter):
361dab433233bd4024ede9ad27c6c61ea0072c2edafJust		from fontTools.misc.textTools import num2binary
3627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is not None:
3637842e56b97ce677b83bdab09cda48bc2d89ac75aJust			xmlWriter.dumphex(self.bytecode)
3647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
3657842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = 0
3667842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
3677842e56b97ce677b83bdab09cda48bc2d89ac75aJust			while 1:
3687842e56b97ce677b83bdab09cda48bc2d89ac75aJust				token, isOperator, index = self.getToken(index)
3697842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if token is None:
3707842e56b97ce677b83bdab09cda48bc2d89ac75aJust					break
3717842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if isOperator:
3727842e56b97ce677b83bdab09cda48bc2d89ac75aJust					args = map(str, args)
3737842e56b97ce677b83bdab09cda48bc2d89ac75aJust					if token in ('hintmask', 'cntrmask'):
3747842e56b97ce677b83bdab09cda48bc2d89ac75aJust						hintMask, isOperator, index = self.getToken(index)
3757842e56b97ce677b83bdab09cda48bc2d89ac75aJust						bits = []
3767842e56b97ce677b83bdab09cda48bc2d89ac75aJust						for byte in hintMask:
3777842e56b97ce677b83bdab09cda48bc2d89ac75aJust							bits.append(num2binary(ord(byte), 8))
378586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr						hintMask = string.join(bits, "")
3797842e56b97ce677b83bdab09cda48bc2d89ac75aJust						line = string.join(args + [token, hintMask], " ")
3807842e56b97ce677b83bdab09cda48bc2d89ac75aJust					else:
3817842e56b97ce677b83bdab09cda48bc2d89ac75aJust						line = string.join(args + [token], " ")
3827842e56b97ce677b83bdab09cda48bc2d89ac75aJust					xmlWriter.write(line)
3837842e56b97ce677b83bdab09cda48bc2d89ac75aJust					xmlWriter.newline()
3847842e56b97ce677b83bdab09cda48bc2d89ac75aJust					args = []
3857842e56b97ce677b83bdab09cda48bc2d89ac75aJust				else:
3867842e56b97ce677b83bdab09cda48bc2d89ac75aJust					args.append(token)
3874e5af60930726d06a58a30bae45bb27ae50aea77jvr
3884e5af60930726d06a58a30bae45bb27ae50aea77jvr	def fromXML(self, (name, attrs, content)):
389b58176e5ac4d1e0b0e6a6c71c3020f5e85bd4dfejvr		from fontTools.misc.textTools import binary2num, readHex
390b58176e5ac4d1e0b0e6a6c71c3020f5e85bd4dfejvr		if attrs.get("raw"):
391b58176e5ac4d1e0b0e6a6c71c3020f5e85bd4dfejvr			self.setBytecode(readHex(content))
392b58176e5ac4d1e0b0e6a6c71c3020f5e85bd4dfejvr			return
3934e5af60930726d06a58a30bae45bb27ae50aea77jvr		content = "".join(content)
3944e5af60930726d06a58a30bae45bb27ae50aea77jvr		content = content.split()
3954e5af60930726d06a58a30bae45bb27ae50aea77jvr		program = []
3964e5af60930726d06a58a30bae45bb27ae50aea77jvr		end = len(content)
3974e5af60930726d06a58a30bae45bb27ae50aea77jvr		i = 0
3984e5af60930726d06a58a30bae45bb27ae50aea77jvr		while i < end:
3994e5af60930726d06a58a30bae45bb27ae50aea77jvr			token = content[i]
4004e5af60930726d06a58a30bae45bb27ae50aea77jvr			i = i + 1
4014e5af60930726d06a58a30bae45bb27ae50aea77jvr			try:
4024e5af60930726d06a58a30bae45bb27ae50aea77jvr				token = int(token)
4034e5af60930726d06a58a30bae45bb27ae50aea77jvr			except ValueError:
40495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				try:
40595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr					token = float(token)
40695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				except ValueError:
40795c9e9fc11dc028bd1747788f2b417f3936fc59bjvr					program.append(token)
40895c9e9fc11dc028bd1747788f2b417f3936fc59bjvr					if token in ('hintmask', 'cntrmask'):
40995c9e9fc11dc028bd1747788f2b417f3936fc59bjvr						mask = content[i]
41095c9e9fc11dc028bd1747788f2b417f3936fc59bjvr						maskBytes = ""
41195c9e9fc11dc028bd1747788f2b417f3936fc59bjvr						for j in range(0, len(mask), 8):
41295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr							maskBytes = maskBytes + chr(binary2num(mask[j:j+8]))
41395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr						program.append(maskBytes)
41495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr						i = i + 1
41595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				else:
41695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr					program.append(token)
4174e5af60930726d06a58a30bae45bb27ae50aea77jvr			else:
4184e5af60930726d06a58a30bae45bb27ae50aea77jvr				program.append(token)
4194e5af60930726d06a58a30bae45bb27ae50aea77jvr		self.setProgram(program)
4207842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4217842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4227842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1Operators = [
4237842e56b97ce677b83bdab09cda48bc2d89ac75aJust#	opcode     name
4247842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(1,        'hstem'),
4257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(3,        'vstem'),
4267842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(4,        'vmoveto'),
4277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(5,        'rlineto'),
4287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(6,        'hlineto'),
4297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(7,        'vlineto'),
4307842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(8,        'rrcurveto'),
4317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(9,        'closepath'),
4327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(10,       'callsubr'),
4337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(11,       'return'),
4347842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(13,       'hsbw'),
4357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(14,       'endchar'),
4367842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(21,       'rmoveto'),
4377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(22,       'hmoveto'),
4387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(30,       'vhcurveto'),
4397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(31,       'hvcurveto'),
4407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 0),  'dotsection'),
4417842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 1),  'vstem3'),
4427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 2),  'hstem3'),
4437842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 6),  'seac'),
4447842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 7),  'sbw'),
4457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 12), 'div'),
4467842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 16), 'callothersubr'),
4477842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 17), 'pop'),
4487842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 33), 'setcurrentpoint'),
4497842e56b97ce677b83bdab09cda48bc2d89ac75aJust]
4507842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4517842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T1CharString(T2CharString):
4527842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4537842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = t1OperandEncoding
454455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	operators, opcodes = buildOperatorDict(t1Operators)
4557842e56b97ce677b83bdab09cda48bc2d89ac75aJust
456489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, bytecode=None, program=None, subrs=None):
457489d76a340845361def6af9ab7d9152f8e66f417jvr		if program is None:
458489d76a340845361def6af9ab7d9152f8e66f417jvr			program = []
459489d76a340845361def6af9ab7d9152f8e66f417jvr		self.bytecode = bytecode
460489d76a340845361def6af9ab7d9152f8e66f417jvr		self.program = program
461489d76a340845361def6af9ab7d9152f8e66f417jvr		self.subrs = subrs
462489d76a340845361def6af9ab7d9152f8e66f417jvr
46395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	def getIntEncoder(self):
46495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		return encodeIntT1
46595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr
46695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	def getFixedEncoder(self):
46795c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		def encodeFixed(value):
46895c9e9fc11dc028bd1747788f2b417f3936fc59bjvr			raise TypeError("Type 1 charstrings don't support floating point operands")
46995c9e9fc11dc028bd1747788f2b417f3936fc59bjvr
4707842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self):
471b68a700595ff730c29d3d4b7abf92ee287678745Just		if self.program is not None:
4727842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
4737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		program = []
4747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
4757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while 1:
4767842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token, isOperator, index = self.getToken(index)
4777842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if token is None:
4787842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break
4797842e56b97ce677b83bdab09cda48bc2d89ac75aJust			program.append(token)
4807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.setProgram(program)
4817842e56b97ce677b83bdab09cda48bc2d89ac75aJust
482489d76a340845361def6af9ab7d9152f8e66f417jvr	def draw(self, pen):
483489d76a340845361def6af9ab7d9152f8e66f417jvr		extractor = T1OutlineExtractor(pen, self.subrs)
484489d76a340845361def6af9ab7d9152f8e66f417jvr		extractor.execute(self)
485489d76a340845361def6af9ab7d9152f8e66f417jvr		self.width = extractor.width
486489d76a340845361def6af9ab7d9152f8e66f417jvr
4877842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4887842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass SimpleT2Decompiler:
4897842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4907842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __init__(self, localSubrs, globalSubrs):
4917842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.localSubrs = localSubrs
4927842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.localBias = calcSubrBias(localSubrs)
4937842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.globalSubrs = globalSubrs
4947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.globalBias = calcSubrBias(globalSubrs)
4957842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.reset()
4967842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
4987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.callingStack = []
4997842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.operandStack = []
5007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = 0
5017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintMaskBytes = 0
5027842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def execute(self, charString):
5047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.callingStack.append(charString)
5057842e56b97ce677b83bdab09cda48bc2d89ac75aJust		needsDecompilation = charString.needsDecompilation()
5067842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if needsDecompilation:
5077842e56b97ce677b83bdab09cda48bc2d89ac75aJust			program = []
5087842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pushToProgram = program.append
5097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
5107842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pushToProgram = lambda x: None
5117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pushToStack = self.operandStack.append
5127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
5137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while 1:
5147842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token, isOperator, index = charString.getToken(index)
5157842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if token is None:
5167842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break  # we're done!
5177842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pushToProgram(token)
5187842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if isOperator:
5197842e56b97ce677b83bdab09cda48bc2d89ac75aJust				handlerName = "op_" + token
5207842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if hasattr(self, handlerName):
5217842e56b97ce677b83bdab09cda48bc2d89ac75aJust					handler = getattr(self, handlerName)
5227842e56b97ce677b83bdab09cda48bc2d89ac75aJust					rv = handler(index)
5237842e56b97ce677b83bdab09cda48bc2d89ac75aJust					if rv:
5247842e56b97ce677b83bdab09cda48bc2d89ac75aJust						hintMaskBytes, index = rv
5257842e56b97ce677b83bdab09cda48bc2d89ac75aJust						pushToProgram(hintMaskBytes)
5267842e56b97ce677b83bdab09cda48bc2d89ac75aJust				else:
5277842e56b97ce677b83bdab09cda48bc2d89ac75aJust					self.popall()
5287842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
5297842e56b97ce677b83bdab09cda48bc2d89ac75aJust				pushToStack(token)
5307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if needsDecompilation:
5319920ad5286b6e61d67f07f908107d65f7fa817acjvr			assert program, "illegal CharString: decompiled to empty program"
5329920ad5286b6e61d67f07f908107d65f7fa817acjvr			assert program[-1] in ("endchar", "return", "callsubr", "callgsubr",
5339920ad5286b6e61d67f07f908107d65f7fa817acjvr					"seac"), "illegal CharString"
5347842e56b97ce677b83bdab09cda48bc2d89ac75aJust			charString.setProgram(program)
5357842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.callingStack[-1]
5367842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def pop(self):
5387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value = self.operandStack[-1]
5397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.operandStack[-1]
5407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value
5417842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popall(self):
5437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack = self.operandStack[:]
5447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.operandStack[:] = []
5457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return stack
5467842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5477842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def push(self, value):
5487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.operandStack.append(value)
5497842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5507842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_return(self, index):
5517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.operandStack:
5527842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pass
5537842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5547842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
5557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pass
5567099f4c0f9fbaf1a5c811113fdfd2404dee04361jvr
5577099f4c0f9fbaf1a5c811113fdfd2404dee04361jvr	def op_ignore(self, index):
5587099f4c0f9fbaf1a5c811113fdfd2404dee04361jvr		pass
5597099f4c0f9fbaf1a5c811113fdfd2404dee04361jvr
5607842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callsubr(self, index):
5617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
5627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.localSubrs[subrIndex+self.localBias]
5637842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
5647842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5657842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callgsubr(self, index):
5667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
5677842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.globalSubrs[subrIndex+self.globalBias]
5687842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
5697842e56b97ce677b83bdab09cda48bc2d89ac75aJust
570586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def op_hstem(self, index):
571586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.countHints()
572586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def op_vstem(self, index):
573586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.countHints()
5747842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hstemhm(self, index):
5757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.countHints()
576586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def op_vstemhm(self, index):
577586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.countHints()
5787842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5797842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hintmask(self, index):
5807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if not self.hintMaskBytes:
5817842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.countHints()
5827842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.hintMaskBytes = (self.hintCount + 7) / 8
5837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		hintMaskBytes, index = self.callingStack[-1].getBytes(index, self.hintMaskBytes)
5847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return hintMaskBytes, index
5857842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5867842e56b97ce677b83bdab09cda48bc2d89ac75aJust	op_cntrmask = op_hintmask
5877842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5887842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def countHints(self):
5897842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
5907842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = self.hintCount + len(args) / 2
5917842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5927842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5937842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T2OutlineExtractor(SimpleT2Decompiler):
5947842e56b97ce677b83bdab09cda48bc2d89ac75aJust
595489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, pen, localSubrs, globalSubrs, nominalWidthX, defaultWidthX):
5967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		SimpleT2Decompiler.__init__(self, localSubrs, globalSubrs)
597489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen = pen
5987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.nominalWidthX = nominalWidthX
5997842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.defaultWidthX = defaultWidthX
6007842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
6027842e56b97ce677b83bdab09cda48bc2d89ac75aJust		SimpleT2Decompiler.reset(self)
6037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hints = []
6047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.gotWidth = 0
6057842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = 0
606489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = (0, 0)
607489d76a340845361def6af9ab7d9152f8e66f417jvr		self.sawMoveTo = 0
6087842e56b97ce677b83bdab09cda48bc2d89ac75aJust
609489d76a340845361def6af9ab7d9152f8e66f417jvr	def _nextPoint(self, point):
610489d76a340845361def6af9ab7d9152f8e66f417jvr		x, y = self.currentPoint
611489d76a340845361def6af9ab7d9152f8e66f417jvr		point = x + point[0], y + point[1]
612489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = point
613489d76a340845361def6af9ab7d9152f8e66f417jvr		return point
6147842e56b97ce677b83bdab09cda48bc2d89ac75aJust
615489d76a340845361def6af9ab7d9152f8e66f417jvr	def rMoveTo(self, point):
616489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.moveTo(self._nextPoint(point))
617489d76a340845361def6af9ab7d9152f8e66f417jvr		self.sawMoveTo = 1
618489d76a340845361def6af9ab7d9152f8e66f417jvr
619489d76a340845361def6af9ab7d9152f8e66f417jvr	def rLineTo(self, point):
620489d76a340845361def6af9ab7d9152f8e66f417jvr		if not self.sawMoveTo:
621489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rMoveTo((0, 0))
622489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.lineTo(self._nextPoint(point))
623489d76a340845361def6af9ab7d9152f8e66f417jvr
624489d76a340845361def6af9ab7d9152f8e66f417jvr	def rCurveTo(self, pt1, pt2, pt3):
625489d76a340845361def6af9ab7d9152f8e66f417jvr		if not self.sawMoveTo:
626489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rMoveTo((0, 0))
627489d76a340845361def6af9ab7d9152f8e66f417jvr		nextPoint = self._nextPoint
628489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.curveTo(nextPoint(pt1), nextPoint(pt2), nextPoint(pt3))
6297842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6307842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def closePath(self):
631489d76a340845361def6af9ab7d9152f8e66f417jvr		if self.sawMoveTo:
632489d76a340845361def6af9ab7d9152f8e66f417jvr			self.pen.closePath()
633489d76a340845361def6af9ab7d9152f8e66f417jvr		self.sawMoveTo = 0
6347842e56b97ce677b83bdab09cda48bc2d89ac75aJust
635d3ee2d4319742ec61cb299665ccba66c139e4834jvr	def endPath(self):
636d3ee2d4319742ec61cb299665ccba66c139e4834jvr		# In T2 there are no open paths, so always do a closePath when
637d3ee2d4319742ec61cb299665ccba66c139e4834jvr		# finishing a sub path.
638d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.closePath()
639d3ee2d4319742ec61cb299665ccba66c139e4834jvr
6407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popallWidth(self, evenOdd=0):
6417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
6427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if not self.gotWidth:
6437842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if evenOdd ^ (len(args) % 2):
6447842e56b97ce677b83bdab09cda48bc2d89ac75aJust				self.width = self.nominalWidthX + args[0]
6457842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = args[1:]
6467842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
6477842e56b97ce677b83bdab09cda48bc2d89ac75aJust				self.width = self.defaultWidthX
6487842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.gotWidth = 1
6497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
6507842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6517842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def countHints(self):
6527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popallWidth()
6537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = self.hintCount + len(args) / 2
6547842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6557842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6567842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# hint operators
6577842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
658586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_hstem(self, index):
659586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
660586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_vstem(self, index):
661586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
662586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_hstemhm(self, index):
663586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
664586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_vstemhm(self, index):
665586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
6667842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#def op_hintmask(self, index):
6677842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#	self.countHints()
6687842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#def op_cntrmask(self, index):
6697842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#	self.countHints()
6707842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6717842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6727842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, moveto
6737842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6747842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rmoveto(self, index):
675d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
676489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo(self.popallWidth())
6777842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hmoveto(self, index):
678d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
679489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((self.popallWidth(1)[0], 0))
6807842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vmoveto(self, index):
681d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
682489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((0, self.popallWidth(1)[0]))
6837842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
684d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
685382df6c42a7a6aecb690e07c6338e19f038f0543jvr		args = self.popallWidth()
686382df6c42a7a6aecb690e07c6338e19f038f0543jvr		if args:
687382df6c42a7a6aecb690e07c6338e19f038f0543jvr			from fontTools.encodings.StandardEncoding import StandardEncoding
688382df6c42a7a6aecb690e07c6338e19f038f0543jvr			# endchar can do seac accent bulding; The T2 spec says it's deprecated,
689382df6c42a7a6aecb690e07c6338e19f038f0543jvr			# but recent software that shall remain nameless does output it.
690382df6c42a7a6aecb690e07c6338e19f038f0543jvr			adx, ady, bchar, achar = args
691382df6c42a7a6aecb690e07c6338e19f038f0543jvr			baseGlyph = StandardEncoding[bchar]
692382df6c42a7a6aecb690e07c6338e19f038f0543jvr			self.pen.addComponent(baseGlyph, (1, 0, 0, 1, 0, 0))
693382df6c42a7a6aecb690e07c6338e19f038f0543jvr			accentGlyph = StandardEncoding[achar]
694382df6c42a7a6aecb690e07c6338e19f038f0543jvr			self.pen.addComponent(accentGlyph, (1, 0, 0, 1, adx, ady))
6957842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, lines
6987842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rlineto(self, index):
7007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 2):
7027842e56b97ce677b83bdab09cda48bc2d89ac75aJust			point = args[i:i+2]
703489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rLineTo(point)
7047842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hlineto(self, index):
7067842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.alternatingLineto(1)
7077842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vlineto(self, index):
7087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.alternatingLineto(0)
7097842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, curves
7127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7137842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rrcurveto(self, index):
7147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya dxb dyb dxc dyc}+ rrcurveto"""
7157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7167842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 6):
7177842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxa, dya, dxb, dyb, dxc, dyc, = args[i:i+6]
718489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dxa, dya), (dxb, dyb), (dxc, dyc))
7197842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rcurveline(self, index):
7217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya dxb dyb dxc dyc}+ dxd dyd rcurveline"""
7227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args)-2, 6):
7247842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxb, dyb, dxc, dyc, dxd, dyd = args[i:i+6]
725489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dxb, dyb), (dxc, dyc), (dxd, dyd))
726489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rLineTo(args[-2:])
7277842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rlinecurve(self, index):
7297842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya}+ dxb dyb dxc dyc dxd dyd rlinecurve"""
7307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lineArgs = args[:-6]
7327842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(lineArgs), 2):
733489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rLineTo(lineArgs[i:i+2])
7347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dxb, dyb, dxc, dyc, dxd, dyd = args[-6:]
735489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rCurveTo((dxb, dyb), (dxc, dyc), (dxd, dyd))
7367842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vvcurveto(self, index):
7387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"dx1? {dya dxb dyb dyc}+ vvcurveto"
7397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) % 2:
7417842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = args[0]
7427842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = args[1:]
7437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
7447842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = 0
7457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 4):
7467842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dya, dxb, dyb, dyc = args[i:i+4]
747489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dx1, dya), (dxb, dyb), (0, dyc))
7487842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = 0
7497842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7507842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hhcurveto(self, index):
7517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dy1? {dxa dxb dyb dxc}+ hhcurveto"""
7527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) % 2:
7547842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = args[0]
7557842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = args[1:]
7567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
7577842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = 0
7587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 4):
7597842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxa, dxb, dyb, dxc = args[i:i+4]
760489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dxa, dy1), (dxb, dyb), (dxc, 0))
7617842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = 0
7627842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7637842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vhcurveto(self, index):
7647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? vhcurveto (30)
7657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		{dya dxb dyb dxc dxd dxe dye dyf}+ dxf? vhcurveto
7667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""
7677842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7687842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while args:
7697842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = self.vcurveto(args)
7707842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if args:
7717842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = self.hcurveto(args)
7727842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7737842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hvcurveto(self, index):
7747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf?
7757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		{dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?
7767842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""
7777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while args:
7797842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = self.hcurveto(args)
7807842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if args:
7817842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = self.vcurveto(args)
7827842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7837842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7847842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, flex
7857842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7867842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hflex(self, index):
7878b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx1, dx2, dy2, dx3, dx4, dx5, dx6 = self.popall()
788d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr		dy1 = dy3 = dy4 = dy6 = 0
789d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr		dy5 = -dy2
7908b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx1, dy1), (dx2, dy2), (dx3, dy3))
7918b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx4, dy4), (dx5, dy5), (dx6, dy6))
7927842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_flex(self, index):
7938b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4, dx5, dy5, dx6, dy6, fd = self.popall()
7948b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx1, dy1), (dx2, dy2), (dx3, dy3))
7958b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx4, dy4), (dx5, dy5), (dx6, dy6))
7967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hflex1(self, index):
7978b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx1, dy1, dx2, dy2, dx3, dx4, dx5, dy5, dx6 = self.popall()
798d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr		dy3 = dy4 = 0
799d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr		dy6 = -(dy1 + dy2 + dy3 + dy4 + dy5)
800d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr
8018b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx1, dy1), (dx2, dy2), (dx3, dy3))
8028b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx4, dy4), (dx5, dy5), (dx6, dy6))
8037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_flex1(self, index):
8048b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4, dx5, dy5, d6 = self.popall()
8058b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx = dx1 + dx2 + dx3 + dx4 + dx5
8068b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dy = dy1 + dy2 + dy3 + dy4 + dy5
8078b8b44904e116287ca0eb587f9c5b21296fb3123jvr		if abs(dx) > abs(dy):
8088b8b44904e116287ca0eb587f9c5b21296fb3123jvr			dx6 = d6
809d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr			dy6 = -dy
8108b8b44904e116287ca0eb587f9c5b21296fb3123jvr		else:
811d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr			dx6 = -dx
8128b8b44904e116287ca0eb587f9c5b21296fb3123jvr			dy6 = d6
8138b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx1, dy1), (dx2, dy2), (dx3, dy3))
8148b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx4, dy4), (dx5, dy5), (dx6, dy6))
8157842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8177842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# MultipleMaster. Well...
8187842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_blend(self, index):
8208b8b44904e116287ca0eb587f9c5b21296fb3123jvr		args = self.popall()
8217842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8227842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# misc
8237842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_and(self, index):
8248b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_or(self, index):
8268b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_not(self, index):
8288b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_store(self, index):
8308b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_abs(self, index):
8328b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_add(self, index):
8348b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sub(self, index):
8368b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_div(self, index):
8387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		num2 = self.pop()
8397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		num1 = self.pop()
8407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		d1 = num1/num2
8417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		d2 = float(num1)/num2
8427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if d1 == d2:
8437842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(d1)
8447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
8457842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(d2)
8467842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_load(self, index):
8478b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8487842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_neg(self, index):
8498b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8507842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_eq(self, index):
8518b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8527842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_drop(self, index):
8538b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8547842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_put(self, index):
8558b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8567842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_get(self, index):
8578b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8587842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_ifelse(self, index):
8598b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8607842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_random(self, index):
8618b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8627842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_mul(self, index):
8638b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8647842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sqrt(self, index):
8658b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8667842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_dup(self, index):
8678b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8687842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_exch(self, index):
8698b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8707842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_index(self, index):
8718b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8727842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_roll(self, index):
8738b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8747842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8757842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8767842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# miscelaneous helpers
8777842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8787842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def alternatingLineto(self, isHorizontal):
8797842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
8807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for arg in args:
8817842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if isHorizontal:
8827842e56b97ce677b83bdab09cda48bc2d89ac75aJust				point = (arg, 0)
8837842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
8847842e56b97ce677b83bdab09cda48bc2d89ac75aJust				point = (0, arg)
885489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rLineTo(point)
8867842e56b97ce677b83bdab09cda48bc2d89ac75aJust			isHorizontal = not isHorizontal
8877842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8887842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def vcurveto(self, args):
8897842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dya, dxb, dyb, dxc = args[:4]
8907842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = args[4:]
8917842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) == 1:
8927842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dyc = args[0]
8937842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
8947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
8957842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dyc = 0
896489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rCurveTo((0, dya), (dxb, dyb), (dxc, dyc))
8977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
8987842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def hcurveto(self, args):
9007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dxa, dxb, dyb, dyc = args[:4]
9017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = args[4:]
9027842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) == 1:
9037842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxc = args[0]
9047842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
9057842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
9067842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxc = 0
907489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rCurveTo((dxa, 0), (dxb, dyb), (dxc, dyc))
9087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
9097842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9107842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9117842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T1OutlineExtractor(T2OutlineExtractor):
9127842e56b97ce677b83bdab09cda48bc2d89ac75aJust
913489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, pen, subrs):
914489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen = pen
9157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.subrs = subrs
9167842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.reset()
9177842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9187842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
9197842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.flexing = 0
9207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = 0
9217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.sbx = 0
9227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		T2OutlineExtractor.reset(self)
9237842e56b97ce677b83bdab09cda48bc2d89ac75aJust
924d3ee2d4319742ec61cb299665ccba66c139e4834jvr	def endPath(self):
925d3ee2d4319742ec61cb299665ccba66c139e4834jvr		if self.sawMoveTo:
926d3ee2d4319742ec61cb299665ccba66c139e4834jvr			self.pen.endPath()
927d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.sawMoveTo = 0
928d3ee2d4319742ec61cb299665ccba66c139e4834jvr
9297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popallWidth(self, evenOdd=0):
9307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.popall()
9317842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def exch(self):
9337842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack = self.operandStack
9347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack[-1], stack[-2] = stack[-2], stack[-1]
9357842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9367842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
9377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors
9387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
9397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rmoveto(self, index):
940d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
9417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
9427842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
943489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo(self.popall())
9447842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hmoveto(self, index):
9457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
9467842e56b97ce677b83bdab09cda48bc2d89ac75aJust			# We must add a parameter to the stack if we are flexing
9477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(0)
9487842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
949d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
950489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((self.popall()[0], 0))
9517842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vmoveto(self, index):
9527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
9537842e56b97ce677b83bdab09cda48bc2d89ac75aJust			# We must add a parameter to the stack if we are flexing
9547842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(0)
9557842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.exch()
9567842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
957d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
958489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((0, self.popall()[0]))
9597842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_closepath(self, index):
9607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
9617842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_setcurrentpoint(self, index):
9627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
9637842e56b97ce677b83bdab09cda48bc2d89ac75aJust		x, y = args
964489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = x, y
9657842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9667842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
967d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
9687842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9697842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hsbw(self, index):
9707842e56b97ce677b83bdab09cda48bc2d89ac75aJust		sbx, wx = self.popall()
9717842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = wx
9727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.sbx = sbx
973489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = sbx, self.currentPoint[1]
9747842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sbw(self, index):
9757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
9767842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9777842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
9787842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callsubr(self, index):
9797842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
9807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.subrs[subrIndex]
9817842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
9827842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callothersubr(self, index):
9837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
9847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		nArgs = self.pop()
9857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		#print nArgs, subrIndex, "callothersubr"
9867842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if subrIndex == 0 and nArgs == 3:
9877842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.doFlex()
9887842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.flexing = 0
9897842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif subrIndex == 1 and nArgs == 0:
9907842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.flexing = 1
9917842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# ignore...
9927842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_pop(self, index):
9937842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pass  # ignore...
9947842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def doFlex(self):
9967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		finaly = self.pop()
9977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		finalx = self.pop()
9987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.pop()	# flex height is unused
9997842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p3y = self.pop()
10017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p3x = self.pop()
10027842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp4y = self.pop()
10037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp4x = self.pop()
10047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp3y = self.pop()
10057842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp3x = self.pop()
10067842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p2y = self.pop()
10077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p2x = self.pop()
10087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp2y = self.pop()
10097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp2x = self.pop()
10107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp1y = self.pop()
10117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp1x = self.pop()
10127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		rpy = self.pop()
10137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		rpx = self.pop()
10147842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# call rrcurveto
10167842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp1x+rpx)
10177842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp1y+rpy)
10187842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp2x)
10197842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp2y)
10207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p2x)
10217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p2y)
10227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.op_rrcurveto(None)
10237842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# call rrcurveto
10257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp3x)
10267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp3y)
10277842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp4x)
10287842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp4y)
10297842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p3x)
10307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p3y)
10317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.op_rrcurveto(None)
10327842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10337842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# Push back final coords so subr 0 can find them
10347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(finalx)
10357842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(finaly)
10367842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_dotsection(self, index):
10387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
10397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hstem3(self, index):
10407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
10417842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_seac(self, index):
10427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"asb adx ady bchar achar seac"
1043489d76a340845361def6af9ab7d9152f8e66f417jvr		from fontTools.encodings.StandardEncoding import StandardEncoding
1044489d76a340845361def6af9ab7d9152f8e66f417jvr		asb, adx, ady, bchar, achar = self.popall()
1045489d76a340845361def6af9ab7d9152f8e66f417jvr		baseGlyph = StandardEncoding[bchar]
1046489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.addComponent(baseGlyph, (1, 0, 0, 1, 0, 0))
1047489d76a340845361def6af9ab7d9152f8e66f417jvr		accentGlyph = StandardEncoding[achar]
1048489d76a340845361def6af9ab7d9152f8e66f417jvr		adx = adx + self.sbx - asb  # seac weirdness
1049489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.addComponent(accentGlyph, (1, 0, 0, 1, adx, ady))
10507842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vstem3(self, index):
10517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
10527842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10537842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1054f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrclass DictDecompiler(ByteCodeBase):
10557842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10567842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = cffDictOperandEncoding
10577842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10587842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __init__(self, strings):
10597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.stack = []
10607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.strings = strings
10617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.dict = {}
10627842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10637842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getDict(self):
10647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		assert len(self.stack) == 0, "non-empty stack"
10657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.dict
10667842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10677842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self, data):
10687842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
10697842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lenData = len(data)
10707842e56b97ce677b83bdab09cda48bc2d89ac75aJust		push = self.stack.append
10717842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while index < lenData:
10727842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b0 = ord(data[index])
10737842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
10747842e56b97ce677b83bdab09cda48bc2d89ac75aJust			code = self.operandEncoding[b0]
10757842e56b97ce677b83bdab09cda48bc2d89ac75aJust			handler = getattr(self, code)
10767842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value, index = handler(b0, data, index)
10777842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if value is not None:
10787842e56b97ce677b83bdab09cda48bc2d89ac75aJust				push(value)
10797842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10807842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def pop(self):
10817842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value = self.stack[-1]
10827842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.stack[-1]
10837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value
10847842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10857842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popall(self):
10867842e56b97ce677b83bdab09cda48bc2d89ac75aJust		all = self.stack[:]
10877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.stack[:]
10887842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return all
10897842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10907842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def do_operator(self, b0, data, index):
10917842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if b0 == 12:
10927842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = (b0, ord(data[index]))
10937842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index+1
10947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
10957842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = b0
10967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		operator, argType = self.operators[op]
10977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.handle_operator(operator, argType)
10987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return None, index
10997842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11007842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def handle_operator(self, operator, argType):
11017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if type(argType) == type(()):
11027842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = ()
1103bf2f402913a2706dfa92190e60cba7acbf01c9d7jvr			for i in range(len(argType)-1, -1, -1):
1104bf2f402913a2706dfa92190e60cba7acbf01c9d7jvr				arg = argType[i]
11057842e56b97ce677b83bdab09cda48bc2d89ac75aJust				arghandler = getattr(self, "arg_" + arg)
11067842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value = (arghandler(operator),) + value
11077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
11087842e56b97ce677b83bdab09cda48bc2d89ac75aJust			arghandler = getattr(self, "arg_" + argType)
11097842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = arghandler(operator)
11107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.dict[operator] = value
11117842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_number(self, name):
11137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.pop()
11147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_SID(self, name):
11157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.strings[self.pop()]
11167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_array(self, name):
11177842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.popall()
1118dc18128aa9b3f6b98a623c294ac615195159025ejvr	def arg_delta(self, name):
1119dc18128aa9b3f6b98a623c294ac615195159025ejvr		out = []
1120dc18128aa9b3f6b98a623c294ac615195159025ejvr		current = 0
1121dc18128aa9b3f6b98a623c294ac615195159025ejvr		for v in self.popall():
11226f03a58f59fb20662602e3d4bb153d7db2f778d3jvr			current = current + v
1123dc18128aa9b3f6b98a623c294ac615195159025ejvr			out.append(current)
1124dc18128aa9b3f6b98a623c294ac615195159025ejvr		return out
11257842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11267842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11277842e56b97ce677b83bdab09cda48bc2d89ac75aJustdef calcSubrBias(subrs):
11287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	nSubrs = len(subrs)
11297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	if nSubrs < 1240:
11307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 107
11317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	elif nSubrs < 33900:
11327842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 1131
11337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	else:
11347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 32768
11357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	return bias
1136