fonttools/Lib/fontTools/ttLib/xmlImport.py
Just 7842e56b97 Created a new library directory called "FreeLib". All OpenSource RFMKII components will reside there, fontTools being the flagship.
git-svn-id: svn://svn.code.sf.net/p/fonttools/code/trunk@2 4cde692c-a291-49d1-8350-778aa11640f8
1999-12-16 21:34:53 +00:00

197 lines
4.9 KiB
Python

from fontTools import ttLib
from fontTools.misc.textTools import safeEval
import types
import string
import Numeric, array
from xml.parsers.xmlproc import xmlproc
xmlerror = "xmlerror"
xml_parse_error = "XML parse error"
class UnicodeString:
def __init__(self, value):
if isinstance(value, UnicodeString):
self.value = value.value
else:
if type(value) == types.StringType:
# Since Numeric interprets char codes as *signed*,
# we feed it through the array module.
value = array.array("B", value)
self.value = Numeric.array(value, Numeric.Int16)
def __len__(self):
return len(self.value)
#def __hash__(self):
# return hash(self.value.tostring())
#
#def __cmp__(self, other):
# if not isinstance(other, UnicodeString):
# return 1
# else:
# return not Numeric.alltrue(
# Numeric.equal(self.value, other.value))
def __add__(self, other):
if not isinstance(other, UnicodeString):
other = self.__class__(other)
return self.__class__(Numeric.concatenate((self.value, other.value)))
def __radd__(self, other):
if not isinstance(other, UnicodeString):
other = self.__class__(other)
return self.__class__(Numeric.concatenate((other.value, self.value)))
def __getslice__(self, i, j):
return self.__class__(self.value[i:j])
def __getitem__(self, i):
return self.__class__(self.value[i:i+1])
def tostring(self):
value = self.value
if ttLib.endian <> "big":
value = value.byteswapped()
return value.tostring()
def stripped(self):
value = self.value
i = 0
for i in range(len(value)):
if value[i] not in (0xa, 0xd, 0x9, 0x20):
break
value = value[i:]
i = 0
for i in range(len(value)-1, -1, -1):
if value[i] not in (0xa, 0xd, 0x9, 0x20):
break
value = value[:i+1]
return self.__class__(value)
def __repr__(self):
return "<%s %s at %x>" % (self.__class__.__name__, `self.value.tostring()`, id(self))
class UnicodeProcessor(xmlproc.XMLProcessor):
def parse_charref(self):
"Parses a character reference."
if self.now_at("x"):
digs=unhex(self.get_match(xmlproc.reg_hex_digits))
else:
try:
digs=string.atoi(self.get_match(xmlproc.reg_digits))
except ValueError,e:
self.report_error(3027)
digs=None
if digs == 169:
pass
if not self.now_at(";"): self.report_error(3005,";")
if digs==None: return
if not (digs==9 or digs==10 or digs==13 or \
(digs>=32 and digs<=255)):
if digs>255:
self.app.handle_data(UnicodeString([digs]),0,1)
else:
# hrm, I need to let some null bytes go through...
self.app.handle_data(chr(digs),0,1)
#self.report_error(3018,digs)
else:
if self.stack==[]:
self.report_error(3028)
self.app.handle_data(chr(digs),0,1)
class XMLErrorHandler(xmlproc.ErrorHandler):
def fatal(self, msg):
"Handles a fatal error message."
# we don't want no stinkin' sys.exit(1)
raise xml_parse_error, msg
class XMLApplication(xmlproc.Application):
def __init__(self, ttFont, progress=None):
self.ttFont = ttFont
self.progress = progress
self.root = None
self.content_stack = []
self.lastpos = 0
def handle_start_tag(self, name, attrs):
if self.progress:
pos = self.locator.pos + self.locator.block_offset
if (pos - self.lastpos) > 4000:
self.progress.set(pos / 100)
self.lastpos = pos
stack = self.locator.stack
stacksize = len(stack)
if not stacksize:
if name <> "ttFont":
raise xml_parse_error, "illegal root tag: %s" % name
sfntVersion = attrs.get("sfntVersion", "\000\001\000\000")
if len(sfntVersion) <> 4:
sfntVersion = safeEval('"' + sfntVersion + '"')
self.ttFont.sfntVersion = sfntVersion
self.content_stack.append([])
elif stacksize == 1:
msg = "Parsing '%s' table..." % ttLib.xmltag2tag(name)
if self.progress:
self.progress.setlabel(msg)
elif self.ttFont.verbose:
ttLib.debugmsg(msg)
else:
print msg
tag = ttLib.xmltag2tag(name)
tableclass = ttLib.getTableClass(tag)
if tableclass is None:
from fontTools.ttLib.tables.DefaultTable import DefaultTable
tableclass = DefaultTable
self.current_table = tableclass(tag)
self.ttFont[tag] = self.current_table
self.content_stack.append([])
elif stacksize == 2:
self.content_stack.append([])
self.root = (name, attrs, self.content_stack[-1])
else:
list = []
self.content_stack[-1].append(name, attrs, list)
self.content_stack.append(list)
def handle_data(self, data, start, end):
if len(self.locator.stack) > 1:
self.content_stack[-1].append(data[start:end])
def handle_end_tag(self, name):
del self.content_stack[-1]
stack = self.locator.stack
stacksize = len(stack)
if stacksize == 1:
self.root = None
elif stacksize == 2:
self.current_table.fromXML(self.root, self.ttFont)
self.root = None
class ProgressPrinter:
def __init__(self, title, maxval=100):
print title
def set(self, val, maxval=None):
pass
def increment(self, val=1):
pass
def setlabel(self, text):
print text