Spaces:
Sleeping
Sleeping
_accessstrings = {0: "", 1: "readonly", 2: "executeonly", 3: "noaccess"} | |
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)) | |
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 | |
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 + "}" | |
class ps_name(ps_object): | |
literal = 0 | |
def __str__(self): | |
if self.literal: | |
return "/" + self.value | |
else: | |
return self.value | |
class ps_literal(ps_object): | |
def __str__(self): | |
return "/" + self.value | |
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" | |
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>" | |
class ps_file(ps_object): | |
pass | |
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>" | |
class ps_mark(ps_object): | |
def __init__(self): | |
self.value = "mark" | |
self.type = self.__class__.__name__[3:] + "type" | |
class ps_procmark(ps_object): | |
def __init__(self): | |
self.value = "procmark" | |
self.type = self.__class__.__name__[3:] + "type" | |
class ps_null(ps_object): | |
def __init__(self): | |
self.type = self.__class__.__name__[3:] + "type" | |
class ps_boolean(ps_object): | |
def __str__(self): | |
if self.value: | |
return "true" | |
else: | |
return "false" | |
class ps_string(ps_object): | |
def __str__(self): | |
return "(%s)" % repr(self.value)[1:-1] | |
class ps_integer(ps_object): | |
def __str__(self): | |
return repr(self.value) | |
class ps_real(ps_object): | |
def __str__(self): | |
return repr(self.value) | |
class PSOperators(object): | |
def ps_def(self): | |
obj = self.pop() | |
name = self.pop() | |
self.dictstack[-1][name.value] = obj | |
def ps_bind(self): | |
proc = self.pop("proceduretype") | |
self.proc_bind(proc) | |
self.push(proc) | |
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 | |
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) | |
def ps_dup(self): | |
if not self.stack: | |
raise RuntimeError("stack underflow") | |
self.push(self.stack[-1]) | |
def ps_exec(self): | |
obj = self.pop() | |
if obj.type == "proceduretype": | |
self.call_procedure(obj) | |
else: | |
self.handle_object(obj) | |
def ps_count(self): | |
self.push(ps_integer(len(self.stack))) | |
def ps_eq(self): | |
any1 = self.pop() | |
any2 = self.pop() | |
self.push(ps_boolean(any1.value == any2.value)) | |
def ps_ne(self): | |
any1 = self.pop() | |
any2 = self.pop() | |
self.push(ps_boolean(any1.value != any2.value)) | |
def ps_cvx(self): | |
obj = self.pop() | |
obj.literal = 0 | |
self.push(obj) | |
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)) | |
def ps_string(self): | |
num = self.pop("integertype").value | |
self.push(ps_string("\0" * num)) | |
def ps_type(self): | |
obj = self.pop() | |
self.push(ps_string(obj.type)) | |
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 | |
def ps_where(self): | |
name = self.pop() | |
# XXX | |
self.push(ps_boolean(0)) | |
def ps_systemdict(self): | |
self.push(ps_dict(self.dictstack[0])) | |
def ps_userdict(self): | |
self.push(ps_dict(self.dictstack[1])) | |
def ps_currentdict(self): | |
self.push(ps_dict(self.dictstack[-1])) | |
def ps_currentfile(self): | |
self.push(ps_file(self.tokenizer)) | |
def ps_eexec(self): | |
f = self.pop("filetype").value | |
f.starteexec() | |
def ps_closefile(self): | |
f = self.pop("filetype").value | |
f.skipwhite() | |
f.stopeexec() | |
def ps_cleartomark(self): | |
obj = self.pop() | |
while obj != self.mark: | |
obj = self.pop() | |
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))) | |
def ps_known(self): | |
key = self.pop() | |
d = self.pop("dicttype", "fonttype") | |
self.push(ps_boolean(key.value in d.value)) | |
def ps_if(self): | |
proc = self.pop("proceduretype") | |
if self.pop("booleantype").value: | |
self.call_procedure(proc) | |
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) | |
def ps_readonly(self): | |
obj = self.pop() | |
if obj.access < 1: | |
obj.access = 1 | |
self.push(obj) | |
def ps_executeonly(self): | |
obj = self.pop() | |
if obj.access < 2: | |
obj.access = 2 | |
self.push(obj) | |
def ps_noaccess(self): | |
obj = self.pop() | |
if obj.access < 3: | |
obj.access = 3 | |
self.push(obj) | |
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)) | |
def ps_print(self): | |
str = self.pop("stringtype") | |
print("PS output --->", str.value) | |
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)) | |
def ps_array(self): | |
num = self.pop("integertype") | |
array = ps_array([None] * num.value) | |
self.push(array) | |
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) | |
def ps_load(self): | |
name = self.pop() | |
self.push(self.resolve_name(name.value)) | |
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 :] | |
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" | |
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])) | |
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 | |
def ps_cvn(self): | |
self.push(ps_name(self.pop("stringtype").value)) | |
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]) | |
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 | |
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) | |
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) | |
def ps_findfont(self): | |
name = self.pop() | |
font = self.dictstack[0]["FontDirectory"].value[name.value] | |
self.push(font) | |
def ps_pop(self): | |
self.pop() | |
def ps_dict(self): | |
self.pop("integertype") | |
self.push(ps_dict({})) | |
def ps_begin(self): | |
self.dictstack.append(self.pop("dicttype").value) | |
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)) | |