123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572 |
- _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))
|