xref: /aosp_15_r20/external/fonttools/Lib/fontTools/misc/psOperators.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
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