11ae29591efbb29492ce05378909ccf4028d7c1eeBehdad Esfahbodfrom __future__ import print_function, division, absolute_import 27279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbodfrom fontTools.misc.py23 import * 3b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbodfrom fontTools.misc import eexec 4dc0ce0b498912287a557bdad58301ec7611c569eBehdad Esfahbodfrom .psOperators import * 57279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbodimport re 67279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbodimport collections 77279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbodfrom string import whitespace 8b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 9b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 10b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbodps_special = '()<>[]{}%' # / is one too, but we take care of that one differently 11b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 12b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad EsfahbodskipwhiteRE = re.compile("[%s]*" % whitespace) 13b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad EsfahbodendofthingPat = "[^][(){}<>/%%%s]*" % whitespace 14b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad EsfahbodendofthingRE = re.compile(endofthingPat) 15b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad EsfahbodcommentRE = re.compile("%[^\n\r]*") 16b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 17b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod# XXX This not entirely correct as it doesn't allow *nested* embedded parens: 18b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad EsfahbodstringPat = r""" 19b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod \( 20b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod ( 21b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod ( 22b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod [^()]* \ [()] 23b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod ) 24b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod | 25b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod ( 26b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod [^()]* \( [^()]* \) 27b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod ) 28b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod )* 29b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod [^()]* 30b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod \) 31b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod""" 32b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad EsfahbodstringPat = "".join(stringPat.split()) 33b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad EsfahbodstringRE = re.compile(stringPat) 34b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 35b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad EsfahbodhexstringRE = re.compile("<[%s0-9A-Fa-f]*>" % whitespace) 36b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 37b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbodclass PSTokenError(Exception): pass 38b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbodclass PSError(Exception): pass 39b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 40b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 417279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbodclass PSTokenizer(StringIO): 42b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 437279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod def getnexttoken(self, 44b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod # localize some stuff, for performance 45b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod len=len, 46b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod ps_special=ps_special, 47b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod stringmatch=stringRE.match, 48b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod hexstringmatch=hexstringRE.match, 49b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod commentmatch=commentRE.match, 50b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod endmatch=endofthingRE.match, 51b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod whitematch=skipwhiteRE.match): 52b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 53b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod _, nextpos = whitematch(self.buf, self.pos).span() 54b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.pos = nextpos 55b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if self.pos >= self.len: 56b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return None, None 57b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod pos = self.pos 58b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod buf = self.buf 59b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod char = buf[pos] 60b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if char in ps_special: 61b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if char in '{}[]': 62b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod tokentype = 'do_special' 63b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod token = char 64b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod elif char == '%': 65b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod tokentype = 'do_comment' 66b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod _, nextpos = commentmatch(buf, pos).span() 67b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod token = buf[pos:nextpos] 68b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod elif char == '(': 69b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod tokentype = 'do_string' 70b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod m = stringmatch(buf, pos) 71b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if m is None: 727279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod raise PSTokenError('bad string at character %d' % pos) 73b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod _, nextpos = m.span() 74b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod token = buf[pos:nextpos] 75b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod elif char == '<': 76b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod tokentype = 'do_hexstring' 77b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod m = hexstringmatch(buf, pos) 78b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if m is None: 797279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod raise PSTokenError('bad hexstring at character %d' % pos) 80b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod _, nextpos = m.span() 81b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod token = buf[pos:nextpos] 82b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 837279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod raise PSTokenError('bad token at character %d' % pos) 84b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 85b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if char == '/': 86b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod tokentype = 'do_literal' 87b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod m = endmatch(buf, pos+1) 88b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 89b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod tokentype = '' 90b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod m = endmatch(buf, pos) 91b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if m is None: 927279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod raise PSTokenError('bad token at character %d' % pos) 93b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod _, nextpos = m.span() 94b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod token = buf[pos:nextpos] 95b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.pos = pos + len(token) 96b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return tokentype, token 97b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 98b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def skipwhite(self, whitematch=skipwhiteRE.match): 99b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod _, nextpos = whitematch(self.buf, self.pos).span() 100b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.pos = nextpos 101b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 102b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def starteexec(self): 103b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.pos = self.pos + 1 104b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod #self.skipwhite() 105b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.dirtybuf = self.buf[self.pos:] 106b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.buf, R = eexec.decrypt(self.dirtybuf, 55665) 107b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.len = len(self.buf) 108b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.pos = 4 109b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 110b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def stopeexec(self): 111b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if not hasattr(self, 'dirtybuf'): 112b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return 113b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.buf = self.dirtybuf 114b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod del self.dirtybuf 115b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 116b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def flush(self): 117b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if self.buflist: 118b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.buf = self.buf + "".join(self.buflist) 119b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.buflist = [] 120b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 121b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 122b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbodclass PSInterpreter(PSOperators): 123b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 124b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def __init__(self): 125b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod systemdict = {} 126b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod userdict = {} 127b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.dictstack = [systemdict, userdict] 128b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.stack = [] 129b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.proclevel = 0 130b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.procmark = ps_procmark() 131b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.fillsystemdict() 132b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 133b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def fillsystemdict(self): 134b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod systemdict = self.dictstack[0] 135b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod systemdict['['] = systemdict['mark'] = self.mark = ps_mark() 136b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod systemdict[']'] = ps_operator(']', self.do_makearray) 137b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod systemdict['true'] = ps_boolean(1) 138b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod systemdict['false'] = ps_boolean(0) 139b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod systemdict['StandardEncoding'] = ps_array(ps_StandardEncoding) 140b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod systemdict['FontDirectory'] = ps_dict({}) 141b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.suckoperators(systemdict, self.__class__) 142b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 143b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def suckoperators(self, systemdict, klass): 144b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod for name in dir(klass): 145b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod attr = getattr(self, name) 1467279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod if isinstance(attr, collections.Callable) and name[:3] == 'ps_': 147b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod name = name[3:] 148b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod systemdict[name] = ps_operator(name, attr) 149b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod for baseclass in klass.__bases__: 150b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.suckoperators(systemdict, baseclass) 151b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 152b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def interpret(self, data, getattr = getattr): 153b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod tokenizer = self.tokenizer = PSTokenizer(data) 154b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod getnexttoken = tokenizer.getnexttoken 155b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod do_token = self.do_token 156b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod handle_object = self.handle_object 157b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod try: 158b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod while 1: 159b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod tokentype, token = getnexttoken() 160b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod #print token 161b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if not token: 162b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod break 163b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if tokentype: 164b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod handler = getattr(self, tokentype) 165b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod object = handler(token) 166b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 167b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod object = do_token(token) 168b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if object is not None: 169b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod handle_object(object) 170b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod tokenizer.close() 171b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.tokenizer = None 172b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod finally: 173b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if self.tokenizer is not None: 174b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if 0: 1757279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod print('ps error:\n- - - - - - -') 1767279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod print(self.tokenizer.buf[self.tokenizer.pos-50:self.tokenizer.pos]) 1777279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod print('>>>') 1787279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod print(self.tokenizer.buf[self.tokenizer.pos:self.tokenizer.pos+50]) 1797279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod print('- - - - - - -') 180b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 181b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def handle_object(self, object): 182b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if not (self.proclevel or object.literal or object.type == 'proceduretype'): 1837279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod if object.type != 'operatortype': 184b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod object = self.resolve_name(object.value) 185b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if object.literal: 186b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.push(object) 187b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 188b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if object.type == 'proceduretype': 189b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.call_procedure(object) 190b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 191b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod object.function() 192b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 193b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.push(object) 194b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 195b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def call_procedure(self, proc): 196b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod handle_object = self.handle_object 197b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod for item in proc.value: 198b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod handle_object(item) 199b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 200b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def resolve_name(self, name): 201b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod dictstack = self.dictstack 202b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod for i in range(len(dictstack)-1, -1, -1): 2037279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod if name in dictstack[i]: 204b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return dictstack[i][name] 2057279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod raise PSError('name error: ' + str(name)) 206b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 207b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def do_token(self, token, 208b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod int=int, 209b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod float=float, 210b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod ps_name=ps_name, 211b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod ps_integer=ps_integer, 212b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod ps_real=ps_real): 213b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod try: 214b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod num = int(token) 215b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod except (ValueError, OverflowError): 216b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod try: 217b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod num = float(token) 218b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod except (ValueError, OverflowError): 219b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if '#' in token: 220b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod hashpos = token.find('#') 221b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod try: 222b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod base = int(token[:hashpos]) 223b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod num = int(token[hashpos+1:], base) 224b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod except (ValueError, OverflowError): 225b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return ps_name(token) 226b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 227b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return ps_integer(num) 228b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 229b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return ps_name(token) 230b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 231b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return ps_real(num) 232b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 233b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return ps_integer(num) 234b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 235b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def do_comment(self, token): 236b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod pass 237b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 238b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def do_literal(self, token): 239b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return ps_literal(token[1:]) 240b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 241b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def do_string(self, token): 242b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return ps_string(token[1:-1]) 243b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 244b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def do_hexstring(self, token): 245b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod hexStr = "".join(token[1:-1].split()) 246b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if len(hexStr) % 2: 247b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod hexStr = hexStr + '0' 248b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod cleanstr = [] 249b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod for i in range(0, len(hexStr), 2): 250b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod cleanstr.append(chr(int(hexStr[i:i+2], 16))) 251b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod cleanstr = "".join(cleanstr) 252b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return ps_string(cleanstr) 253b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 254b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def do_special(self, token): 255b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if token == '{': 256b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.proclevel = self.proclevel + 1 257b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return self.procmark 258b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod elif token == '}': 259b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod proc = [] 260b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod while 1: 261b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod topobject = self.pop() 262b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if topobject == self.procmark: 263b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod break 264b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod proc.append(topobject) 265b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.proclevel = self.proclevel - 1 266b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod proc.reverse() 267b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return ps_procedure(proc) 268b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod elif token == '[': 269b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return self.mark 270b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod elif token == ']': 271b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return ps_name(']') 272b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 2737279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod raise PSTokenError('huh?') 274b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 275b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def push(self, object): 276b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.stack.append(object) 277b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 278b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def pop(self, *types): 279b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod stack = self.stack 280b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if not stack: 2817279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod raise PSError('stack underflow') 282b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod object = stack[-1] 283b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if types: 284b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if object.type not in types: 2857279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod raise PSError('typecheck, expected %s, found %s' % (repr(types), object.type)) 286b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod del stack[-1] 287b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return object 288b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 289b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def do_makearray(self): 290b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod array = [] 291b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod while 1: 292b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod topobject = self.pop() 293b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if topobject == self.mark: 294b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod break 295b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod array.append(topobject) 296b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod array.reverse() 297b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod self.push(ps_array(array)) 298b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 299b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod def close(self): 300b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod """Remove circular references.""" 301b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod del self.stack 302b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod del self.dictstack 303b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 304b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 305b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahboddef unpack_item(item): 306b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod tp = type(item.value) 3077279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod if tp == dict: 308b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod newitem = {} 309b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod for key, value in item.value.items(): 310b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod newitem[key] = unpack_item(value) 3117279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod elif tp == list: 312b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod newitem = [None] * len(item.value) 313b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod for i in range(len(item.value)): 314b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod newitem[i] = unpack_item(item.value[i]) 315b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if item.type == 'proceduretype': 316b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod newitem = tuple(newitem) 317b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 318b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod newitem = item.value 319b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return newitem 320b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 321b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahboddef suckfont(data): 322b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod import re 323dc0ce0b498912287a557bdad58301ec7611c569eBehdad Esfahbod m = re.search(br"/FontName\s+/([^ \t\n\r]+)\s+def", data) 324b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if m: 325b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod fontName = m.group(1) 326b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 327b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod fontName = None 328b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod interpreter = PSInterpreter() 329dc0ce0b498912287a557bdad58301ec7611c569eBehdad Esfahbod interpreter.interpret(b"/Helvetica 4 dict dup /Encoding StandardEncoding put definefont pop") 330b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod interpreter.interpret(data) 331b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod fontdir = interpreter.dictstack[0]['FontDirectory'].value 3327279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod if fontName in fontdir: 333b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod rawfont = fontdir[fontName] 334b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod else: 335b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod # fall back, in case fontName wasn't found 3367279302238a2d57d609cab45934615c4d959c88cBehdad Esfahbod fontNames = list(fontdir.keys()) 337b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if len(fontNames) > 1: 338b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod fontNames.remove("Helvetica") 339b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod fontNames.sort() 340b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod rawfont = fontdir[fontNames[0]] 341b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod interpreter.close() 342b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod return unpack_item(rawfont) 343b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 344b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod 345b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbodif __name__ == "__main__": 346b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod import EasyDialogs 347b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod path = EasyDialogs.AskFileForOpen() 348b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod if path: 349b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod from fontTools import t1Lib 350b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod data, kind = t1Lib.read(path) 351b49aa66e6192a66330b19187d18e9c39c5a0caf3Behdad Esfahbod font = suckfont(data) 352