1*e1fe3e4aSElliott Hughes_accessstrings = {0: "", 1: "readonly", 2: "executeonly", 3: "noaccess"} 2*e1fe3e4aSElliott Hughes 3*e1fe3e4aSElliott Hughes 4*e1fe3e4aSElliott Hughesclass ps_object(object): 5*e1fe3e4aSElliott Hughes literal = 1 6*e1fe3e4aSElliott Hughes access = 0 7*e1fe3e4aSElliott Hughes value = None 8*e1fe3e4aSElliott Hughes 9*e1fe3e4aSElliott Hughes def __init__(self, value): 10*e1fe3e4aSElliott Hughes self.value = value 11*e1fe3e4aSElliott Hughes self.type = self.__class__.__name__[3:] + "type" 12*e1fe3e4aSElliott Hughes 13*e1fe3e4aSElliott Hughes def __repr__(self): 14*e1fe3e4aSElliott Hughes return "<%s %s>" % (self.__class__.__name__[3:], repr(self.value)) 15*e1fe3e4aSElliott Hughes 16*e1fe3e4aSElliott Hughes 17*e1fe3e4aSElliott Hughesclass ps_operator(ps_object): 18*e1fe3e4aSElliott Hughes literal = 0 19*e1fe3e4aSElliott Hughes 20*e1fe3e4aSElliott Hughes def __init__(self, name, function): 21*e1fe3e4aSElliott Hughes self.name = name 22*e1fe3e4aSElliott Hughes self.function = function 23*e1fe3e4aSElliott Hughes self.type = self.__class__.__name__[3:] + "type" 24*e1fe3e4aSElliott Hughes 25*e1fe3e4aSElliott Hughes def __repr__(self): 26*e1fe3e4aSElliott Hughes return "<operator %s>" % self.name 27*e1fe3e4aSElliott Hughes 28*e1fe3e4aSElliott Hughes 29*e1fe3e4aSElliott Hughesclass ps_procedure(ps_object): 30*e1fe3e4aSElliott Hughes literal = 0 31*e1fe3e4aSElliott Hughes 32*e1fe3e4aSElliott Hughes def __repr__(self): 33*e1fe3e4aSElliott Hughes return "<procedure>" 34*e1fe3e4aSElliott Hughes 35*e1fe3e4aSElliott Hughes def __str__(self): 36*e1fe3e4aSElliott Hughes psstring = "{" 37*e1fe3e4aSElliott Hughes for i in range(len(self.value)): 38*e1fe3e4aSElliott Hughes if i: 39*e1fe3e4aSElliott Hughes psstring = psstring + " " + str(self.value[i]) 40*e1fe3e4aSElliott Hughes else: 41*e1fe3e4aSElliott Hughes psstring = psstring + str(self.value[i]) 42*e1fe3e4aSElliott Hughes return psstring + "}" 43*e1fe3e4aSElliott Hughes 44*e1fe3e4aSElliott Hughes 45*e1fe3e4aSElliott Hughesclass ps_name(ps_object): 46*e1fe3e4aSElliott Hughes literal = 0 47*e1fe3e4aSElliott Hughes 48*e1fe3e4aSElliott Hughes def __str__(self): 49*e1fe3e4aSElliott Hughes if self.literal: 50*e1fe3e4aSElliott Hughes return "/" + self.value 51*e1fe3e4aSElliott Hughes else: 52*e1fe3e4aSElliott Hughes return self.value 53*e1fe3e4aSElliott Hughes 54*e1fe3e4aSElliott Hughes 55*e1fe3e4aSElliott Hughesclass ps_literal(ps_object): 56*e1fe3e4aSElliott Hughes def __str__(self): 57*e1fe3e4aSElliott Hughes return "/" + self.value 58*e1fe3e4aSElliott Hughes 59*e1fe3e4aSElliott Hughes 60*e1fe3e4aSElliott Hughesclass ps_array(ps_object): 61*e1fe3e4aSElliott Hughes def __str__(self): 62*e1fe3e4aSElliott Hughes psstring = "[" 63*e1fe3e4aSElliott Hughes for i in range(len(self.value)): 64*e1fe3e4aSElliott Hughes item = self.value[i] 65*e1fe3e4aSElliott Hughes access = _accessstrings[item.access] 66*e1fe3e4aSElliott Hughes if access: 67*e1fe3e4aSElliott Hughes access = " " + access 68*e1fe3e4aSElliott Hughes if i: 69*e1fe3e4aSElliott Hughes psstring = psstring + " " + str(item) + access 70*e1fe3e4aSElliott Hughes else: 71*e1fe3e4aSElliott Hughes psstring = psstring + str(item) + access 72*e1fe3e4aSElliott Hughes return psstring + "]" 73*e1fe3e4aSElliott Hughes 74*e1fe3e4aSElliott Hughes def __repr__(self): 75*e1fe3e4aSElliott Hughes return "<array>" 76*e1fe3e4aSElliott Hughes 77*e1fe3e4aSElliott Hughes 78*e1fe3e4aSElliott Hughes_type1_pre_eexec_order = [ 79*e1fe3e4aSElliott Hughes "FontInfo", 80*e1fe3e4aSElliott Hughes "FontName", 81*e1fe3e4aSElliott Hughes "Encoding", 82*e1fe3e4aSElliott Hughes "PaintType", 83*e1fe3e4aSElliott Hughes "FontType", 84*e1fe3e4aSElliott Hughes "FontMatrix", 85*e1fe3e4aSElliott Hughes "FontBBox", 86*e1fe3e4aSElliott Hughes "UniqueID", 87*e1fe3e4aSElliott Hughes "Metrics", 88*e1fe3e4aSElliott Hughes "StrokeWidth", 89*e1fe3e4aSElliott Hughes] 90*e1fe3e4aSElliott Hughes 91*e1fe3e4aSElliott Hughes_type1_fontinfo_order = [ 92*e1fe3e4aSElliott Hughes "version", 93*e1fe3e4aSElliott Hughes "Notice", 94*e1fe3e4aSElliott Hughes "FullName", 95*e1fe3e4aSElliott Hughes "FamilyName", 96*e1fe3e4aSElliott Hughes "Weight", 97*e1fe3e4aSElliott Hughes "ItalicAngle", 98*e1fe3e4aSElliott Hughes "isFixedPitch", 99*e1fe3e4aSElliott Hughes "UnderlinePosition", 100*e1fe3e4aSElliott Hughes "UnderlineThickness", 101*e1fe3e4aSElliott Hughes] 102*e1fe3e4aSElliott Hughes 103*e1fe3e4aSElliott Hughes_type1_post_eexec_order = ["Private", "CharStrings", "FID"] 104*e1fe3e4aSElliott Hughes 105*e1fe3e4aSElliott Hughes 106*e1fe3e4aSElliott Hughesdef _type1_item_repr(key, value): 107*e1fe3e4aSElliott Hughes psstring = "" 108*e1fe3e4aSElliott Hughes access = _accessstrings[value.access] 109*e1fe3e4aSElliott Hughes if access: 110*e1fe3e4aSElliott Hughes access = access + " " 111*e1fe3e4aSElliott Hughes if key == "CharStrings": 112*e1fe3e4aSElliott Hughes psstring = psstring + "/%s %s def\n" % ( 113*e1fe3e4aSElliott Hughes key, 114*e1fe3e4aSElliott Hughes _type1_CharString_repr(value.value), 115*e1fe3e4aSElliott Hughes ) 116*e1fe3e4aSElliott Hughes elif key == "Encoding": 117*e1fe3e4aSElliott Hughes psstring = psstring + _type1_Encoding_repr(value, access) 118*e1fe3e4aSElliott Hughes else: 119*e1fe3e4aSElliott Hughes psstring = psstring + "/%s %s %sdef\n" % (str(key), str(value), access) 120*e1fe3e4aSElliott Hughes return psstring 121*e1fe3e4aSElliott Hughes 122*e1fe3e4aSElliott Hughes 123*e1fe3e4aSElliott Hughesdef _type1_Encoding_repr(encoding, access): 124*e1fe3e4aSElliott Hughes encoding = encoding.value 125*e1fe3e4aSElliott Hughes psstring = "/Encoding 256 array\n0 1 255 {1 index exch /.notdef put} for\n" 126*e1fe3e4aSElliott Hughes for i in range(256): 127*e1fe3e4aSElliott Hughes name = encoding[i].value 128*e1fe3e4aSElliott Hughes if name != ".notdef": 129*e1fe3e4aSElliott Hughes psstring = psstring + "dup %d /%s put\n" % (i, name) 130*e1fe3e4aSElliott Hughes return psstring + access + "def\n" 131*e1fe3e4aSElliott Hughes 132*e1fe3e4aSElliott Hughes 133*e1fe3e4aSElliott Hughesdef _type1_CharString_repr(charstrings): 134*e1fe3e4aSElliott Hughes items = sorted(charstrings.items()) 135*e1fe3e4aSElliott Hughes return "xxx" 136*e1fe3e4aSElliott Hughes 137*e1fe3e4aSElliott Hughes 138*e1fe3e4aSElliott Hughesclass ps_font(ps_object): 139*e1fe3e4aSElliott Hughes def __str__(self): 140*e1fe3e4aSElliott Hughes psstring = "%d dict dup begin\n" % len(self.value) 141*e1fe3e4aSElliott Hughes for key in _type1_pre_eexec_order: 142*e1fe3e4aSElliott Hughes try: 143*e1fe3e4aSElliott Hughes value = self.value[key] 144*e1fe3e4aSElliott Hughes except KeyError: 145*e1fe3e4aSElliott Hughes pass 146*e1fe3e4aSElliott Hughes else: 147*e1fe3e4aSElliott Hughes psstring = psstring + _type1_item_repr(key, value) 148*e1fe3e4aSElliott Hughes items = sorted(self.value.items()) 149*e1fe3e4aSElliott Hughes for key, value in items: 150*e1fe3e4aSElliott Hughes if key not in _type1_pre_eexec_order + _type1_post_eexec_order: 151*e1fe3e4aSElliott Hughes psstring = psstring + _type1_item_repr(key, value) 152*e1fe3e4aSElliott Hughes psstring = psstring + "currentdict end\ncurrentfile eexec\ndup " 153*e1fe3e4aSElliott Hughes for key in _type1_post_eexec_order: 154*e1fe3e4aSElliott Hughes try: 155*e1fe3e4aSElliott Hughes value = self.value[key] 156*e1fe3e4aSElliott Hughes except KeyError: 157*e1fe3e4aSElliott Hughes pass 158*e1fe3e4aSElliott Hughes else: 159*e1fe3e4aSElliott Hughes psstring = psstring + _type1_item_repr(key, value) 160*e1fe3e4aSElliott Hughes return ( 161*e1fe3e4aSElliott Hughes psstring 162*e1fe3e4aSElliott Hughes + "dup/FontName get exch definefont pop\nmark currentfile closefile\n" 163*e1fe3e4aSElliott Hughes + 8 * (64 * "0" + "\n") 164*e1fe3e4aSElliott Hughes + "cleartomark" 165*e1fe3e4aSElliott Hughes + "\n" 166*e1fe3e4aSElliott Hughes ) 167*e1fe3e4aSElliott Hughes 168*e1fe3e4aSElliott Hughes def __repr__(self): 169*e1fe3e4aSElliott Hughes return "<font>" 170*e1fe3e4aSElliott Hughes 171*e1fe3e4aSElliott Hughes 172*e1fe3e4aSElliott Hughesclass ps_file(ps_object): 173*e1fe3e4aSElliott Hughes pass 174*e1fe3e4aSElliott Hughes 175*e1fe3e4aSElliott Hughes 176*e1fe3e4aSElliott Hughesclass ps_dict(ps_object): 177*e1fe3e4aSElliott Hughes def __str__(self): 178*e1fe3e4aSElliott Hughes psstring = "%d dict dup begin\n" % len(self.value) 179*e1fe3e4aSElliott Hughes items = sorted(self.value.items()) 180*e1fe3e4aSElliott Hughes for key, value in items: 181*e1fe3e4aSElliott Hughes access = _accessstrings[value.access] 182*e1fe3e4aSElliott Hughes if access: 183*e1fe3e4aSElliott Hughes access = access + " " 184*e1fe3e4aSElliott Hughes psstring = psstring + "/%s %s %sdef\n" % (str(key), str(value), access) 185*e1fe3e4aSElliott Hughes return psstring + "end " 186*e1fe3e4aSElliott Hughes 187*e1fe3e4aSElliott Hughes def __repr__(self): 188*e1fe3e4aSElliott Hughes return "<dict>" 189*e1fe3e4aSElliott Hughes 190*e1fe3e4aSElliott Hughes 191*e1fe3e4aSElliott Hughesclass ps_mark(ps_object): 192*e1fe3e4aSElliott Hughes def __init__(self): 193*e1fe3e4aSElliott Hughes self.value = "mark" 194*e1fe3e4aSElliott Hughes self.type = self.__class__.__name__[3:] + "type" 195*e1fe3e4aSElliott Hughes 196*e1fe3e4aSElliott Hughes 197*e1fe3e4aSElliott Hughesclass ps_procmark(ps_object): 198*e1fe3e4aSElliott Hughes def __init__(self): 199*e1fe3e4aSElliott Hughes self.value = "procmark" 200*e1fe3e4aSElliott Hughes self.type = self.__class__.__name__[3:] + "type" 201*e1fe3e4aSElliott Hughes 202*e1fe3e4aSElliott Hughes 203*e1fe3e4aSElliott Hughesclass ps_null(ps_object): 204*e1fe3e4aSElliott Hughes def __init__(self): 205*e1fe3e4aSElliott Hughes self.type = self.__class__.__name__[3:] + "type" 206*e1fe3e4aSElliott Hughes 207*e1fe3e4aSElliott Hughes 208*e1fe3e4aSElliott Hughesclass ps_boolean(ps_object): 209*e1fe3e4aSElliott Hughes def __str__(self): 210*e1fe3e4aSElliott Hughes if self.value: 211*e1fe3e4aSElliott Hughes return "true" 212*e1fe3e4aSElliott Hughes else: 213*e1fe3e4aSElliott Hughes return "false" 214*e1fe3e4aSElliott Hughes 215*e1fe3e4aSElliott Hughes 216*e1fe3e4aSElliott Hughesclass ps_string(ps_object): 217*e1fe3e4aSElliott Hughes def __str__(self): 218*e1fe3e4aSElliott Hughes return "(%s)" % repr(self.value)[1:-1] 219*e1fe3e4aSElliott Hughes 220*e1fe3e4aSElliott Hughes 221*e1fe3e4aSElliott Hughesclass ps_integer(ps_object): 222*e1fe3e4aSElliott Hughes def __str__(self): 223*e1fe3e4aSElliott Hughes return repr(self.value) 224*e1fe3e4aSElliott Hughes 225*e1fe3e4aSElliott Hughes 226*e1fe3e4aSElliott Hughesclass ps_real(ps_object): 227*e1fe3e4aSElliott Hughes def __str__(self): 228*e1fe3e4aSElliott Hughes return repr(self.value) 229*e1fe3e4aSElliott Hughes 230*e1fe3e4aSElliott Hughes 231*e1fe3e4aSElliott Hughesclass PSOperators(object): 232*e1fe3e4aSElliott Hughes def ps_def(self): 233*e1fe3e4aSElliott Hughes obj = self.pop() 234*e1fe3e4aSElliott Hughes name = self.pop() 235*e1fe3e4aSElliott Hughes self.dictstack[-1][name.value] = obj 236*e1fe3e4aSElliott Hughes 237*e1fe3e4aSElliott Hughes def ps_bind(self): 238*e1fe3e4aSElliott Hughes proc = self.pop("proceduretype") 239*e1fe3e4aSElliott Hughes self.proc_bind(proc) 240*e1fe3e4aSElliott Hughes self.push(proc) 241*e1fe3e4aSElliott Hughes 242*e1fe3e4aSElliott Hughes def proc_bind(self, proc): 243*e1fe3e4aSElliott Hughes for i in range(len(proc.value)): 244*e1fe3e4aSElliott Hughes item = proc.value[i] 245*e1fe3e4aSElliott Hughes if item.type == "proceduretype": 246*e1fe3e4aSElliott Hughes self.proc_bind(item) 247*e1fe3e4aSElliott Hughes else: 248*e1fe3e4aSElliott Hughes if not item.literal: 249*e1fe3e4aSElliott Hughes try: 250*e1fe3e4aSElliott Hughes obj = self.resolve_name(item.value) 251*e1fe3e4aSElliott Hughes except: 252*e1fe3e4aSElliott Hughes pass 253*e1fe3e4aSElliott Hughes else: 254*e1fe3e4aSElliott Hughes if obj.type == "operatortype": 255*e1fe3e4aSElliott Hughes proc.value[i] = obj 256*e1fe3e4aSElliott Hughes 257*e1fe3e4aSElliott Hughes def ps_exch(self): 258*e1fe3e4aSElliott Hughes if len(self.stack) < 2: 259*e1fe3e4aSElliott Hughes raise RuntimeError("stack underflow") 260*e1fe3e4aSElliott Hughes obj1 = self.pop() 261*e1fe3e4aSElliott Hughes obj2 = self.pop() 262*e1fe3e4aSElliott Hughes self.push(obj1) 263*e1fe3e4aSElliott Hughes self.push(obj2) 264*e1fe3e4aSElliott Hughes 265*e1fe3e4aSElliott Hughes def ps_dup(self): 266*e1fe3e4aSElliott Hughes if not self.stack: 267*e1fe3e4aSElliott Hughes raise RuntimeError("stack underflow") 268*e1fe3e4aSElliott Hughes self.push(self.stack[-1]) 269*e1fe3e4aSElliott Hughes 270*e1fe3e4aSElliott Hughes def ps_exec(self): 271*e1fe3e4aSElliott Hughes obj = self.pop() 272*e1fe3e4aSElliott Hughes if obj.type == "proceduretype": 273*e1fe3e4aSElliott Hughes self.call_procedure(obj) 274*e1fe3e4aSElliott Hughes else: 275*e1fe3e4aSElliott Hughes self.handle_object(obj) 276*e1fe3e4aSElliott Hughes 277*e1fe3e4aSElliott Hughes def ps_count(self): 278*e1fe3e4aSElliott Hughes self.push(ps_integer(len(self.stack))) 279*e1fe3e4aSElliott Hughes 280*e1fe3e4aSElliott Hughes def ps_eq(self): 281*e1fe3e4aSElliott Hughes any1 = self.pop() 282*e1fe3e4aSElliott Hughes any2 = self.pop() 283*e1fe3e4aSElliott Hughes self.push(ps_boolean(any1.value == any2.value)) 284*e1fe3e4aSElliott Hughes 285*e1fe3e4aSElliott Hughes def ps_ne(self): 286*e1fe3e4aSElliott Hughes any1 = self.pop() 287*e1fe3e4aSElliott Hughes any2 = self.pop() 288*e1fe3e4aSElliott Hughes self.push(ps_boolean(any1.value != any2.value)) 289*e1fe3e4aSElliott Hughes 290*e1fe3e4aSElliott Hughes def ps_cvx(self): 291*e1fe3e4aSElliott Hughes obj = self.pop() 292*e1fe3e4aSElliott Hughes obj.literal = 0 293*e1fe3e4aSElliott Hughes self.push(obj) 294*e1fe3e4aSElliott Hughes 295*e1fe3e4aSElliott Hughes def ps_matrix(self): 296*e1fe3e4aSElliott Hughes matrix = [ 297*e1fe3e4aSElliott Hughes ps_real(1.0), 298*e1fe3e4aSElliott Hughes ps_integer(0), 299*e1fe3e4aSElliott Hughes ps_integer(0), 300*e1fe3e4aSElliott Hughes ps_real(1.0), 301*e1fe3e4aSElliott Hughes ps_integer(0), 302*e1fe3e4aSElliott Hughes ps_integer(0), 303*e1fe3e4aSElliott Hughes ] 304*e1fe3e4aSElliott Hughes self.push(ps_array(matrix)) 305*e1fe3e4aSElliott Hughes 306*e1fe3e4aSElliott Hughes def ps_string(self): 307*e1fe3e4aSElliott Hughes num = self.pop("integertype").value 308*e1fe3e4aSElliott Hughes self.push(ps_string("\0" * num)) 309*e1fe3e4aSElliott Hughes 310*e1fe3e4aSElliott Hughes def ps_type(self): 311*e1fe3e4aSElliott Hughes obj = self.pop() 312*e1fe3e4aSElliott Hughes self.push(ps_string(obj.type)) 313*e1fe3e4aSElliott Hughes 314*e1fe3e4aSElliott Hughes def ps_store(self): 315*e1fe3e4aSElliott Hughes value = self.pop() 316*e1fe3e4aSElliott Hughes key = self.pop() 317*e1fe3e4aSElliott Hughes name = key.value 318*e1fe3e4aSElliott Hughes for i in range(len(self.dictstack) - 1, -1, -1): 319*e1fe3e4aSElliott Hughes if name in self.dictstack[i]: 320*e1fe3e4aSElliott Hughes self.dictstack[i][name] = value 321*e1fe3e4aSElliott Hughes break 322*e1fe3e4aSElliott Hughes self.dictstack[-1][name] = value 323*e1fe3e4aSElliott Hughes 324*e1fe3e4aSElliott Hughes def ps_where(self): 325*e1fe3e4aSElliott Hughes name = self.pop() 326*e1fe3e4aSElliott Hughes # XXX 327*e1fe3e4aSElliott Hughes self.push(ps_boolean(0)) 328*e1fe3e4aSElliott Hughes 329*e1fe3e4aSElliott Hughes def ps_systemdict(self): 330*e1fe3e4aSElliott Hughes self.push(ps_dict(self.dictstack[0])) 331*e1fe3e4aSElliott Hughes 332*e1fe3e4aSElliott Hughes def ps_userdict(self): 333*e1fe3e4aSElliott Hughes self.push(ps_dict(self.dictstack[1])) 334*e1fe3e4aSElliott Hughes 335*e1fe3e4aSElliott Hughes def ps_currentdict(self): 336*e1fe3e4aSElliott Hughes self.push(ps_dict(self.dictstack[-1])) 337*e1fe3e4aSElliott Hughes 338*e1fe3e4aSElliott Hughes def ps_currentfile(self): 339*e1fe3e4aSElliott Hughes self.push(ps_file(self.tokenizer)) 340*e1fe3e4aSElliott Hughes 341*e1fe3e4aSElliott Hughes def ps_eexec(self): 342*e1fe3e4aSElliott Hughes f = self.pop("filetype").value 343*e1fe3e4aSElliott Hughes f.starteexec() 344*e1fe3e4aSElliott Hughes 345*e1fe3e4aSElliott Hughes def ps_closefile(self): 346*e1fe3e4aSElliott Hughes f = self.pop("filetype").value 347*e1fe3e4aSElliott Hughes f.skipwhite() 348*e1fe3e4aSElliott Hughes f.stopeexec() 349*e1fe3e4aSElliott Hughes 350*e1fe3e4aSElliott Hughes def ps_cleartomark(self): 351*e1fe3e4aSElliott Hughes obj = self.pop() 352*e1fe3e4aSElliott Hughes while obj != self.mark: 353*e1fe3e4aSElliott Hughes obj = self.pop() 354*e1fe3e4aSElliott Hughes 355*e1fe3e4aSElliott Hughes def ps_readstring(self, ps_boolean=ps_boolean, len=len): 356*e1fe3e4aSElliott Hughes s = self.pop("stringtype") 357*e1fe3e4aSElliott Hughes oldstr = s.value 358*e1fe3e4aSElliott Hughes f = self.pop("filetype") 359*e1fe3e4aSElliott Hughes # pad = file.value.read(1) 360*e1fe3e4aSElliott Hughes # for StringIO, this is faster 361*e1fe3e4aSElliott Hughes f.value.pos = f.value.pos + 1 362*e1fe3e4aSElliott Hughes newstr = f.value.read(len(oldstr)) 363*e1fe3e4aSElliott Hughes s.value = newstr 364*e1fe3e4aSElliott Hughes self.push(s) 365*e1fe3e4aSElliott Hughes self.push(ps_boolean(len(oldstr) == len(newstr))) 366*e1fe3e4aSElliott Hughes 367*e1fe3e4aSElliott Hughes def ps_known(self): 368*e1fe3e4aSElliott Hughes key = self.pop() 369*e1fe3e4aSElliott Hughes d = self.pop("dicttype", "fonttype") 370*e1fe3e4aSElliott Hughes self.push(ps_boolean(key.value in d.value)) 371*e1fe3e4aSElliott Hughes 372*e1fe3e4aSElliott Hughes def ps_if(self): 373*e1fe3e4aSElliott Hughes proc = self.pop("proceduretype") 374*e1fe3e4aSElliott Hughes if self.pop("booleantype").value: 375*e1fe3e4aSElliott Hughes self.call_procedure(proc) 376*e1fe3e4aSElliott Hughes 377*e1fe3e4aSElliott Hughes def ps_ifelse(self): 378*e1fe3e4aSElliott Hughes proc2 = self.pop("proceduretype") 379*e1fe3e4aSElliott Hughes proc1 = self.pop("proceduretype") 380*e1fe3e4aSElliott Hughes if self.pop("booleantype").value: 381*e1fe3e4aSElliott Hughes self.call_procedure(proc1) 382*e1fe3e4aSElliott Hughes else: 383*e1fe3e4aSElliott Hughes self.call_procedure(proc2) 384*e1fe3e4aSElliott Hughes 385*e1fe3e4aSElliott Hughes def ps_readonly(self): 386*e1fe3e4aSElliott Hughes obj = self.pop() 387*e1fe3e4aSElliott Hughes if obj.access < 1: 388*e1fe3e4aSElliott Hughes obj.access = 1 389*e1fe3e4aSElliott Hughes self.push(obj) 390*e1fe3e4aSElliott Hughes 391*e1fe3e4aSElliott Hughes def ps_executeonly(self): 392*e1fe3e4aSElliott Hughes obj = self.pop() 393*e1fe3e4aSElliott Hughes if obj.access < 2: 394*e1fe3e4aSElliott Hughes obj.access = 2 395*e1fe3e4aSElliott Hughes self.push(obj) 396*e1fe3e4aSElliott Hughes 397*e1fe3e4aSElliott Hughes def ps_noaccess(self): 398*e1fe3e4aSElliott Hughes obj = self.pop() 399*e1fe3e4aSElliott Hughes if obj.access < 3: 400*e1fe3e4aSElliott Hughes obj.access = 3 401*e1fe3e4aSElliott Hughes self.push(obj) 402*e1fe3e4aSElliott Hughes 403*e1fe3e4aSElliott Hughes def ps_not(self): 404*e1fe3e4aSElliott Hughes obj = self.pop("booleantype", "integertype") 405*e1fe3e4aSElliott Hughes if obj.type == "booleantype": 406*e1fe3e4aSElliott Hughes self.push(ps_boolean(not obj.value)) 407*e1fe3e4aSElliott Hughes else: 408*e1fe3e4aSElliott Hughes self.push(ps_integer(~obj.value)) 409*e1fe3e4aSElliott Hughes 410*e1fe3e4aSElliott Hughes def ps_print(self): 411*e1fe3e4aSElliott Hughes str = self.pop("stringtype") 412*e1fe3e4aSElliott Hughes print("PS output --->", str.value) 413*e1fe3e4aSElliott Hughes 414*e1fe3e4aSElliott Hughes def ps_anchorsearch(self): 415*e1fe3e4aSElliott Hughes seek = self.pop("stringtype") 416*e1fe3e4aSElliott Hughes s = self.pop("stringtype") 417*e1fe3e4aSElliott Hughes seeklen = len(seek.value) 418*e1fe3e4aSElliott Hughes if s.value[:seeklen] == seek.value: 419*e1fe3e4aSElliott Hughes self.push(ps_string(s.value[seeklen:])) 420*e1fe3e4aSElliott Hughes self.push(seek) 421*e1fe3e4aSElliott Hughes self.push(ps_boolean(1)) 422*e1fe3e4aSElliott Hughes else: 423*e1fe3e4aSElliott Hughes self.push(s) 424*e1fe3e4aSElliott Hughes self.push(ps_boolean(0)) 425*e1fe3e4aSElliott Hughes 426*e1fe3e4aSElliott Hughes def ps_array(self): 427*e1fe3e4aSElliott Hughes num = self.pop("integertype") 428*e1fe3e4aSElliott Hughes array = ps_array([None] * num.value) 429*e1fe3e4aSElliott Hughes self.push(array) 430*e1fe3e4aSElliott Hughes 431*e1fe3e4aSElliott Hughes def ps_astore(self): 432*e1fe3e4aSElliott Hughes array = self.pop("arraytype") 433*e1fe3e4aSElliott Hughes for i in range(len(array.value) - 1, -1, -1): 434*e1fe3e4aSElliott Hughes array.value[i] = self.pop() 435*e1fe3e4aSElliott Hughes self.push(array) 436*e1fe3e4aSElliott Hughes 437*e1fe3e4aSElliott Hughes def ps_load(self): 438*e1fe3e4aSElliott Hughes name = self.pop() 439*e1fe3e4aSElliott Hughes self.push(self.resolve_name(name.value)) 440*e1fe3e4aSElliott Hughes 441*e1fe3e4aSElliott Hughes def ps_put(self): 442*e1fe3e4aSElliott Hughes obj1 = self.pop() 443*e1fe3e4aSElliott Hughes obj2 = self.pop() 444*e1fe3e4aSElliott Hughes obj3 = self.pop("arraytype", "dicttype", "stringtype", "proceduretype") 445*e1fe3e4aSElliott Hughes tp = obj3.type 446*e1fe3e4aSElliott Hughes if tp == "arraytype" or tp == "proceduretype": 447*e1fe3e4aSElliott Hughes obj3.value[obj2.value] = obj1 448*e1fe3e4aSElliott Hughes elif tp == "dicttype": 449*e1fe3e4aSElliott Hughes obj3.value[obj2.value] = obj1 450*e1fe3e4aSElliott Hughes elif tp == "stringtype": 451*e1fe3e4aSElliott Hughes index = obj2.value 452*e1fe3e4aSElliott Hughes obj3.value = obj3.value[:index] + chr(obj1.value) + obj3.value[index + 1 :] 453*e1fe3e4aSElliott Hughes 454*e1fe3e4aSElliott Hughes def ps_get(self): 455*e1fe3e4aSElliott Hughes obj1 = self.pop() 456*e1fe3e4aSElliott Hughes if obj1.value == "Encoding": 457*e1fe3e4aSElliott Hughes pass 458*e1fe3e4aSElliott Hughes obj2 = self.pop( 459*e1fe3e4aSElliott Hughes "arraytype", "dicttype", "stringtype", "proceduretype", "fonttype" 460*e1fe3e4aSElliott Hughes ) 461*e1fe3e4aSElliott Hughes tp = obj2.type 462*e1fe3e4aSElliott Hughes if tp in ("arraytype", "proceduretype"): 463*e1fe3e4aSElliott Hughes self.push(obj2.value[obj1.value]) 464*e1fe3e4aSElliott Hughes elif tp in ("dicttype", "fonttype"): 465*e1fe3e4aSElliott Hughes self.push(obj2.value[obj1.value]) 466*e1fe3e4aSElliott Hughes elif tp == "stringtype": 467*e1fe3e4aSElliott Hughes self.push(ps_integer(ord(obj2.value[obj1.value]))) 468*e1fe3e4aSElliott Hughes else: 469*e1fe3e4aSElliott Hughes assert False, "shouldn't get here" 470*e1fe3e4aSElliott Hughes 471*e1fe3e4aSElliott Hughes def ps_getinterval(self): 472*e1fe3e4aSElliott Hughes obj1 = self.pop("integertype") 473*e1fe3e4aSElliott Hughes obj2 = self.pop("integertype") 474*e1fe3e4aSElliott Hughes obj3 = self.pop("arraytype", "stringtype") 475*e1fe3e4aSElliott Hughes tp = obj3.type 476*e1fe3e4aSElliott Hughes if tp == "arraytype": 477*e1fe3e4aSElliott Hughes self.push(ps_array(obj3.value[obj2.value : obj2.value + obj1.value])) 478*e1fe3e4aSElliott Hughes elif tp == "stringtype": 479*e1fe3e4aSElliott Hughes self.push(ps_string(obj3.value[obj2.value : obj2.value + obj1.value])) 480*e1fe3e4aSElliott Hughes 481*e1fe3e4aSElliott Hughes def ps_putinterval(self): 482*e1fe3e4aSElliott Hughes obj1 = self.pop("arraytype", "stringtype") 483*e1fe3e4aSElliott Hughes obj2 = self.pop("integertype") 484*e1fe3e4aSElliott Hughes obj3 = self.pop("arraytype", "stringtype") 485*e1fe3e4aSElliott Hughes tp = obj3.type 486*e1fe3e4aSElliott Hughes if tp == "arraytype": 487*e1fe3e4aSElliott Hughes obj3.value[obj2.value : obj2.value + len(obj1.value)] = obj1.value 488*e1fe3e4aSElliott Hughes elif tp == "stringtype": 489*e1fe3e4aSElliott Hughes newstr = obj3.value[: obj2.value] 490*e1fe3e4aSElliott Hughes newstr = newstr + obj1.value 491*e1fe3e4aSElliott Hughes newstr = newstr + obj3.value[obj2.value + len(obj1.value) :] 492*e1fe3e4aSElliott Hughes obj3.value = newstr 493*e1fe3e4aSElliott Hughes 494*e1fe3e4aSElliott Hughes def ps_cvn(self): 495*e1fe3e4aSElliott Hughes self.push(ps_name(self.pop("stringtype").value)) 496*e1fe3e4aSElliott Hughes 497*e1fe3e4aSElliott Hughes def ps_index(self): 498*e1fe3e4aSElliott Hughes n = self.pop("integertype").value 499*e1fe3e4aSElliott Hughes if n < 0: 500*e1fe3e4aSElliott Hughes raise RuntimeError("index may not be negative") 501*e1fe3e4aSElliott Hughes self.push(self.stack[-1 - n]) 502*e1fe3e4aSElliott Hughes 503*e1fe3e4aSElliott Hughes def ps_for(self): 504*e1fe3e4aSElliott Hughes proc = self.pop("proceduretype") 505*e1fe3e4aSElliott Hughes limit = self.pop("integertype", "realtype").value 506*e1fe3e4aSElliott Hughes increment = self.pop("integertype", "realtype").value 507*e1fe3e4aSElliott Hughes i = self.pop("integertype", "realtype").value 508*e1fe3e4aSElliott Hughes while 1: 509*e1fe3e4aSElliott Hughes if increment > 0: 510*e1fe3e4aSElliott Hughes if i > limit: 511*e1fe3e4aSElliott Hughes break 512*e1fe3e4aSElliott Hughes else: 513*e1fe3e4aSElliott Hughes if i < limit: 514*e1fe3e4aSElliott Hughes break 515*e1fe3e4aSElliott Hughes if type(i) == type(0.0): 516*e1fe3e4aSElliott Hughes self.push(ps_real(i)) 517*e1fe3e4aSElliott Hughes else: 518*e1fe3e4aSElliott Hughes self.push(ps_integer(i)) 519*e1fe3e4aSElliott Hughes self.call_procedure(proc) 520*e1fe3e4aSElliott Hughes i = i + increment 521*e1fe3e4aSElliott Hughes 522*e1fe3e4aSElliott Hughes def ps_forall(self): 523*e1fe3e4aSElliott Hughes proc = self.pop("proceduretype") 524*e1fe3e4aSElliott Hughes obj = self.pop("arraytype", "stringtype", "dicttype") 525*e1fe3e4aSElliott Hughes tp = obj.type 526*e1fe3e4aSElliott Hughes if tp == "arraytype": 527*e1fe3e4aSElliott Hughes for item in obj.value: 528*e1fe3e4aSElliott Hughes self.push(item) 529*e1fe3e4aSElliott Hughes self.call_procedure(proc) 530*e1fe3e4aSElliott Hughes elif tp == "stringtype": 531*e1fe3e4aSElliott Hughes for item in obj.value: 532*e1fe3e4aSElliott Hughes self.push(ps_integer(ord(item))) 533*e1fe3e4aSElliott Hughes self.call_procedure(proc) 534*e1fe3e4aSElliott Hughes elif tp == "dicttype": 535*e1fe3e4aSElliott Hughes for key, value in obj.value.items(): 536*e1fe3e4aSElliott Hughes self.push(ps_name(key)) 537*e1fe3e4aSElliott Hughes self.push(value) 538*e1fe3e4aSElliott Hughes self.call_procedure(proc) 539*e1fe3e4aSElliott Hughes 540*e1fe3e4aSElliott Hughes def ps_definefont(self): 541*e1fe3e4aSElliott Hughes font = self.pop("dicttype") 542*e1fe3e4aSElliott Hughes name = self.pop() 543*e1fe3e4aSElliott Hughes font = ps_font(font.value) 544*e1fe3e4aSElliott Hughes self.dictstack[0]["FontDirectory"].value[name.value] = font 545*e1fe3e4aSElliott Hughes self.push(font) 546*e1fe3e4aSElliott Hughes 547*e1fe3e4aSElliott Hughes def ps_findfont(self): 548*e1fe3e4aSElliott Hughes name = self.pop() 549*e1fe3e4aSElliott Hughes font = self.dictstack[0]["FontDirectory"].value[name.value] 550*e1fe3e4aSElliott Hughes self.push(font) 551*e1fe3e4aSElliott Hughes 552*e1fe3e4aSElliott Hughes def ps_pop(self): 553*e1fe3e4aSElliott Hughes self.pop() 554*e1fe3e4aSElliott Hughes 555*e1fe3e4aSElliott Hughes def ps_dict(self): 556*e1fe3e4aSElliott Hughes self.pop("integertype") 557*e1fe3e4aSElliott Hughes self.push(ps_dict({})) 558*e1fe3e4aSElliott Hughes 559*e1fe3e4aSElliott Hughes def ps_begin(self): 560*e1fe3e4aSElliott Hughes self.dictstack.append(self.pop("dicttype").value) 561*e1fe3e4aSElliott Hughes 562*e1fe3e4aSElliott Hughes def ps_end(self): 563*e1fe3e4aSElliott Hughes if len(self.dictstack) > 2: 564*e1fe3e4aSElliott Hughes del self.dictstack[-1] 565*e1fe3e4aSElliott Hughes else: 566*e1fe3e4aSElliott Hughes raise RuntimeError("dictstack underflow") 567*e1fe3e4aSElliott Hughes 568*e1fe3e4aSElliott Hughes 569*e1fe3e4aSElliott Hughesnotdef = ".notdef" 570*e1fe3e4aSElliott Hughesfrom fontTools.encodings.StandardEncoding import StandardEncoding 571*e1fe3e4aSElliott Hughes 572*e1fe3e4aSElliott Hughesps_StandardEncoding = list(map(ps_name, StandardEncoding)) 573