psCharStrings.py revision 3a9fd301808f5a8991ca9ac44028d1ecb22d307f
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
245846d09e380215f8c7fdb4bbb9f083f8e68722cdaBehdad Esfahbod		self.globalSubrs = globalSubrs if globalSubrs is not None else []
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:
294cd5aad92f23737ff93a110d5c73d624658a28da8Behdad Esfahbod					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
3883a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod	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
592f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	# misc
593f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_and(self, index):
594f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
595f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_or(self, index):
596f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
597f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_not(self, index):
598f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
599f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_store(self, index):
600f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
601f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_abs(self, index):
602f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
603f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_add(self, index):
604f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
605f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_sub(self, index):
606f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
607f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_div(self, index):
608f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
609f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_load(self, index):
610f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
611f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_neg(self, index):
612f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
613f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_eq(self, index):
614f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
615f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_drop(self, index):
616f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
617f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_put(self, index):
618f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
619f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_get(self, index):
620f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
621f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_ifelse(self, index):
622f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
623f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_random(self, index):
624f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
625f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_mul(self, index):
626f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
627f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_sqrt(self, index):
628f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
629f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_dup(self, index):
630f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
631f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_exch(self, index):
632f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
633f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_index(self, index):
634f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
635f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod	def op_roll(self, index):
636f09f1d406446d1e249ab89b5c345d0a86e8392e3Behdad Esfahbod		raise NotImplementedError
6377842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6387842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T2OutlineExtractor(SimpleT2Decompiler):
6397842e56b97ce677b83bdab09cda48bc2d89ac75aJust
640489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, pen, localSubrs, globalSubrs, nominalWidthX, defaultWidthX):
6417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		SimpleT2Decompiler.__init__(self, localSubrs, globalSubrs)
642489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen = pen
6437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.nominalWidthX = nominalWidthX
6447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.defaultWidthX = defaultWidthX
6457842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6467842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
6477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		SimpleT2Decompiler.reset(self)
6487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hints = []
6497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.gotWidth = 0
6507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = 0
651489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = (0, 0)
652489d76a340845361def6af9ab7d9152f8e66f417jvr		self.sawMoveTo = 0
6537842e56b97ce677b83bdab09cda48bc2d89ac75aJust
654489d76a340845361def6af9ab7d9152f8e66f417jvr	def _nextPoint(self, point):
655489d76a340845361def6af9ab7d9152f8e66f417jvr		x, y = self.currentPoint
656489d76a340845361def6af9ab7d9152f8e66f417jvr		point = x + point[0], y + point[1]
657489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = point
658489d76a340845361def6af9ab7d9152f8e66f417jvr		return point
6597842e56b97ce677b83bdab09cda48bc2d89ac75aJust
660489d76a340845361def6af9ab7d9152f8e66f417jvr	def rMoveTo(self, point):
661489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.moveTo(self._nextPoint(point))
662489d76a340845361def6af9ab7d9152f8e66f417jvr		self.sawMoveTo = 1
663489d76a340845361def6af9ab7d9152f8e66f417jvr
664489d76a340845361def6af9ab7d9152f8e66f417jvr	def rLineTo(self, point):
665489d76a340845361def6af9ab7d9152f8e66f417jvr		if not self.sawMoveTo:
666489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rMoveTo((0, 0))
667489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.lineTo(self._nextPoint(point))
668489d76a340845361def6af9ab7d9152f8e66f417jvr
669489d76a340845361def6af9ab7d9152f8e66f417jvr	def rCurveTo(self, pt1, pt2, pt3):
670489d76a340845361def6af9ab7d9152f8e66f417jvr		if not self.sawMoveTo:
671489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rMoveTo((0, 0))
672489d76a340845361def6af9ab7d9152f8e66f417jvr		nextPoint = self._nextPoint
673489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.curveTo(nextPoint(pt1), nextPoint(pt2), nextPoint(pt3))
6747842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6757842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def closePath(self):
676489d76a340845361def6af9ab7d9152f8e66f417jvr		if self.sawMoveTo:
677489d76a340845361def6af9ab7d9152f8e66f417jvr			self.pen.closePath()
678489d76a340845361def6af9ab7d9152f8e66f417jvr		self.sawMoveTo = 0
6797842e56b97ce677b83bdab09cda48bc2d89ac75aJust
680d3ee2d4319742ec61cb299665ccba66c139e4834jvr	def endPath(self):
681d3ee2d4319742ec61cb299665ccba66c139e4834jvr		# In T2 there are no open paths, so always do a closePath when
682d3ee2d4319742ec61cb299665ccba66c139e4834jvr		# finishing a sub path.
683d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.closePath()
684d3ee2d4319742ec61cb299665ccba66c139e4834jvr
6857842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popallWidth(self, evenOdd=0):
6867842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
6877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if not self.gotWidth:
6887842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if evenOdd ^ (len(args) % 2):
6897842e56b97ce677b83bdab09cda48bc2d89ac75aJust				self.width = self.nominalWidthX + args[0]
6907842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = args[1:]
6917842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
6927842e56b97ce677b83bdab09cda48bc2d89ac75aJust				self.width = self.defaultWidthX
6937842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.gotWidth = 1
6947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
6957842e56b97ce677b83bdab09cda48bc2d89ac75aJust
6967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def countHints(self):
6977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popallWidth()
6987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.hintCount = self.hintCount + len(args) / 2
6997842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7007842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# hint operators
7027842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
703586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_hstem(self, index):
704586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
705586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_vstem(self, index):
706586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
707586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_hstemhm(self, index):
708586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
709586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#def op_vstemhm(self, index):
710586345b7c1c0aa97b06f1597b67c3bb4c4e97be1jvr	#	self.countHints()
7117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#def op_hintmask(self, index):
7127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#	self.countHints()
7137842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#def op_cntrmask(self, index):
7147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#	self.countHints()
7157842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7177842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, moveto
7187842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rmoveto(self, index):
720d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
721489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo(self.popallWidth())
7227842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hmoveto(self, index):
723d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
724489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((self.popallWidth(1)[0], 0))
7257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vmoveto(self, index):
726d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
727489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((0, self.popallWidth(1)[0]))
7287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
729d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
730382df6c42a7a6aecb690e07c6338e19f038f0543jvr		args = self.popallWidth()
731382df6c42a7a6aecb690e07c6338e19f038f0543jvr		if args:
732382df6c42a7a6aecb690e07c6338e19f038f0543jvr			from fontTools.encodings.StandardEncoding import StandardEncoding
733382df6c42a7a6aecb690e07c6338e19f038f0543jvr			# endchar can do seac accent bulding; The T2 spec says it's deprecated,
734382df6c42a7a6aecb690e07c6338e19f038f0543jvr			# but recent software that shall remain nameless does output it.
735382df6c42a7a6aecb690e07c6338e19f038f0543jvr			adx, ady, bchar, achar = args
736382df6c42a7a6aecb690e07c6338e19f038f0543jvr			baseGlyph = StandardEncoding[bchar]
737382df6c42a7a6aecb690e07c6338e19f038f0543jvr			self.pen.addComponent(baseGlyph, (1, 0, 0, 1, 0, 0))
738382df6c42a7a6aecb690e07c6338e19f038f0543jvr			accentGlyph = StandardEncoding[achar]
739382df6c42a7a6aecb690e07c6338e19f038f0543jvr			self.pen.addComponent(accentGlyph, (1, 0, 0, 1, adx, ady))
7407842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7417842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, lines
7437842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7447842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rlineto(self, index):
7457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 2):
7477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			point = args[i:i+2]
748489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rLineTo(point)
7497842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7507842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hlineto(self, index):
7517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.alternatingLineto(1)
7527842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vlineto(self, index):
7537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.alternatingLineto(0)
7547842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7557842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7567842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, curves
7577842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
7587842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rrcurveto(self, index):
7597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya dxb dyb dxc dyc}+ rrcurveto"""
7607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 6):
7627842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxa, dya, dxb, dyb, dxc, dyc, = args[i:i+6]
763489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dxa, dya), (dxb, dyb), (dxc, dyc))
7647842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7657842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rcurveline(self, index):
7667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya dxb dyb dxc dyc}+ dxd dyd rcurveline"""
7677842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7687842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args)-2, 6):
7697842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxb, dyb, dxc, dyc, dxd, dyd = args[i:i+6]
770489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dxb, dyb), (dxc, dyc), (dxd, dyd))
771489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rLineTo(args[-2:])
7727842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7737842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rlinecurve(self, index):
7747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""{dxa dya}+ dxb dyb dxc dyc dxd dyd rlinecurve"""
7757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7767842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lineArgs = args[:-6]
7777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(lineArgs), 2):
778489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rLineTo(lineArgs[i:i+2])
7797842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dxb, dyb, dxc, dyc, dxd, dyd = args[-6:]
780489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rCurveTo((dxb, dyb), (dxc, dyc), (dxd, dyd))
7817842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7827842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vvcurveto(self, index):
7837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"dx1? {dya dxb dyb dyc}+ vvcurveto"
7847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) % 2:
7867842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = args[0]
7877842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = args[1:]
7887842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
7897842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = 0
7907842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 4):
7917842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dya, dxb, dyb, dyc = args[i:i+4]
792489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dx1, dya), (dxb, dyb), (0, dyc))
7937842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dx1 = 0
7947842e56b97ce677b83bdab09cda48bc2d89ac75aJust
7957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hhcurveto(self, index):
7967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dy1? {dxa dxb dyb dxc}+ hhcurveto"""
7977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
7987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) % 2:
7997842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = args[0]
8007842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = args[1:]
8017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
8027842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = 0
8037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(0, len(args), 4):
8047842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxa, dxb, dyb, dxc = args[i:i+4]
805489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rCurveTo((dxa, dy1), (dxb, dyb), (dxc, 0))
8067842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dy1 = 0
8077842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vhcurveto(self, index):
8097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? vhcurveto (30)
8107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		{dya dxb dyb dxc dxd dxe dye dyf}+ dxf? vhcurveto
8117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""
8127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
8137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while args:
8147842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = self.vcurveto(args)
8157842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if args:
8167842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = self.hcurveto(args)
8177842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8187842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hvcurveto(self, index):
8197842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf?
8207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		{dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?
8217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""
8227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
8237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while args:
8247842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = self.hcurveto(args)
8257842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if args:
8267842e56b97ce677b83bdab09cda48bc2d89ac75aJust				args = self.vcurveto(args)
8277842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8287842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8297842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors, flex
8307842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hflex(self, index):
8328b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx1, dx2, dy2, dx3, dx4, dx5, dx6 = self.popall()
833d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr		dy1 = dy3 = dy4 = dy6 = 0
834d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr		dy5 = -dy2
8358b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx1, dy1), (dx2, dy2), (dx3, dy3))
8368b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx4, dy4), (dx5, dy5), (dx6, dy6))
8377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_flex(self, index):
8388b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4, dx5, dy5, dx6, dy6, fd = self.popall()
8398b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx1, dy1), (dx2, dy2), (dx3, dy3))
8408b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx4, dy4), (dx5, dy5), (dx6, dy6))
8417842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hflex1(self, index):
8428b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx1, dy1, dx2, dy2, dx3, dx4, dx5, dy5, dx6 = self.popall()
843d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr		dy3 = dy4 = 0
844d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr		dy6 = -(dy1 + dy2 + dy3 + dy4 + dy5)
845d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr
8468b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx1, dy1), (dx2, dy2), (dx3, dy3))
8478b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx4, dy4), (dx5, dy5), (dx6, dy6))
8487842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_flex1(self, index):
8498b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4, dx5, dy5, d6 = self.popall()
8508b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dx = dx1 + dx2 + dx3 + dx4 + dx5
8518b8b44904e116287ca0eb587f9c5b21296fb3123jvr		dy = dy1 + dy2 + dy3 + dy4 + dy5
8528b8b44904e116287ca0eb587f9c5b21296fb3123jvr		if abs(dx) > abs(dy):
8538b8b44904e116287ca0eb587f9c5b21296fb3123jvr			dx6 = d6
854d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr			dy6 = -dy
8558b8b44904e116287ca0eb587f9c5b21296fb3123jvr		else:
856d4561ec1b4ac67b2c29d0db13913431a3d2fbd50jvr			dx6 = -dx
8578b8b44904e116287ca0eb587f9c5b21296fb3123jvr			dy6 = d6
8588b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx1, dy1), (dx2, dy2), (dx3, dy3))
8598b8b44904e116287ca0eb587f9c5b21296fb3123jvr		self.rCurveTo((dx4, dy4), (dx5, dy5), (dx6, dy6))
8607842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8617842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8627842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# MultipleMaster. Well...
8637842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
8647842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_blend(self, index):
8658b8b44904e116287ca0eb587f9c5b21296fb3123jvr		args = self.popall()
8667842e56b97ce677b83bdab09cda48bc2d89ac75aJust
8677842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# misc
8687842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_and(self, index):
8698b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8707842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_or(self, index):
8718b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8727842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_not(self, index):
8738b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8747842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_store(self, index):
8758b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8767842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_abs(self, index):
8778b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8787842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_add(self, index):
8798b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8807842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sub(self, index):
8818b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8827842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_div(self, index):
8837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		num2 = self.pop()
8847842e56b97ce677b83bdab09cda48bc2d89ac75aJust		num1 = self.pop()
8857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		d1 = num1/num2
8867842e56b97ce677b83bdab09cda48bc2d89ac75aJust		d2 = float(num1)/num2
8877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if d1 == d2:
8887842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(d1)
8897842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
8907842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(d2)
8917842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_load(self, index):
8928b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_neg(self, index):
8948b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_eq(self, index):
8968b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8977842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_drop(self, index):
8988b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
8997842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_put(self, index):
9008b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_get(self, index):
9028b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_ifelse(self, index):
9048b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9057842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_random(self, index):
9068b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9077842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_mul(self, index):
9088b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9097842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sqrt(self, index):
9108b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_dup(self, index):
9128b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9137842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_exch(self, index):
9148b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9157842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_index(self, index):
9168b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9177842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_roll(self, index):
9188b8b44904e116287ca0eb587f9c5b21296fb3123jvr		raise NotImplementedError
9197842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9207842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
9217842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# miscelaneous helpers
9227842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
9237842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def alternatingLineto(self, isHorizontal):
9247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
9257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for arg in args:
9267842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if isHorizontal:
9277842e56b97ce677b83bdab09cda48bc2d89ac75aJust				point = (arg, 0)
9287842e56b97ce677b83bdab09cda48bc2d89ac75aJust			else:
9297842e56b97ce677b83bdab09cda48bc2d89ac75aJust				point = (0, arg)
930489d76a340845361def6af9ab7d9152f8e66f417jvr			self.rLineTo(point)
9317842e56b97ce677b83bdab09cda48bc2d89ac75aJust			isHorizontal = not isHorizontal
9327842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def vcurveto(self, args):
9347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dya, dxb, dyb, dxc = args[:4]
9357842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = args[4:]
9367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) == 1:
9377842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dyc = args[0]
9387842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
9397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
9407842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dyc = 0
941489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rCurveTo((0, dya), (dxb, dyb), (dxc, dyc))
9427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
9437842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9447842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def hcurveto(self, args):
9457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dxa, dxb, dyb, dyc = args[:4]
9467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = args[4:]
9477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if len(args) == 1:
9487842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxc = args[0]
9497842e56b97ce677b83bdab09cda48bc2d89ac75aJust			args = []
9507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
9517842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dxc = 0
952489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rCurveTo((dxa, 0), (dxb, dyb), (dxc, dyc))
9537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return args
9547842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9557842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9567842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass T1OutlineExtractor(T2OutlineExtractor):
9577842e56b97ce677b83bdab09cda48bc2d89ac75aJust
958489d76a340845361def6af9ab7d9152f8e66f417jvr	def __init__(self, pen, subrs):
959489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen = pen
9607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.subrs = subrs
9617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.reset()
9627842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9637842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def reset(self):
9647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.flexing = 0
9657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = 0
9667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.sbx = 0
9677842e56b97ce677b83bdab09cda48bc2d89ac75aJust		T2OutlineExtractor.reset(self)
9687842e56b97ce677b83bdab09cda48bc2d89ac75aJust
969d3ee2d4319742ec61cb299665ccba66c139e4834jvr	def endPath(self):
970d3ee2d4319742ec61cb299665ccba66c139e4834jvr		if self.sawMoveTo:
971d3ee2d4319742ec61cb299665ccba66c139e4834jvr			self.pen.endPath()
972d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.sawMoveTo = 0
973d3ee2d4319742ec61cb299665ccba66c139e4834jvr
9747842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popallWidth(self, evenOdd=0):
9757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.popall()
9767842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9777842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def exch(self):
9787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack = self.operandStack
9797842e56b97ce677b83bdab09cda48bc2d89ac75aJust		stack[-1], stack[-2] = stack[-2], stack[-1]
9807842e56b97ce677b83bdab09cda48bc2d89ac75aJust
9817842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
9827842e56b97ce677b83bdab09cda48bc2d89ac75aJust	# path constructors
9837842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
9847842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_rmoveto(self, index):
9857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
9867842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
987e56bc902cf6a707349ae6ddfe8a83a1bd7b155b9jvr		self.endPath()
988489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo(self.popall())
9897842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hmoveto(self, index):
9907842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
9917842e56b97ce677b83bdab09cda48bc2d89ac75aJust			# We must add a parameter to the stack if we are flexing
9927842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(0)
9937842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
994d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
995489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((self.popall()[0], 0))
9967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vmoveto(self, index):
9977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.flexing:
9987842e56b97ce677b83bdab09cda48bc2d89ac75aJust			# We must add a parameter to the stack if we are flexing
9997842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.push(0)
10007842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.exch()
10017842e56b97ce677b83bdab09cda48bc2d89ac75aJust			return
1002d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
1003489d76a340845361def6af9ab7d9152f8e66f417jvr		self.rMoveTo((0, self.popall()[0]))
10047842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_closepath(self, index):
10057842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.closePath()
10067842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_setcurrentpoint(self, index):
10077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		args = self.popall()
10087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		x, y = args
1009489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = x, y
10107842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_endchar(self, index):
1012d3ee2d4319742ec61cb299665ccba66c139e4834jvr		self.endPath()
10137842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hsbw(self, index):
10157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		sbx, wx = self.popall()
10167842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.width = wx
10177842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.sbx = sbx
1018489d76a340845361def6af9ab7d9152f8e66f417jvr		self.currentPoint = sbx, self.currentPoint[1]
10197842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_sbw(self, index):
10207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
10217842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10227842e56b97ce677b83bdab09cda48bc2d89ac75aJust	#
10237842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callsubr(self, index):
10247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
10257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subr = self.subrs[subrIndex]
10267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.execute(subr)
10277842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_callothersubr(self, index):
10287842e56b97ce677b83bdab09cda48bc2d89ac75aJust		subrIndex = self.pop()
10297842e56b97ce677b83bdab09cda48bc2d89ac75aJust		nArgs = self.pop()
10307842e56b97ce677b83bdab09cda48bc2d89ac75aJust		#print nArgs, subrIndex, "callothersubr"
10317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if subrIndex == 0 and nArgs == 3:
10327842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.doFlex()
10337842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.flexing = 0
10347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		elif subrIndex == 1 and nArgs == 0:
10357842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.flexing = 1
10367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# ignore...
10377842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_pop(self, index):
10387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		pass  # ignore...
10397842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def doFlex(self):
10417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		finaly = self.pop()
10427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		finalx = self.pop()
10437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.pop()	# flex height is unused
10447842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p3y = self.pop()
10467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p3x = self.pop()
10477842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp4y = self.pop()
10487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp4x = self.pop()
10497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp3y = self.pop()
10507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp3x = self.pop()
10517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p2y = self.pop()
10527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		p2x = self.pop()
10537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp2y = self.pop()
10547842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp2x = self.pop()
10557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp1y = self.pop()
10567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bcp1x = self.pop()
10577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		rpy = self.pop()
10587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		rpx = self.pop()
10597842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# call rrcurveto
10617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp1x+rpx)
10627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp1y+rpy)
10637842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp2x)
10647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp2y)
10657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p2x)
10667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p2y)
10677842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.op_rrcurveto(None)
10687842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10697842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# call rrcurveto
10707842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp3x)
10717842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp3y)
10727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp4x)
10737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(bcp4y)
10747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p3x)
10757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(p3y)
10767842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.op_rrcurveto(None)
10777842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10787842e56b97ce677b83bdab09cda48bc2d89ac75aJust		# Push back final coords so subr 0 can find them
10797842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(finalx)
10807842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.push(finaly)
10817842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10827842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_dotsection(self, index):
10837842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
10847842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_hstem3(self, index):
10857842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
10867842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_seac(self, index):
10877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"asb adx ady bchar achar seac"
1088489d76a340845361def6af9ab7d9152f8e66f417jvr		from fontTools.encodings.StandardEncoding import StandardEncoding
1089489d76a340845361def6af9ab7d9152f8e66f417jvr		asb, adx, ady, bchar, achar = self.popall()
1090489d76a340845361def6af9ab7d9152f8e66f417jvr		baseGlyph = StandardEncoding[bchar]
1091489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.addComponent(baseGlyph, (1, 0, 0, 1, 0, 0))
1092489d76a340845361def6af9ab7d9152f8e66f417jvr		accentGlyph = StandardEncoding[achar]
1093489d76a340845361def6af9ab7d9152f8e66f417jvr		adx = adx + self.sbx - asb  # seac weirdness
1094489d76a340845361def6af9ab7d9152f8e66f417jvr		self.pen.addComponent(accentGlyph, (1, 0, 0, 1, adx, ady))
10957842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def op_vstem3(self, index):
10967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.popall()  # XXX
10977842e56b97ce677b83bdab09cda48bc2d89ac75aJust
10987842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1099f2cf9c5d6d503e16ee43dc9b617d96aed38806a8jvrclass DictDecompiler(ByteCodeBase):
11007842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11017842e56b97ce677b83bdab09cda48bc2d89ac75aJust	operandEncoding = cffDictOperandEncoding
11027842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11037842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __init__(self, strings):
11047842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.stack = []
11057842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.strings = strings
11067842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.dict = {}
11077842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def getDict(self):
11097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		assert len(self.stack) == 0, "non-empty stack"
11107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.dict
11117842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self, data):
11137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		index = 0
11147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lenData = len(data)
11157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		push = self.stack.append
11167842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while index < lenData:
11177842e56b97ce677b83bdab09cda48bc2d89ac75aJust			b0 = ord(data[index])
11187842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index + 1
11197842e56b97ce677b83bdab09cda48bc2d89ac75aJust			code = self.operandEncoding[b0]
11207842e56b97ce677b83bdab09cda48bc2d89ac75aJust			handler = getattr(self, code)
11217842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value, index = handler(b0, data, index)
11227842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if value is not None:
11237842e56b97ce677b83bdab09cda48bc2d89ac75aJust				push(value)
11247842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11257842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def pop(self):
11267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		value = self.stack[-1]
11277842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.stack[-1]
11287842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return value
11297842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11307842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def popall(self):
11317842e56b97ce677b83bdab09cda48bc2d89ac75aJust		all = self.stack[:]
11327842e56b97ce677b83bdab09cda48bc2d89ac75aJust		del self.stack[:]
11337842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return all
11347842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def do_operator(self, b0, data, index):
11367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if b0 == 12:
11377842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = (b0, ord(data[index]))
11387842e56b97ce677b83bdab09cda48bc2d89ac75aJust			index = index+1
11397842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
11407842e56b97ce677b83bdab09cda48bc2d89ac75aJust			op = b0
11417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		operator, argType = self.operators[op]
11427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.handle_operator(operator, argType)
11437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return None, index
11447842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11457842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def handle_operator(self, operator, argType):
11467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if type(argType) == type(()):
11477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = ()
1148bf2f402913a2706dfa92190e60cba7acbf01c9d7jvr			for i in range(len(argType)-1, -1, -1):
1149bf2f402913a2706dfa92190e60cba7acbf01c9d7jvr				arg = argType[i]
11507842e56b97ce677b83bdab09cda48bc2d89ac75aJust				arghandler = getattr(self, "arg_" + arg)
11517842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value = (arghandler(operator),) + value
11527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
11537842e56b97ce677b83bdab09cda48bc2d89ac75aJust			arghandler = getattr(self, "arg_" + argType)
11547842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = arghandler(operator)
11557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.dict[operator] = value
11567842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11577842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_number(self, name):
11587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.pop()
11597842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_SID(self, name):
11607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.strings[self.pop()]
11617842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def arg_array(self, name):
11627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.popall()
1163dc18128aa9b3f6b98a623c294ac615195159025ejvr	def arg_delta(self, name):
1164dc18128aa9b3f6b98a623c294ac615195159025ejvr		out = []
1165dc18128aa9b3f6b98a623c294ac615195159025ejvr		current = 0
1166dc18128aa9b3f6b98a623c294ac615195159025ejvr		for v in self.popall():
11676f03a58f59fb20662602e3d4bb153d7db2f778d3jvr			current = current + v
1168dc18128aa9b3f6b98a623c294ac615195159025ejvr			out.append(current)
1169dc18128aa9b3f6b98a623c294ac615195159025ejvr		return out
11707842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11717842e56b97ce677b83bdab09cda48bc2d89ac75aJust
11727842e56b97ce677b83bdab09cda48bc2d89ac75aJustdef calcSubrBias(subrs):
11737842e56b97ce677b83bdab09cda48bc2d89ac75aJust	nSubrs = len(subrs)
11747842e56b97ce677b83bdab09cda48bc2d89ac75aJust	if nSubrs < 1240:
11757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 107
11767842e56b97ce677b83bdab09cda48bc2d89ac75aJust	elif nSubrs < 33900:
11777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 1131
11787842e56b97ce677b83bdab09cda48bc2d89ac75aJust	else:
11797842e56b97ce677b83bdab09cda48bc2d89ac75aJust		bias = 32768
11807842e56b97ce677b83bdab09cda48bc2d89ac75aJust	return bias
1181