psCharStrings.py revision 14fb031125b773f0a15eb19be4f02ed8540b2db6
17842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""psCharStrings.py -- module implementing various kinds of CharStrings:
27842e56b97ce677b83bdab09cda48bc2d89ac75aJustCFF dictionary data and Type1/Type2 CharStrings.
37842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
47842e56b97ce677b83bdab09cda48bc2d89ac75aJust
57842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport struct
67842e56b97ce677b83bdab09cda48bc2d89ac75aJust
77842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8455af6592bffbd6f2fc9f56fbfe083022a8353d4jvrDEBUG = 0
9455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr
10455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr
117842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1OperandEncoding = [None] * 256
127842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1OperandEncoding[0:32] = (32) * ["do_operator"]
137842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1OperandEncoding[32:247] = (247 - 32) * ["read_byte"]
147842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1OperandEncoding[247:251] = (251 - 247) * ["read_smallInt1"]
157842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1OperandEncoding[251:255] = (255 - 251) * ["read_smallInt2"]
167842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1OperandEncoding[255] = "read_longInt"
177842e56b97ce677b83bdab09cda48bc2d89ac75aJustassert len(t1OperandEncoding) == 256
187842e56b97ce677b83bdab09cda48bc2d89ac75aJust
197842e56b97ce677b83bdab09cda48bc2d89ac75aJustt2OperandEncoding = t1OperandEncoding[:]
207842e56b97ce677b83bdab09cda48bc2d89ac75aJustt2OperandEncoding[28] = "read_shortInt"
2195c9e9fc11dc028bd1747788f2b417f3936fc59bjvrt2OperandEncoding[255] = "read_fixed1616"
227842e56b97ce677b83bdab09cda48bc2d89ac75aJust
237842e56b97ce677b83bdab09cda48bc2d89ac75aJustcffDictOperandEncoding = t2OperandEncoding[:]
247842e56b97ce677b83bdab09cda48bc2d89ac75aJustcffDictOperandEncoding[29] = "read_longInt"
257842e56b97ce677b83bdab09cda48bc2d89ac75aJustcffDictOperandEncoding[30] = "read_realNumber"
267842e56b97ce677b83bdab09cda48bc2d89ac75aJustcffDictOperandEncoding[255] = "reserved"
277842e56b97ce677b83bdab09cda48bc2d89ac75aJust
287842e56b97ce677b83bdab09cda48bc2d89ac75aJust
297842e56b97ce677b83bdab09cda48bc2d89ac75aJustrealNibbles = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		'.', 'E', 'E-', None, '-']
31f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrrealNibblesDict = {}
32f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrfor _i in range(len(realNibbles)):
33f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	realNibblesDict[realNibbles[_i]] = _i
347842e56b97ce677b83bdab09cda48bc2d89ac75aJust
357842e56b97ce677b83bdab09cda48bc2d89ac75aJust
36f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrclass ByteCodeBase:
377842e56b97ce677b83bdab09cda48bc2d89ac75aJust
387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_byte(self, b0, data, index):
397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return b0 - 139, index
407842e56b97ce677b83bdab09cda48bc2d89ac75aJust
417842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_smallInt1(self, b0, data, index):
427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		b1 = ord(data[index])
437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return (b0-247)*256 + b1 + 108, index+1
447842e56b97ce677b83bdab09cda48bc2d89ac75aJust
457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_smallInt2(self, b0, data, index):
467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		b1 = ord(data[index])
477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return -(b0-251)*256 - b1 - 108, index+1
487842e56b97ce677b83bdab09cda48bc2d89ac75aJust
497842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_shortInt(self, b0, data, index):
507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bin = data[index] + data[index+1]
517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value, = struct.unpack(">h", bin)
527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value, index+2
537842e56b97ce677b83bdab09cda48bc2d89ac75aJust
547842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_longInt(self, b0, data, index):
557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bin = data[index] + data[index+1] + data[index+2] + data[index+3]
567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value, = struct.unpack(">l", bin)
577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value, index+4
587842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5995c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	def read_fixed1616(self, b0, data, index):
6095c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		bin = data[index] + data[index+1] + data[index+2] + data[index+3]
6195c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		value, = struct.unpack(">l", bin)
6295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		return value / 65536.0, index+4
6395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr
647842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def read_realNumber(self, b0, data, index):
657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		number = ''
66ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod		while True:
677842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b = ord(data[index])
687842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
697842e56b97ce677b83bdab09cda48bc2d89ac75aJust			nibble0 = (b & 0xf0) >> 4
707842e56b97ce677b83bdab09cda48bc2d89ac75aJust			nibble1 = b & 0x0f
717842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if nibble0 == 0xf:
727842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break
737842e56b97ce677b83bdab09cda48bc2d89ac75aJust			number = number + realNibbles[nibble0]
747842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if nibble1 == 0xf:
757842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break
767842e56b97ce677b83bdab09cda48bc2d89ac75aJust			number = number + realNibbles[nibble1]
77455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		return float(number), index
787842e56b97ce677b83bdab09cda48bc2d89ac75aJust
797842e56b97ce677b83bdab09cda48bc2d89ac75aJust
80dbc2c173b35360386c907a3c70cb931ae4c3fac9jvrdef buildOperatorDict(operatorList):
81455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	oper = {}
82455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	opc = {}
837842e56b97ce677b83bdab09cda48bc2d89ac75aJust	for item in operatorList:
847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(item) == 2:
85455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			oper[item[0]] = item[1]
86455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		else:
87455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			oper[item[0]] = item[1:]
88002c32fd0d869e280783777ec57916a9267aaea5Behdad Esfahbod		if isinstance(item[0], tuple):
89455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			opc[item[1]] = item[0]
907842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
91455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			opc[item[1]] = (item[0],)
92455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	return oper, opc
937842e56b97ce677b83bdab09cda48bc2d89ac75aJust
947842e56b97ce677b83bdab09cda48bc2d89ac75aJust
957842e56b97ce677b83bdab09cda48bc2d89ac75aJustt2Operators = [
967842e56b97ce677b83bdab09cda48bc2d89ac75aJust#	opcode     name
977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(1,        'hstem'),
987842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(3,        'vstem'),
997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(4,        'vmoveto'),
1007842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(5,        'rlineto'),
1017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(6,        'hlineto'),
1027842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(7,        'vlineto'),
1037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(8,        'rrcurveto'),
1047842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(10,       'callsubr'),
1057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(11,       'return'),
1067842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(14,       'endchar'),
1077842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(16,       'blend'),
1087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(18,       'hstemhm'),
1097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(19,       'hintmask'),
1107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(20,       'cntrmask'),
1117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(21,       'rmoveto'),
1127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(22,       'hmoveto'),
1137842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(23,       'vstemhm'),
1147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(24,       'rcurveline'),
1157842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(25,       'rlinecurve'),
1167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(26,       'vvcurveto'),
1177842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(27,       'hhcurveto'),
1187842e56b97ce677b83bdab09cda48bc2d89ac75aJust#	(28,       'shortint'),  # not really an operator
1197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(29,       'callgsubr'),
1207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(30,       'vhcurveto'),
1217842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(31,       'hvcurveto'),
1227099f4c0f9fbaf1a5c811113fdfd2404dee04361jvr	((12, 0),  'ignore'),  # dotsection. Yes, there a few very early OTF/CFF
1237099f4c0f9fbaf1a5c811113fdfd2404dee04361jvr	                   # fonts with this deprecated operator. Just ignore it.
1247842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 3),  'and'),
1257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 4),  'or'),
1267842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 5),  'not'),
1277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 8),  'store'),
1287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 9),  'abs'),
1297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 10), 'add'),
1307842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 11), 'sub'),
1317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 12), 'div'),
1327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 13), 'load'),
1337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 14), 'neg'),
1347842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 15), 'eq'),
1357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 18), 'drop'),
1367842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 20), 'put'),
1377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 21), 'get'),
1387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 22), 'ifelse'),
1397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 23), 'random'),
1407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 24), 'mul'),
1417842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 26), 'sqrt'),
1427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 27), 'dup'),
1437842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 28), 'exch'),
1447842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 29), 'index'),
1457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 30), 'roll'),
1467842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 34), 'hflex'),
1477842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 35), 'flex'),
1487842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 36), 'hflex1'),
1497842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 37), 'flex1'),
1507842e56b97ce677b83bdab09cda48bc2d89ac75aJust]
1517842e56b97ce677b83bdab09cda48bc2d89ac75aJust
152f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
153f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrdef getIntEncoder(format):
154f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	if format == "cff":
155f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		fourByteOp = chr(29)
156f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	elif format == "t1":
15795c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		fourByteOp = chr(255)
158f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	else:
159f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		assert format == "t2"
16095c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		fourByteOp = None
161f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
16295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	def encodeInt(value, fourByteOp=fourByteOp, chr=chr,
16395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr			pack=struct.pack, unpack=struct.unpack):
164f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		if -107 <= value <= 107:
165f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = chr(value + 139)
166f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		elif 108 <= value <= 1131:
167f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			value = value - 108
168f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = chr((value >> 8) + 247) + chr(value & 0xFF)
169f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		elif -1131 <= value <= -108:
170f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			value = -value - 108
171f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = chr((value >> 8) + 251) + chr(value & 0xFF)
17295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		elif fourByteOp is None:
17395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr			# T2 only supports 2 byte ints
17495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr			if -32768 <= value <= 32767:
17595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				code = chr(28) + pack(">h", value)
17695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr			else:
17795c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# Backwards compatible hack: due to a previous bug in FontTools,
17895c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# 16.16 fixed numbers were written out as 4-byte ints. When
17995c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# these numbers were small, they were wrongly written back as
18095c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# small ints instead of 4-byte ints, breaking round-tripping.
18195c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# This here workaround doesn't do it any better, since we can't
18295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# distinguish anymore between small ints that were supposed to
18395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# be small fixed numbers and small ints that were just small
18495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				# ints. Hence the warning.
18595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				import sys
18695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				sys.stderr.write("Warning: 4-byte T2 number got passed to the "
18795c9e9fc11dc028bd1747788f2b417f3936fc59bjvr					"IntType handler. This should happen only when reading in "
18895c9e9fc11dc028bd1747788f2b417f3936fc59bjvr					"old XML files.\n")
18995c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				code = chr(255) + pack(">l", value)
190f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		else:
191f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			code = fourByteOp + pack(">l", value)
192f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		return code
193f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
194f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	return encodeInt
195f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
196f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
197f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrencodeIntCFF = getIntEncoder("cff")
198f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrencodeIntT1 = getIntEncoder("t1")
199f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrencodeIntT2 = getIntEncoder("t2")
200f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
20195c9e9fc11dc028bd1747788f2b417f3936fc59bjvrdef encodeFixed(f, pack=struct.pack):
20295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	# For T2 only
20395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	return "\xff" + pack(">l", int(round(f * 65536)))
20495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr
205f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrdef encodeFloat(f):
20695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	# For CFF only, used in cffLib
207f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	s = str(f).upper()
208f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	if s[:2] == "0.":
209f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		s = s[1:]
210f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	elif s[:3] == "-0.":
211f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		s = "-" + s[2:]
212f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	nibbles = []
213f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	while s:
214f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		c = s[0]
215f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		s = s[1:]
216f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		if c == "E" and s[:1] == "-":
217f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			s = s[1:]
218f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr			c = "E-"
219f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		nibbles.append(realNibblesDict[c])
220f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	nibbles.append(0xf)
221f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	if len(nibbles) % 2:
222f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		nibbles.append(0xf)
223f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	d = chr(30)
224f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	for i in range(0, len(nibbles), 2):
225f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		d = d + chr(nibbles[i] << 4 | nibbles[i+1])
226f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	return d
227f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
228f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
2294e5af60930726d06a58a30bae45bb27ae50aea77jvrclass CharStringCompileError(Exception): pass
2304e5af60930726d06a58a30bae45bb27ae50aea77jvr
2314e5af60930726d06a58a30bae45bb27ae50aea77jvr
232f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrclass T2CharString(ByteCodeBase):
2337842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2347842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = t2OperandEncoding
235455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	operators, opcodes = buildOperatorDict(t2Operators)
2367842e56b97ce677b83bdab09cda48bc2d89ac75aJust
237489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, bytecode=None, program=None, private=None, globalSubrs=None):
2387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if program is None:
2397842e56b97ce677b83bdab09cda48bc2d89ac75aJust			program = []
2407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.bytecode = bytecode
2417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.program = program
242489d76a340845361def6af9ab7d9152f8e66f417jvr		self.private = private
243846d09e380215f8c7fdb4bbb9f083f8e68722cdaBehdad Esfahbod		self.globalSubrs = globalSubrs if globalSubrs is not None else []
2447842e56b97ce677b83bdab09cda48bc2d89ac75aJust
2457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __repr__(self):
2467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is None:
2477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return "<%s (source) at %x>" % (self.__class__.__name__, id(self))
2487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
2497842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return "<%s (bytecode) at %x>" % (self.__class__.__name__, id(self))
2507842e56b97ce677b83bdab09cda48bc2d89ac75aJust
25195c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	def getIntEncoder(self):
25295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		return encodeIntT2
25395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr
25495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	def getFixedEncoder(self):
25595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		return encodeFixed
25695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr
257586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def decompile(self):
258586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		if not self.needsDecompilation():
259586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr			return
260489d76a340845361def6af9ab7d9152f8e66f417jvr		subrs = getattr(self.private, "Subrs", [])
261489d76a340845361def6af9ab7d9152f8e66f417jvr		decompiler = SimpleT2Decompiler(subrs, self.globalSubrs)
262586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		decompiler.execute(self)
263586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr
264489d76a340845361def6af9ab7d9152f8e66f417jvr	def draw(self, pen):
265489d76a340845361def6af9ab7d9152f8e66f417jvr		subrs = getattr(self.private, "Subrs", [])
266489d76a340845361def6af9ab7d9152f8e66f417jvr		extractor = T2OutlineExtractor(pen, subrs, self.globalSubrs,
267489d76a340845361def6af9ab7d9152f8e66f417jvr				self.private.nominalWidthX, self.private.defaultWidthX)
268489d76a340845361def6af9ab7d9152f8e66f417jvr		extractor.execute(self)
269489d76a340845361def6af9ab7d9152f8e66f417jvr		self.width = extractor.width
270489d76a340845361def6af9ab7d9152f8e66f417jvr
271455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	def compile(self):
272455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		if self.bytecode is not None:
273455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			return
2749920ad5286b6e61d67f07f908107d65f7fa817acjvr		assert self.program, "illegal CharString: decompiled to empty program"
2759920ad5286b6e61d67f07f908107d65f7fa817acjvr		assert self.program[-1] in ("endchar", "return", "callsubr", "callgsubr",
2769920ad5286b6e61d67f07f908107d65f7fa817acjvr				"seac"), "illegal CharString"
277455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		bytecode = []
278455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr		opcodes = self.opcodes
2794e5af60930726d06a58a30bae45bb27ae50aea77jvr		program = self.program
28095c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		encodeInt = self.getIntEncoder()
28195c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		encodeFixed = self.getFixedEncoder()
2824e5af60930726d06a58a30bae45bb27ae50aea77jvr		i = 0
2834e5af60930726d06a58a30bae45bb27ae50aea77jvr		end = len(program)
2844e5af60930726d06a58a30bae45bb27ae50aea77jvr		while i < end:
2854e5af60930726d06a58a30bae45bb27ae50aea77jvr			token = program[i]
2864e5af60930726d06a58a30bae45bb27ae50aea77jvr			i = i + 1
287455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			tp = type(token)
288002c32fd0d869e280783777ec57916a9267aaea5Behdad Esfahbod			if tp == str:
2894e5af60930726d06a58a30bae45bb27ae50aea77jvr				try:
290e5ca79699d00fdf7ac6eaceaed372aea8d6bc1fdBehdad Esfahbod					bytecode.extend(chr(b) for b in opcodes[token])
2914e5af60930726d06a58a30bae45bb27ae50aea77jvr				except KeyError:
292cd5aad92f23737ff93a110d5c73d624658a28da8Behdad Esfahbod					raise CharStringCompileError("illegal operator: %s" % token)
2934e5af60930726d06a58a30bae45bb27ae50aea77jvr				if token in ('hintmask', 'cntrmask'):
2944e5af60930726d06a58a30bae45bb27ae50aea77jvr					bytecode.append(program[i])  # hint mask
2954e5af60930726d06a58a30bae45bb27ae50aea77jvr					i = i + 1
296002c32fd0d869e280783777ec57916a9267aaea5Behdad Esfahbod			elif tp == int:
29795c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				bytecode.append(encodeInt(token))
298002c32fd0d869e280783777ec57916a9267aaea5Behdad Esfahbod			elif tp == float:
29995c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				bytecode.append(encodeFixed(token))
300455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr			else:
301f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr				assert 0, "unsupported type: %s" % tp
3024e5af60930726d06a58a30bae45bb27ae50aea77jvr		try:
3034e5af60930726d06a58a30bae45bb27ae50aea77jvr			bytecode = "".join(bytecode)
3044e5af60930726d06a58a30bae45bb27ae50aea77jvr		except TypeError:
3053ec6a258238b6068e4eef3fe579f1f5c0a06bbbaBehdad Esfahbod			print(bytecode)
3064e5af60930726d06a58a30bae45bb27ae50aea77jvr			raise
307f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		self.setBytecode(bytecode)
308f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
3097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def needsDecompilation(self):
3107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.bytecode is not None
3117842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def setProgram(self, program):
3137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.program = program
3147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.bytecode = None
3157842e56b97ce677b83bdab09cda48bc2d89ac75aJust
316f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr	def setBytecode(self, bytecode):
317f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		self.bytecode = bytecode
318f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr		self.program = None
319f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvr
3207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getToken(self, index,
321002c32fd0d869e280783777ec57916a9267aaea5Behdad Esfahbod			len=len, ord=ord, getattr=getattr, type=type, StringType=str):
3227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is not None:
3237842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if index >= len(self.bytecode):
3247842e56b97ce677b83bdab09cda48bc2d89ac75aJust				return None, 0, 0
3257842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b0 = ord(self.bytecode[index])
3267842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
3277842e56b97ce677b83bdab09cda48bc2d89ac75aJust			code = self.operandEncoding[b0]
3287842e56b97ce677b83bdab09cda48bc2d89ac75aJust			handler = getattr(self, code)
3297842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token, index = handler(b0, self.bytecode, index)
3307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
3317842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if index >= len(self.program):
3327842e56b97ce677b83bdab09cda48bc2d89ac75aJust				return None, 0, 0
3337842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token = self.program[index]
3347842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
335ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod		isOperator = isinstance(token, StringType)
3367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return token, isOperator, index
3377842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getBytes(self, index, nBytes):
3397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is not None:
3407842e56b97ce677b83bdab09cda48bc2d89ac75aJust			newIndex = index + nBytes
3417842e56b97ce677b83bdab09cda48bc2d89ac75aJust			bytes = self.bytecode[index:newIndex]
3427842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = newIndex
3437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
3447842e56b97ce677b83bdab09cda48bc2d89ac75aJust			bytes = self.program[index]
3457842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
3467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		assert len(bytes) == nBytes
3477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return bytes, index
3487842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3497842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def do_operator(self, b0, data, index):
3507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if b0 == 12:
3517842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = (b0, ord(data[index]))
3527842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index+1
3537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
3547842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = b0
3557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		operator = self.operators[op]
3567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return operator, index
3577842e56b97ce677b83bdab09cda48bc2d89ac75aJust
3587842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def toXML(self, xmlWriter):
359dab433233bd4024ede9ad27c6c61ea0072c2edafJust		from fontTools.misc.textTools import num2binary
3607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.bytecode is not None:
3617842e56b97ce677b83bdab09cda48bc2d89ac75aJust			xmlWriter.dumphex(self.bytecode)
3627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
3637842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = 0
3647842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
365ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod			while True:
3667842e56b97ce677b83bdab09cda48bc2d89ac75aJust				token, isOperator, index = self.getToken(index)
3677842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if token is None:
3687842e56b97ce677b83bdab09cda48bc2d89ac75aJust					break
3697842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if isOperator:
370e5ca79699d00fdf7ac6eaceaed372aea8d6bc1fdBehdad Esfahbod					args = [str(arg) for arg in args]
3717842e56b97ce677b83bdab09cda48bc2d89ac75aJust					if token in ('hintmask', 'cntrmask'):
3727842e56b97ce677b83bdab09cda48bc2d89ac75aJust						hintMask, isOperator, index = self.getToken(index)
3737842e56b97ce677b83bdab09cda48bc2d89ac75aJust						bits = []
3747842e56b97ce677b83bdab09cda48bc2d89ac75aJust						for byte in hintMask:
3757842e56b97ce677b83bdab09cda48bc2d89ac75aJust							bits.append(num2binary(ord(byte), 8))
37614fb031125b773f0a15eb19be4f02ed8540b2db6Behdad Esfahbod						hintMask = ''.join(bits)
37714fb031125b773f0a15eb19be4f02ed8540b2db6Behdad Esfahbod						line = ' '.join(args + [token, hintMask])
3787842e56b97ce677b83bdab09cda48bc2d89ac75aJust					else:
37914fb031125b773f0a15eb19be4f02ed8540b2db6Behdad Esfahbod						line = ' '.join(args + [token])
3807842e56b97ce677b83bdab09cda48bc2d89ac75aJust					xmlWriter.write(line)
3817842e56b97ce677b83bdab09cda48bc2d89ac75aJust					xmlWriter.newline()
3827842e56b97ce677b83bdab09cda48bc2d89ac75aJust					args = []
3837842e56b97ce677b83bdab09cda48bc2d89ac75aJust				else:
3847842e56b97ce677b83bdab09cda48bc2d89ac75aJust					args.append(token)
3854e5af60930726d06a58a30bae45bb27ae50aea77jvr
3863a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod	def fromXML(self, name, attrs, content):
387b58176e5ac4d1e0b0e6a6c71c3020f5e85bd4dfejvr		from fontTools.misc.textTools import binary2num, readHex
388b58176e5ac4d1e0b0e6a6c71c3020f5e85bd4dfejvr		if attrs.get("raw"):
389b58176e5ac4d1e0b0e6a6c71c3020f5e85bd4dfejvr			self.setBytecode(readHex(content))
390b58176e5ac4d1e0b0e6a6c71c3020f5e85bd4dfejvr			return
3914e5af60930726d06a58a30bae45bb27ae50aea77jvr		content = "".join(content)
3924e5af60930726d06a58a30bae45bb27ae50aea77jvr		content = content.split()
3934e5af60930726d06a58a30bae45bb27ae50aea77jvr		program = []
3944e5af60930726d06a58a30bae45bb27ae50aea77jvr		end = len(content)
3954e5af60930726d06a58a30bae45bb27ae50aea77jvr		i = 0
3964e5af60930726d06a58a30bae45bb27ae50aea77jvr		while i < end:
3974e5af60930726d06a58a30bae45bb27ae50aea77jvr			token = content[i]
3984e5af60930726d06a58a30bae45bb27ae50aea77jvr			i = i + 1
3994e5af60930726d06a58a30bae45bb27ae50aea77jvr			try:
4004e5af60930726d06a58a30bae45bb27ae50aea77jvr				token = int(token)
4014e5af60930726d06a58a30bae45bb27ae50aea77jvr			except ValueError:
40295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				try:
40395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr					token = float(token)
40495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				except ValueError:
40595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr					program.append(token)
40695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr					if token in ('hintmask', 'cntrmask'):
40795c9e9fc11dc028bd1747788f2b417f3936fc59bjvr						mask = content[i]
40895c9e9fc11dc028bd1747788f2b417f3936fc59bjvr						maskBytes = ""
40995c9e9fc11dc028bd1747788f2b417f3936fc59bjvr						for j in range(0, len(mask), 8):
41095c9e9fc11dc028bd1747788f2b417f3936fc59bjvr							maskBytes = maskBytes + chr(binary2num(mask[j:j+8]))
41195c9e9fc11dc028bd1747788f2b417f3936fc59bjvr						program.append(maskBytes)
41295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr						i = i + 1
41395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr				else:
41495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr					program.append(token)
4154e5af60930726d06a58a30bae45bb27ae50aea77jvr			else:
4164e5af60930726d06a58a30bae45bb27ae50aea77jvr				program.append(token)
4174e5af60930726d06a58a30bae45bb27ae50aea77jvr		self.setProgram(program)
4187842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4197842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4207842e56b97ce677b83bdab09cda48bc2d89ac75aJustt1Operators = [
4217842e56b97ce677b83bdab09cda48bc2d89ac75aJust#	opcode     name
4227842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(1,        'hstem'),
4237842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(3,        'vstem'),
4247842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(4,        'vmoveto'),
4257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(5,        'rlineto'),
4267842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(6,        'hlineto'),
4277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(7,        'vlineto'),
4287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(8,        'rrcurveto'),
4297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(9,        'closepath'),
4307842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(10,       'callsubr'),
4317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(11,       'return'),
4327842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(13,       'hsbw'),
4337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(14,       'endchar'),
4347842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(21,       'rmoveto'),
4357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(22,       'hmoveto'),
4367842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(30,       'vhcurveto'),
4377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	(31,       'hvcurveto'),
4387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 0),  'dotsection'),
4397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 1),  'vstem3'),
4407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 2),  'hstem3'),
4417842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 6),  'seac'),
4427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 7),  'sbw'),
4437842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 12), 'div'),
4447842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 16), 'callothersubr'),
4457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 17), 'pop'),
4467842e56b97ce677b83bdab09cda48bc2d89ac75aJust	((12, 33), 'setcurrentpoint'),
4477842e56b97ce677b83bdab09cda48bc2d89ac75aJust]
4487842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4497842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T1CharString(T2CharString):
4507842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4517842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = t1OperandEncoding
452455af6592bffbd6f2fc9f56fbfe083022a8353d4jvr	operators, opcodes = buildOperatorDict(t1Operators)
4537842e56b97ce677b83bdab09cda48bc2d89ac75aJust
454489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, bytecode=None, program=None, subrs=None):
455489d76a340845361def6af9ab7d9152f8e66f417jvr		if program is None:
456489d76a340845361def6af9ab7d9152f8e66f417jvr			program = []
457489d76a340845361def6af9ab7d9152f8e66f417jvr		self.bytecode = bytecode
458489d76a340845361def6af9ab7d9152f8e66f417jvr		self.program = program
459489d76a340845361def6af9ab7d9152f8e66f417jvr		self.subrs = subrs
460489d76a340845361def6af9ab7d9152f8e66f417jvr
46195c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	def getIntEncoder(self):
46295c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		return encodeIntT1
46395c9e9fc11dc028bd1747788f2b417f3936fc59bjvr
46495c9e9fc11dc028bd1747788f2b417f3936fc59bjvr	def getFixedEncoder(self):
46595c9e9fc11dc028bd1747788f2b417f3936fc59bjvr		def encodeFixed(value):
46695c9e9fc11dc028bd1747788f2b417f3936fc59bjvr			raise TypeError("Type 1 charstrings don't support floating point operands")
46795c9e9fc11dc028bd1747788f2b417f3936fc59bjvr
4687842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self):
469b68a700595ff730c29d3d4b7abf92ee287678745Just		if self.program is not None:
4707842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
4717842e56b97ce677b83bdab09cda48bc2d89ac75aJust		program = []
4727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
473ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod		while True:
4747842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token, isOperator, index = self.getToken(index)
4757842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if token is None:
4767842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break
4777842e56b97ce677b83bdab09cda48bc2d89ac75aJust			program.append(token)
4787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.setProgram(program)
4797842e56b97ce677b83bdab09cda48bc2d89ac75aJust
480489d76a340845361def6af9ab7d9152f8e66f417jvr	def draw(self, pen):
481489d76a340845361def6af9ab7d9152f8e66f417jvr		extractor = T1OutlineExtractor(pen, self.subrs)
482489d76a340845361def6af9ab7d9152f8e66f417jvr		extractor.execute(self)
483489d76a340845361def6af9ab7d9152f8e66f417jvr		self.width = extractor.width
484489d76a340845361def6af9ab7d9152f8e66f417jvr
4857842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4867842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass SimpleT2Decompiler:
4877842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4887842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __init__(self, localSubrs, globalSubrs):
4897842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.localSubrs = localSubrs
4907842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.localBias = calcSubrBias(localSubrs)
4917842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.globalSubrs = globalSubrs
4927842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.globalBias = calcSubrBias(globalSubrs)
4937842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.reset()
4947842e56b97ce677b83bdab09cda48bc2d89ac75aJust
4957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
4967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.callingStack = []
4977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.operandStack = []
4987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = 0
4997842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintMaskBytes = 0
5007842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def execute(self, charString):
5027842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.callingStack.append(charString)
5037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		needsDecompilation = charString.needsDecompilation()
5047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if needsDecompilation:
5057842e56b97ce677b83bdab09cda48bc2d89ac75aJust			program = []
5067842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pushToProgram = program.append
5077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
5087842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pushToProgram = lambda x: None
5097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pushToStack = self.operandStack.append
5107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
511ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod		while True:
5127842e56b97ce677b83bdab09cda48bc2d89ac75aJust			token, isOperator, index = charString.getToken(index)
5137842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if token is None:
5147842e56b97ce677b83bdab09cda48bc2d89ac75aJust				break  # we're done!
5157842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pushToProgram(token)
5167842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if isOperator:
5177842e56b97ce677b83bdab09cda48bc2d89ac75aJust				handlerName = "op_" + token
5187842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if hasattr(self, handlerName):
5197842e56b97ce677b83bdab09cda48bc2d89ac75aJust					handler = getattr(self, handlerName)
5207842e56b97ce677b83bdab09cda48bc2d89ac75aJust					rv = handler(index)
5217842e56b97ce677b83bdab09cda48bc2d89ac75aJust					if rv:
5227842e56b97ce677b83bdab09cda48bc2d89ac75aJust						hintMaskBytes, index = rv
5237842e56b97ce677b83bdab09cda48bc2d89ac75aJust						pushToProgram(hintMaskBytes)
5247842e56b97ce677b83bdab09cda48bc2d89ac75aJust				else:
5257842e56b97ce677b83bdab09cda48bc2d89ac75aJust					self.popall()
5267842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
5277842e56b97ce677b83bdab09cda48bc2d89ac75aJust				pushToStack(token)
5287842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if needsDecompilation:
5299920ad5286b6e61d67f07f908107d65f7fa817acjvr			assert program, "illegal CharString: decompiled to empty program"
5309920ad5286b6e61d67f07f908107d65f7fa817acjvr			assert program[-1] in ("endchar", "return", "callsubr", "callgsubr",
5319920ad5286b6e61d67f07f908107d65f7fa817acjvr					"seac"), "illegal CharString"
5327842e56b97ce677b83bdab09cda48bc2d89ac75aJust			charString.setProgram(program)
5337842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.callingStack[-1]
5347842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def pop(self):
5367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value = self.operandStack[-1]
5377842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.operandStack[-1]
5387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value
5397842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popall(self):
5417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack = self.operandStack[:]
5427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.operandStack[:] = []
5437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return stack
5447842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def push(self, value):
5467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.operandStack.append(value)
5477842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5487842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_return(self, index):
5497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.operandStack:
5507842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pass
5517842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5527842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
5537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pass
5547099f4c0f9fbaf1a5c811113fdfd2404dee04361jvr
5557099f4c0f9fbaf1a5c811113fdfd2404dee04361jvr	def op_ignore(self, index):
5567099f4c0f9fbaf1a5c811113fdfd2404dee04361jvr		pass
5577099f4c0f9fbaf1a5c811113fdfd2404dee04361jvr
5587842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callsubr(self, index):
5597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
5607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.localSubrs[subrIndex+self.localBias]
5617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
5627842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5637842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callgsubr(self, index):
5647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
5657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.globalSubrs[subrIndex+self.globalBias]
5667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
5677842e56b97ce677b83bdab09cda48bc2d89ac75aJust
568586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def op_hstem(self, index):
569586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.countHints()
570586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def op_vstem(self, index):
571586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.countHints()
5727842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hstemhm(self, index):
5737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.countHints()
574586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	def op_vstemhm(self, index):
575586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr		self.countHints()
5767842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5777842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hintmask(self, index):
5787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if not self.hintMaskBytes:
5797842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.countHints()
5807842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.hintMaskBytes = (self.hintCount + 7) / 8
5817842e56b97ce677b83bdab09cda48bc2d89ac75aJust		hintMaskBytes, index = self.callingStack[-1].getBytes(index, self.hintMaskBytes)
5827842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return hintMaskBytes, index
5837842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5847842e56b97ce677b83bdab09cda48bc2d89ac75aJust	op_cntrmask = op_hintmask
5857842e56b97ce677b83bdab09cda48bc2d89ac75aJust
5867842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def countHints(self):
5877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
5887842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = self.hintCount + len(args) / 2
5897842e56b97ce677b83bdab09cda48bc2d89ac75aJust
590f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	# misc
591f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_and(self, index):
592f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
593f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_or(self, index):
594f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
595f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_not(self, index):
596f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
597f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_store(self, index):
598f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
599f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_abs(self, index):
600f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
601f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_add(self, index):
602f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
603f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_sub(self, index):
604f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
605f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_div(self, index):
606f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
607f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_load(self, index):
608f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
609f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_neg(self, index):
610f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
611f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_eq(self, index):
612f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
613f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_drop(self, index):
614f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
615f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_put(self, index):
616f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
617f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_get(self, index):
618f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
619f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_ifelse(self, index):
620f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
621f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_random(self, index):
622f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
623f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_mul(self, index):
624f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
625f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_sqrt(self, index):
626f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
627f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_dup(self, index):
628f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
629f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_exch(self, index):
630f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
631f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_index(self, index):
632f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
633f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_roll(self, index):
634f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
6357842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6367842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T2OutlineExtractor(SimpleT2Decompiler):
6377842e56b97ce677b83bdab09cda48bc2d89ac75aJust
638489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, pen, localSubrs, globalSubrs, nominalWidthX, defaultWidthX):
6397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		SimpleT2Decompiler.__init__(self, localSubrs, globalSubrs)
640489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen = pen
6417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.nominalWidthX = nominalWidthX
6427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.defaultWidthX = defaultWidthX
6437842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6447842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
6457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		SimpleT2Decompiler.reset(self)
6467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hints = []
6477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.gotWidth = 0
6487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = 0
649489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = (0, 0)
650489d76a340845361def6af9ab7d9152f8e66f417jvr		self.sawMoveTo = 0
6517842e56b97ce677b83bdab09cda48bc2d89ac75aJust
652489d76a340845361def6af9ab7d9152f8e66f417jvr	def _nextPoint(self, point):
653489d76a340845361def6af9ab7d9152f8e66f417jvr		x, y = self.currentPoint
654489d76a340845361def6af9ab7d9152f8e66f417jvr		point = x + point[0], y + point[1]
655489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = point
656489d76a340845361def6af9ab7d9152f8e66f417jvr		return point
6577842e56b97ce677b83bdab09cda48bc2d89ac75aJust
658489d76a340845361def6af9ab7d9152f8e66f417jvr	def rMoveTo(self, point):
659489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.moveTo(self._nextPoint(point))
660489d76a340845361def6af9ab7d9152f8e66f417jvr		self.sawMoveTo = 1
661489d76a340845361def6af9ab7d9152f8e66f417jvr
662489d76a340845361def6af9ab7d9152f8e66f417jvr	def rLineTo(self, point):
663489d76a340845361def6af9ab7d9152f8e66f417jvr		if not self.sawMoveTo:
664489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rMoveTo((0, 0))
665489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.lineTo(self._nextPoint(point))
666489d76a340845361def6af9ab7d9152f8e66f417jvr
667489d76a340845361def6af9ab7d9152f8e66f417jvr	def rCurveTo(self, pt1, pt2, pt3):
668489d76a340845361def6af9ab7d9152f8e66f417jvr		if not self.sawMoveTo:
669489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rMoveTo((0, 0))
670489d76a340845361def6af9ab7d9152f8e66f417jvr		nextPoint = self._nextPoint
671489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.curveTo(nextPoint(pt1), nextPoint(pt2), nextPoint(pt3))
6727842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6737842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def closePath(self):
674489d76a340845361def6af9ab7d9152f8e66f417jvr		if self.sawMoveTo:
675489d76a340845361def6af9ab7d9152f8e66f417jvr			self.pen.closePath()
676489d76a340845361def6af9ab7d9152f8e66f417jvr		self.sawMoveTo = 0
6777842e56b97ce677b83bdab09cda48bc2d89ac75aJust
678d3ee2d4319742ec61cb299665ccba66c139e4834jvr	def endPath(self):
679d3ee2d4319742ec61cb299665ccba66c139e4834jvr		# In T2 there are no open paths, so always do a closePath when
680d3ee2d4319742ec61cb299665ccba66c139e4834jvr		# finishing a sub path.
681d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.closePath()
682d3ee2d4319742ec61cb299665ccba66c139e4834jvr
6837842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popallWidth(self, evenOdd=0):
6847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
6857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if not self.gotWidth:
6867842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if evenOdd ^ (len(args) % 2):
6877842e56b97ce677b83bdab09cda48bc2d89ac75aJust				self.width = self.nominalWidthX + args[0]
6887842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = args[1:]
6897842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
6907842e56b97ce677b83bdab09cda48bc2d89ac75aJust				self.width = self.defaultWidthX
6917842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.gotWidth = 1
6927842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
6937842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6947842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def countHints(self):
6957842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popallWidth()
6967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = self.hintCount + len(args) / 2
6977842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6987842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
6997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# hint operators
7007842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
701586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_hstem(self, index):
702586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
703586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_vstem(self, index):
704586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
705586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_hstemhm(self, index):
706586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
707586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_vstemhm(self, index):
708586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
7097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#def op_hintmask(self, index):
7107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#	self.countHints()
7117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#def op_cntrmask(self, index):
7127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#	self.countHints()
7137842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7157842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, moveto
7167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7177842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rmoveto(self, index):
718d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
719489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo(self.popallWidth())
7207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hmoveto(self, index):
721d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
722489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((self.popallWidth(1)[0], 0))
7237842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vmoveto(self, index):
724d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
725489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((0, self.popallWidth(1)[0]))
7267842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
727d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
728382df6c42a7a6aecb690e07c6338e19f038f0543jvr		args = self.popallWidth()
729382df6c42a7a6aecb690e07c6338e19f038f0543jvr		if args:
730382df6c42a7a6aecb690e07c6338e19f038f0543jvr			from fontTools.encodings.StandardEncoding import StandardEncoding
731382df6c42a7a6aecb690e07c6338e19f038f0543jvr			# endchar can do seac accent bulding; The T2 spec says it's deprecated,
732382df6c42a7a6aecb690e07c6338e19f038f0543jvr			# but recent software that shall remain nameless does output it.
733382df6c42a7a6aecb690e07c6338e19f038f0543jvr			adx, ady, bchar, achar = args
734382df6c42a7a6aecb690e07c6338e19f038f0543jvr			baseGlyph = StandardEncoding[bchar]
735382df6c42a7a6aecb690e07c6338e19f038f0543jvr			self.pen.addComponent(baseGlyph, (1, 0, 0, 1, 0, 0))
736382df6c42a7a6aecb690e07c6338e19f038f0543jvr			accentGlyph = StandardEncoding[achar]
737382df6c42a7a6aecb690e07c6338e19f038f0543jvr			self.pen.addComponent(accentGlyph, (1, 0, 0, 1, adx, ady))
7387842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, lines
7417842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rlineto(self, index):
7437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 2):
7457842e56b97ce677b83bdab09cda48bc2d89ac75aJust			point = args[i:i+2]
746489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rLineTo(point)
7477842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7487842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hlineto(self, index):
7497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.alternatingLineto(1)
7507842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vlineto(self, index):
7517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.alternatingLineto(0)
7527842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7537842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7547842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, curves
7557842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7567842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rrcurveto(self, index):
7577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya dxb dyb dxc dyc}+ rrcurveto"""
7587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 6):
7607842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxa, dya, dxb, dyb, dxc, dyc, = args[i:i+6]
761489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dxa, dya), (dxb, dyb), (dxc, dyc))
7627842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7637842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rcurveline(self, index):
7647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya dxb dyb dxc dyc}+ dxd dyd rcurveline"""
7657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args)-2, 6):
7677842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxb, dyb, dxc, dyc, dxd, dyd = args[i:i+6]
768489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dxb, dyb), (dxc, dyc), (dxd, dyd))
769489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rLineTo(args[-2:])
7707842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7717842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rlinecurve(self, index):
7727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya}+ dxb dyb dxc dyc dxd dyd rlinecurve"""
7737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lineArgs = args[:-6]
7757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(lineArgs), 2):
776489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rLineTo(lineArgs[i:i+2])
7777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dxb, dyb, dxc, dyc, dxd, dyd = args[-6:]
778489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rCurveTo((dxb, dyb), (dxc, dyc), (dxd, dyd))
7797842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7807842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vvcurveto(self, index):
7817842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"dx1? {dya dxb dyb dyc}+ vvcurveto"
7827842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) % 2:
7847842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = args[0]
7857842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = args[1:]
7867842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
7877842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = 0
7887842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 4):
7897842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dya, dxb, dyb, dyc = args[i:i+4]
790489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dx1, dya), (dxb, dyb), (0, dyc))
7917842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = 0
7927842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hhcurveto(self, index):
7947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dy1? {dxa dxb dyb dxc}+ hhcurveto"""
7957842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) % 2:
7977842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = args[0]
7987842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = args[1:]
7997842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
8007842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = 0
8017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 4):
8027842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxa, dxb, dyb, dxc = args[i:i+4]
803489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dxa, dy1), (dxb, dyb), (dxc, 0))
8047842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = 0
8057842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8067842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vhcurveto(self, index):
8077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? vhcurveto (30)
8087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		{dya dxb dyb dxc dxd dxe dye dyf}+ dxf? vhcurveto
8097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""
8107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
8117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while args:
8127842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = self.vcurveto(args)
8137842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if args:
8147842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = self.hcurveto(args)
8157842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hvcurveto(self, index):
8177842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf?
8187842e56b97ce677b83bdab09cda48bc2d89ac75aJust		{dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?
8197842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""
8207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
8217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while args:
8227842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = self.hcurveto(args)
8237842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if args:
8247842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = self.vcurveto(args)
8257842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8267842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, flex
8287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hflex(self, index):
8308b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx1, dx2, dy2, dx3, dx4, dx5, dx6 = self.popall()
831d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr		dy1 = dy3 = dy4 = dy6 = 0
832d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr		dy5 = -dy2
8338b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx1, dy1), (dx2, dy2), (dx3, dy3))
8348b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx4, dy4), (dx5, dy5), (dx6, dy6))
8357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_flex(self, index):
8368b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4, dx5, dy5, dx6, dy6, fd = self.popall()
8378b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx1, dy1), (dx2, dy2), (dx3, dy3))
8388b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx4, dy4), (dx5, dy5), (dx6, dy6))
8397842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hflex1(self, index):
8408b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx1, dy1, dx2, dy2, dx3, dx4, dx5, dy5, dx6 = self.popall()
841d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr		dy3 = dy4 = 0
842d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr		dy6 = -(dy1 + dy2 + dy3 + dy4 + dy5)
843d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr
8448b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx1, dy1), (dx2, dy2), (dx3, dy3))
8458b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx4, dy4), (dx5, dy5), (dx6, dy6))
8467842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_flex1(self, index):
8478b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4, dx5, dy5, d6 = self.popall()
8488b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx = dx1 + dx2 + dx3 + dx4 + dx5
8498b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dy = dy1 + dy2 + dy3 + dy4 + dy5
8508b8b44904e116287ca0eb587f9c5b21296fb3123jvr		if abs(dx) > abs(dy):
8518b8b44904e116287ca0eb587f9c5b21296fb3123jvr			dx6 = d6
852d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr			dy6 = -dy
8538b8b44904e116287ca0eb587f9c5b21296fb3123jvr		else:
854d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr			dx6 = -dx
8558b8b44904e116287ca0eb587f9c5b21296fb3123jvr			dy6 = d6
8568b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx1, dy1), (dx2, dy2), (dx3, dy3))
8578b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx4, dy4), (dx5, dy5), (dx6, dy6))
8587842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8597842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8607842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# MultipleMaster. Well...
8617842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8627842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_blend(self, index):
8638b8b44904e116287ca0eb587f9c5b21296fb3123jvr		args = self.popall()
8647842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8657842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# misc
8667842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_and(self, index):
8678b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8687842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_or(self, index):
8698b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8707842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_not(self, index):
8718b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8727842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_store(self, index):
8738b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8747842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_abs(self, index):
8758b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8767842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_add(self, index):
8778b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8787842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sub(self, index):
8798b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8807842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_div(self, index):
8817842e56b97ce677b83bdab09cda48bc2d89ac75aJust		num2 = self.pop()
8827842e56b97ce677b83bdab09cda48bc2d89ac75aJust		num1 = self.pop()
8837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		d1 = num1/num2
8847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		d2 = float(num1)/num2
8857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if d1 == d2:
8867842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(d1)
8877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
8887842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(d2)
8897842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_load(self, index):
8908b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8917842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_neg(self, index):
8928b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_eq(self, index):
8948b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_drop(self, index):
8968b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_put(self, index):
8988b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_get(self, index):
9008b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_ifelse(self, index):
9028b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_random(self, index):
9048b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_mul(self, index):
9068b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9077842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sqrt(self, index):
9088b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_dup(self, index):
9108b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_exch(self, index):
9128b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9137842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_index(self, index):
9148b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9157842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_roll(self, index):
9168b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9177842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9187842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
9197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# miscelaneous helpers
9207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
9217842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def alternatingLineto(self, isHorizontal):
9227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
9237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for arg in args:
9247842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if isHorizontal:
9257842e56b97ce677b83bdab09cda48bc2d89ac75aJust				point = (arg, 0)
9267842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
9277842e56b97ce677b83bdab09cda48bc2d89ac75aJust				point = (0, arg)
928489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rLineTo(point)
9297842e56b97ce677b83bdab09cda48bc2d89ac75aJust			isHorizontal = not isHorizontal
9307842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def vcurveto(self, args):
9327842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dya, dxb, dyb, dxc = args[:4]
9337842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = args[4:]
9347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) == 1:
9357842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dyc = args[0]
9367842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
9377842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
9387842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dyc = 0
939489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rCurveTo((0, dya), (dxb, dyb), (dxc, dyc))
9407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
9417842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def hcurveto(self, args):
9437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dxa, dxb, dyb, dyc = args[:4]
9447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = args[4:]
9457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) == 1:
9467842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxc = args[0]
9477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
9487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
9497842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxc = 0
950489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rCurveTo((dxa, 0), (dxb, dyb), (dxc, dyc))
9517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
9527842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9537842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9547842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T1OutlineExtractor(T2OutlineExtractor):
9557842e56b97ce677b83bdab09cda48bc2d89ac75aJust
956489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, pen, subrs):
957489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen = pen
9587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.subrs = subrs
9597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.reset()
9607842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9617842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
9627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.flexing = 0
9637842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = 0
9647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.sbx = 0
9657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		T2OutlineExtractor.reset(self)
9667842e56b97ce677b83bdab09cda48bc2d89ac75aJust
967d3ee2d4319742ec61cb299665ccba66c139e4834jvr	def endPath(self):
968d3ee2d4319742ec61cb299665ccba66c139e4834jvr		if self.sawMoveTo:
969d3ee2d4319742ec61cb299665ccba66c139e4834jvr			self.pen.endPath()
970d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.sawMoveTo = 0
971d3ee2d4319742ec61cb299665ccba66c139e4834jvr
9727842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popallWidth(self, evenOdd=0):
9737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.popall()
9747842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9757842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def exch(self):
9767842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack = self.operandStack
9777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack[-1], stack[-2] = stack[-2], stack[-1]
9787842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9797842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
9807842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors
9817842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
9827842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rmoveto(self, index):
9837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
9847842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
985e56bc902cf6a707349ae6ddfe8a83a1bd7b155b9jvr		self.endPath()
986489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo(self.popall())
9877842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hmoveto(self, index):
9887842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
9897842e56b97ce677b83bdab09cda48bc2d89ac75aJust			# We must add a parameter to the stack if we are flexing
9907842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(0)
9917842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
992d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
993489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((self.popall()[0], 0))
9947842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vmoveto(self, index):
9957842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
9967842e56b97ce677b83bdab09cda48bc2d89ac75aJust			# We must add a parameter to the stack if we are flexing
9977842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(0)
9987842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.exch()
9997842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
1000d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
1001489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((0, self.popall()[0]))
10027842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_closepath(self, index):
10037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
10047842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_setcurrentpoint(self, index):
10057842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
10067842e56b97ce677b83bdab09cda48bc2d89ac75aJust		x, y = args
1007489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = x, y
10087842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
1010d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
10117842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hsbw(self, index):
10137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		sbx, wx = self.popall()
10147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = wx
10157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.sbx = sbx
1016489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = sbx, self.currentPoint[1]
10177842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sbw(self, index):
10187842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
10197842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
10217842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callsubr(self, index):
10227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
10237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.subrs[subrIndex]
10247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
10257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callothersubr(self, index):
10267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
10277842e56b97ce677b83bdab09cda48bc2d89ac75aJust		nArgs = self.pop()
10287842e56b97ce677b83bdab09cda48bc2d89ac75aJust		#print nArgs, subrIndex, "callothersubr"
10297842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if subrIndex == 0 and nArgs == 3:
10307842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.doFlex()
10317842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.flexing = 0
10327842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif subrIndex == 1 and nArgs == 0:
10337842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.flexing = 1
10347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# ignore...
10357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_pop(self, index):
10367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pass  # ignore...
10377842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10387842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def doFlex(self):
10397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		finaly = self.pop()
10407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		finalx = self.pop()
10417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.pop()	# flex height is unused
10427842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p3y = self.pop()
10447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p3x = self.pop()
10457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp4y = self.pop()
10467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp4x = self.pop()
10477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp3y = self.pop()
10487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp3x = self.pop()
10497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p2y = self.pop()
10507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p2x = self.pop()
10517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp2y = self.pop()
10527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp2x = self.pop()
10537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp1y = self.pop()
10547842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp1x = self.pop()
10557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		rpy = self.pop()
10567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		rpx = self.pop()
10577842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# call rrcurveto
10597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp1x+rpx)
10607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp1y+rpy)
10617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp2x)
10627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp2y)
10637842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p2x)
10647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p2y)
10657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.op_rrcurveto(None)
10667842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10677842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# call rrcurveto
10687842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp3x)
10697842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp3y)
10707842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp4x)
10717842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp4y)
10727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p3x)
10737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p3y)
10747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.op_rrcurveto(None)
10757842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10767842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# Push back final coords so subr 0 can find them
10777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(finalx)
10787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(finaly)
10797842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10807842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_dotsection(self, index):
10817842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
10827842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hstem3(self, index):
10837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
10847842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_seac(self, index):
10857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"asb adx ady bchar achar seac"
1086489d76a340845361def6af9ab7d9152f8e66f417jvr		from fontTools.encodings.StandardEncoding import StandardEncoding
1087489d76a340845361def6af9ab7d9152f8e66f417jvr		asb, adx, ady, bchar, achar = self.popall()
1088489d76a340845361def6af9ab7d9152f8e66f417jvr		baseGlyph = StandardEncoding[bchar]
1089489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.addComponent(baseGlyph, (1, 0, 0, 1, 0, 0))
1090489d76a340845361def6af9ab7d9152f8e66f417jvr		accentGlyph = StandardEncoding[achar]
1091489d76a340845361def6af9ab7d9152f8e66f417jvr		adx = adx + self.sbx - asb  # seac weirdness
1092489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.addComponent(accentGlyph, (1, 0, 0, 1, adx, ady))
10937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vstem3(self, index):
10947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
10957842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10967842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1097f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrclass DictDecompiler(ByteCodeBase):
10987842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = cffDictOperandEncoding
11007842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __init__(self, strings):
11027842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.stack = []
11037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.strings = strings
11047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.dict = {}
11057842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11067842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getDict(self):
11077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		assert len(self.stack) == 0, "non-empty stack"
11087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.dict
11097842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self, data):
11117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
11127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lenData = len(data)
11137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		push = self.stack.append
11147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while index < lenData:
11157842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b0 = ord(data[index])
11167842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
11177842e56b97ce677b83bdab09cda48bc2d89ac75aJust			code = self.operandEncoding[b0]
11187842e56b97ce677b83bdab09cda48bc2d89ac75aJust			handler = getattr(self, code)
11197842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value, index = handler(b0, data, index)
11207842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if value is not None:
11217842e56b97ce677b83bdab09cda48bc2d89ac75aJust				push(value)
11227842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11237842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def pop(self):
11247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value = self.stack[-1]
11257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.stack[-1]
11267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value
11277842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popall(self):
11297842e56b97ce677b83bdab09cda48bc2d89ac75aJust		all = self.stack[:]
11307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.stack[:]
11317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return all
11327842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def do_operator(self, b0, data, index):
11347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if b0 == 12:
11357842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = (b0, ord(data[index]))
11367842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index+1
11377842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
11387842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = b0
11397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		operator, argType = self.operators[op]
11407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.handle_operator(operator, argType)
11417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return None, index
11427842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11437842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def handle_operator(self, operator, argType):
1144ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod		if isinstance(argType, type(())):
11457842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = ()
1146bf2f402913a2706dfa92190e60cba7acbf01c9d7jvr			for i in range(len(argType)-1, -1, -1):
1147bf2f402913a2706dfa92190e60cba7acbf01c9d7jvr				arg = argType[i]
11487842e56b97ce677b83bdab09cda48bc2d89ac75aJust				arghandler = getattr(self, "arg_" + arg)
11497842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value = (arghandler(operator),) + value
11507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
11517842e56b97ce677b83bdab09cda48bc2d89ac75aJust			arghandler = getattr(self, "arg_" + argType)
11527842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = arghandler(operator)
11537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.dict[operator] = value
11547842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11557842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_number(self, name):
11567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.pop()
11577842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_SID(self, name):
11587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.strings[self.pop()]
11597842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_array(self, name):
11607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.popall()
1161dc18128aa9b3f6b98a623c294ac615195159025ejvr	def arg_delta(self, name):
1162dc18128aa9b3f6b98a623c294ac615195159025ejvr		out = []
1163dc18128aa9b3f6b98a623c294ac615195159025ejvr		current = 0
1164dc18128aa9b3f6b98a623c294ac615195159025ejvr		for v in self.popall():
11656f03a58f59fb20662602e3d4bb153d7db2f778d3jvr			current = current + v
1166dc18128aa9b3f6b98a623c294ac615195159025ejvr			out.append(current)
1167dc18128aa9b3f6b98a623c294ac615195159025ejvr		return out
11687842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11697842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11707842e56b97ce677b83bdab09cda48bc2d89ac75aJustdef calcSubrBias(subrs):
11717842e56b97ce677b83bdab09cda48bc2d89ac75aJust	nSubrs = len(subrs)
11727842e56b97ce677b83bdab09cda48bc2d89ac75aJust	if nSubrs < 1240:
11737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 107
11747842e56b97ce677b83bdab09cda48bc2d89ac75aJust	elif nSubrs < 33900:
11757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 1131
11767842e56b97ce677b83bdab09cda48bc2d89ac75aJust	else:
11777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 32768
11787842e56b97ce677b83bdab09cda48bc2d89ac75aJust	return bias
1179