Source code for fontTools.misc.psOperators

_accessstrings = {0: "", 1: "readonly", 2: "executeonly", 3: "noaccess"}


[docs] class ps_object(object): literal = 1 access = 0 value = None def __init__(self, value): self.value = value self.type = self.__class__.__name__[3:] + "type" def __repr__(self): return "<%s %s>" % (self.__class__.__name__[3:], repr(self.value))
[docs] class ps_operator(ps_object): literal = 0 def __init__(self, name, function): self.name = name self.function = function self.type = self.__class__.__name__[3:] + "type" def __repr__(self): return "<operator %s>" % self.name
[docs] class ps_procedure(ps_object): literal = 0 def __repr__(self): return "<procedure>" def __str__(self): psstring = "{" for i in range(len(self.value)): if i: psstring = psstring + " " + str(self.value[i]) else: psstring = psstring + str(self.value[i]) return psstring + "}"
[docs] class ps_name(ps_object): literal = 0 def __str__(self): if self.literal: return "/" + self.value else: return self.value
[docs] class ps_literal(ps_object): def __str__(self): return "/" + self.value
[docs] class ps_array(ps_object): def __str__(self): psstring = "[" for i in range(len(self.value)): item = self.value[i] access = _accessstrings[item.access] if access: access = " " + access if i: psstring = psstring + " " + str(item) + access else: psstring = psstring + str(item) + access return psstring + "]" def __repr__(self): return "<array>"
_type1_pre_eexec_order = [ "FontInfo", "FontName", "Encoding", "PaintType", "FontType", "FontMatrix", "FontBBox", "UniqueID", "Metrics", "StrokeWidth", ] _type1_fontinfo_order = [ "version", "Notice", "FullName", "FamilyName", "Weight", "ItalicAngle", "isFixedPitch", "UnderlinePosition", "UnderlineThickness", ] _type1_post_eexec_order = ["Private", "CharStrings", "FID"] def _type1_item_repr(key, value): psstring = "" access = _accessstrings[value.access] if access: access = access + " " if key == "CharStrings": psstring = psstring + "/%s %s def\n" % ( key, _type1_CharString_repr(value.value), ) elif key == "Encoding": psstring = psstring + _type1_Encoding_repr(value, access) else: psstring = psstring + "/%s %s %sdef\n" % (str(key), str(value), access) return psstring def _type1_Encoding_repr(encoding, access): encoding = encoding.value psstring = "/Encoding 256 array\n0 1 255 {1 index exch /.notdef put} for\n" for i in range(256): name = encoding[i].value if name != ".notdef": psstring = psstring + "dup %d /%s put\n" % (i, name) return psstring + access + "def\n" def _type1_CharString_repr(charstrings): items = sorted(charstrings.items()) return "xxx"
[docs] class ps_font(ps_object): def __str__(self): psstring = "%d dict dup begin\n" % len(self.value) for key in _type1_pre_eexec_order: try: value = self.value[key] except KeyError: pass else: psstring = psstring + _type1_item_repr(key, value) items = sorted(self.value.items()) for key, value in items: if key not in _type1_pre_eexec_order + _type1_post_eexec_order: psstring = psstring + _type1_item_repr(key, value) psstring = psstring + "currentdict end\ncurrentfile eexec\ndup " for key in _type1_post_eexec_order: try: value = self.value[key] except KeyError: pass else: psstring = psstring + _type1_item_repr(key, value) return ( psstring + "dup/FontName get exch definefont pop\nmark currentfile closefile\n" + 8 * (64 * "0" + "\n") + "cleartomark" + "\n" ) def __repr__(self): return "<font>"
[docs] class ps_file(ps_object): pass
[docs] class ps_dict(ps_object): def __str__(self): psstring = "%d dict dup begin\n" % len(self.value) items = sorted(self.value.items()) for key, value in items: access = _accessstrings[value.access] if access: access = access + " " psstring = psstring + "/%s %s %sdef\n" % (str(key), str(value), access) return psstring + "end " def __repr__(self): return "<dict>"
[docs] class ps_mark(ps_object): def __init__(self): self.value = "mark" self.type = self.__class__.__name__[3:] + "type"
[docs] class ps_procmark(ps_object): def __init__(self): self.value = "procmark" self.type = self.__class__.__name__[3:] + "type"
[docs] class ps_null(ps_object): def __init__(self): self.type = self.__class__.__name__[3:] + "type"
[docs] class ps_boolean(ps_object): def __str__(self): if self.value: return "true" else: return "false"
[docs] class ps_string(ps_object): def __str__(self): return "(%s)" % repr(self.value)[1:-1]
[docs] class ps_integer(ps_object): def __str__(self): return repr(self.value)
[docs] class ps_real(ps_object): def __str__(self): return repr(self.value)
[docs] class PSOperators(object):
[docs] def ps_def(self): obj = self.pop() name = self.pop() self.dictstack[-1][name.value] = obj
[docs] def ps_bind(self): proc = self.pop("proceduretype") self.proc_bind(proc) self.push(proc)
[docs] def proc_bind(self, proc): for i in range(len(proc.value)): item = proc.value[i] if item.type == "proceduretype": self.proc_bind(item) else: if not item.literal: try: obj = self.resolve_name(item.value) except: pass else: if obj.type == "operatortype": proc.value[i] = obj
[docs] def ps_exch(self): if len(self.stack) < 2: raise RuntimeError("stack underflow") obj1 = self.pop() obj2 = self.pop() self.push(obj1) self.push(obj2)
[docs] def ps_dup(self): if not self.stack: raise RuntimeError("stack underflow") self.push(self.stack[-1])
[docs] def ps_exec(self): obj = self.pop() if obj.type == "proceduretype": self.call_procedure(obj) else: self.handle_object(obj)
[docs] def ps_count(self): self.push(ps_integer(len(self.stack)))
[docs] def ps_eq(self): any1 = self.pop() any2 = self.pop() self.push(ps_boolean(any1.value == any2.value))
[docs] def ps_ne(self): any1 = self.pop() any2 = self.pop() self.push(ps_boolean(any1.value != any2.value))
[docs] def ps_cvx(self): obj = self.pop() obj.literal = 0 self.push(obj)
[docs] def ps_matrix(self): matrix = [ ps_real(1.0), ps_integer(0), ps_integer(0), ps_real(1.0), ps_integer(0), ps_integer(0), ] self.push(ps_array(matrix))
[docs] def ps_string(self): num = self.pop("integertype").value self.push(ps_string("\0" * num))
[docs] def ps_type(self): obj = self.pop() self.push(ps_string(obj.type))
[docs] def ps_store(self): value = self.pop() key = self.pop() name = key.value for i in range(len(self.dictstack) - 1, -1, -1): if name in self.dictstack[i]: self.dictstack[i][name] = value break self.dictstack[-1][name] = value
[docs] def ps_where(self): name = self.pop() # XXX self.push(ps_boolean(0))
[docs] def ps_systemdict(self): self.push(ps_dict(self.dictstack[0]))
[docs] def ps_userdict(self): self.push(ps_dict(self.dictstack[1]))
[docs] def ps_currentdict(self): self.push(ps_dict(self.dictstack[-1]))
[docs] def ps_currentfile(self): self.push(ps_file(self.tokenizer))
[docs] def ps_eexec(self): f = self.pop("filetype").value f.starteexec()
[docs] def ps_closefile(self): f = self.pop("filetype").value f.skipwhite() f.stopeexec()
[docs] def ps_cleartomark(self): obj = self.pop() while obj != self.mark: obj = self.pop()
[docs] def ps_readstring(self, ps_boolean=ps_boolean, len=len): s = self.pop("stringtype") oldstr = s.value f = self.pop("filetype") # pad = file.value.read(1) # for StringIO, this is faster f.value.pos = f.value.pos + 1 newstr = f.value.read(len(oldstr)) s.value = newstr self.push(s) self.push(ps_boolean(len(oldstr) == len(newstr)))
[docs] def ps_known(self): key = self.pop() d = self.pop("dicttype", "fonttype") self.push(ps_boolean(key.value in d.value))
[docs] def ps_if(self): proc = self.pop("proceduretype") if self.pop("booleantype").value: self.call_procedure(proc)
[docs] def ps_ifelse(self): proc2 = self.pop("proceduretype") proc1 = self.pop("proceduretype") if self.pop("booleantype").value: self.call_procedure(proc1) else: self.call_procedure(proc2)
[docs] def ps_readonly(self): obj = self.pop() if obj.access < 1: obj.access = 1 self.push(obj)
[docs] def ps_executeonly(self): obj = self.pop() if obj.access < 2: obj.access = 2 self.push(obj)
[docs] def ps_noaccess(self): obj = self.pop() if obj.access < 3: obj.access = 3 self.push(obj)
[docs] def ps_not(self): obj = self.pop("booleantype", "integertype") if obj.type == "booleantype": self.push(ps_boolean(not obj.value)) else: self.push(ps_integer(~obj.value))
[docs] def ps_print(self): str = self.pop("stringtype") print("PS output --->", str.value)
[docs] def ps_anchorsearch(self): seek = self.pop("stringtype") s = self.pop("stringtype") seeklen = len(seek.value) if s.value[:seeklen] == seek.value: self.push(ps_string(s.value[seeklen:])) self.push(seek) self.push(ps_boolean(1)) else: self.push(s) self.push(ps_boolean(0))
[docs] def ps_array(self): num = self.pop("integertype") array = ps_array([None] * num.value) self.push(array)
[docs] def ps_astore(self): array = self.pop("arraytype") for i in range(len(array.value) - 1, -1, -1): array.value[i] = self.pop() self.push(array)
[docs] def ps_load(self): name = self.pop() self.push(self.resolve_name(name.value))
[docs] def ps_put(self): obj1 = self.pop() obj2 = self.pop() obj3 = self.pop("arraytype", "dicttype", "stringtype", "proceduretype") tp = obj3.type if tp == "arraytype" or tp == "proceduretype": obj3.value[obj2.value] = obj1 elif tp == "dicttype": obj3.value[obj2.value] = obj1 elif tp == "stringtype": index = obj2.value obj3.value = obj3.value[:index] + chr(obj1.value) + obj3.value[index + 1 :]
[docs] def ps_get(self): obj1 = self.pop() if obj1.value == "Encoding": pass obj2 = self.pop( "arraytype", "dicttype", "stringtype", "proceduretype", "fonttype" ) tp = obj2.type if tp in ("arraytype", "proceduretype"): self.push(obj2.value[obj1.value]) elif tp in ("dicttype", "fonttype"): self.push(obj2.value[obj1.value]) elif tp == "stringtype": self.push(ps_integer(ord(obj2.value[obj1.value]))) else: assert False, "shouldn't get here"
[docs] def ps_getinterval(self): obj1 = self.pop("integertype") obj2 = self.pop("integertype") obj3 = self.pop("arraytype", "stringtype") tp = obj3.type if tp == "arraytype": self.push(ps_array(obj3.value[obj2.value : obj2.value + obj1.value])) elif tp == "stringtype": self.push(ps_string(obj3.value[obj2.value : obj2.value + obj1.value]))
[docs] def ps_putinterval(self): obj1 = self.pop("arraytype", "stringtype") obj2 = self.pop("integertype") obj3 = self.pop("arraytype", "stringtype") tp = obj3.type if tp == "arraytype": obj3.value[obj2.value : obj2.value + len(obj1.value)] = obj1.value elif tp == "stringtype": newstr = obj3.value[: obj2.value] newstr = newstr + obj1.value newstr = newstr + obj3.value[obj2.value + len(obj1.value) :] obj3.value = newstr
[docs] def ps_cvn(self): self.push(ps_name(self.pop("stringtype").value))
[docs] def ps_index(self): n = self.pop("integertype").value if n < 0: raise RuntimeError("index may not be negative") self.push(self.stack[-1 - n])
[docs] def ps_for(self): proc = self.pop("proceduretype") limit = self.pop("integertype", "realtype").value increment = self.pop("integertype", "realtype").value i = self.pop("integertype", "realtype").value while 1: if increment > 0: if i > limit: break else: if i < limit: break if type(i) == type(0.0): self.push(ps_real(i)) else: self.push(ps_integer(i)) self.call_procedure(proc) i = i + increment
[docs] def ps_forall(self): proc = self.pop("proceduretype") obj = self.pop("arraytype", "stringtype", "dicttype") tp = obj.type if tp == "arraytype": for item in obj.value: self.push(item) self.call_procedure(proc) elif tp == "stringtype": for item in obj.value: self.push(ps_integer(ord(item))) self.call_procedure(proc) elif tp == "dicttype": for key, value in obj.value.items(): self.push(ps_name(key)) self.push(value) self.call_procedure(proc)
[docs] def ps_definefont(self): font = self.pop("dicttype") name = self.pop() font = ps_font(font.value) self.dictstack[0]["FontDirectory"].value[name.value] = font self.push(font)
[docs] def ps_findfont(self): name = self.pop() font = self.dictstack[0]["FontDirectory"].value[name.value] self.push(font)
[docs] def ps_pop(self): self.pop()
[docs] def ps_dict(self): self.pop("integertype") self.push(ps_dict({}))
[docs] def ps_begin(self): self.dictstack.append(self.pop("dicttype").value)
[docs] def ps_end(self): if len(self.dictstack) > 2: del self.dictstack[-1] else: raise RuntimeError("dictstack underflow")
notdef = ".notdef" from fontTools.encodings.StandardEncoding import StandardEncoding ps_StandardEncoding = list(map(ps_name, StandardEncoding))