Added explicit font and encoding support
authorandy_robinson
Tue, 06 Mar 2001 17:38:15 +0000
changeset 681 934a4f24ea5d
parent 680 3930b21a6f91
child 682 c4ae7b303888
Added explicit font and encoding support
reportlab/__init__.py
reportlab/config.py
reportlab/demos/stdfonts/stdfonts.py
reportlab/lib/graphicsdoc0.py
reportlab/pdfbase/pdfdoc.py
reportlab/pdfbase/pdfmetrics.py
reportlab/pdfgen/canvas.py
reportlab/pdfgen/fonts0.py
reportlab/platypus/doctemplate.py
reportlab/platypus/paragraph.py
reportlab/test/test_pdfbase_pdfmetrics.py
--- a/reportlab/__init__.py	Fri Mar 02 15:35:43 2001 +0000
+++ b/reportlab/__init__.py	Tue Mar 06 17:38:15 2001 +0000
@@ -1,8 +1,19 @@
 #copyright ReportLab Inc. 2000
 #see license.txt for license details
 #history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/__init__.py?cvsroot=reportlab
-#$Header: /tmp/reportlab/reportlab/__init__.py,v 1.9 2001/02/09 15:49:01 johnprecedo Exp $
-__version__=''' $Id: __init__.py,v 1.9 2001/02/09 15:49:01 johnprecedo Exp $ '''
-__doc__="""
-"""
+#$Header: /tmp/reportlab/reportlab/__init__.py,v 1.10 2001/03/06 17:38:14 andy_robinson Exp $
+__version__=''' $Id: __init__.py,v 1.10 2001/03/06 17:38:14 andy_robinson Exp $ '''
+__doc__="""The Reportlab PDF generation library."""
 Version = "1.03"
+
+def getStory(context):
+    if context.target == 'UserGuide':
+        # parse some local file
+        import os
+        myDir = os.path.split(__file__)[0]
+        import yaml
+        return yaml.parseFile(myDir + os.sep + 'mydocs.yaml')
+    else:
+        # this signals that it should revert to default processing
+        return None
+
--- a/reportlab/config.py	Fri Mar 02 15:35:43 2001 +0000
+++ b/reportlab/config.py	Tue Mar 06 17:38:15 2001 +0000
@@ -1,1 +1,2 @@
-shapeChecking = 1
\ No newline at end of file
+shapeChecking = 1
+defaultEncoding = 'WinAnsi'  # 'WinAnsi' or 'MacRoman'
--- a/reportlab/demos/stdfonts/stdfonts.py	Fri Mar 02 15:35:43 2001 +0000
+++ b/reportlab/demos/stdfonts/stdfonts.py	Tue Mar 06 17:38:15 2001 +0000
@@ -1,8 +1,8 @@
 #copyright ReportLab Inc. 2000
 #see license.txt for license details
 #history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/demos/stdfonts/stdfonts.py?cvsroot=reportlab
-#$Header: /tmp/reportlab/reportlab/demos/stdfonts/stdfonts.py,v 1.8 2000/11/08 10:55:37 andy_robinson Exp $
-__version__=''' $Id: stdfonts.py,v 1.8 2000/11/08 10:55:37 andy_robinson Exp $ '''
+#$Header: /tmp/reportlab/reportlab/demos/stdfonts/stdfonts.py,v 1.9 2001/03/06 17:38:15 andy_robinson Exp $
+__version__=''' $Id: stdfonts.py,v 1.9 2001/03/06 17:38:15 andy_robinson Exp $ '''
 __doc__="""
 This generates tables showing the 14 standard fonts in both
 WinAnsi and MacRoman encodings, and their character codes.
@@ -32,7 +32,7 @@
                 )
         canv.setPageCompression(0)
         
-        for fontname in pdfmetrics.StandardEnglishFonts:
+        for fontname in pdfmetrics.standardEnglishFonts:
             if fontname in ['Symbol', 'ZapfDingbats']:
                 encLabel = 'StandardEncoding'
             else:
--- a/reportlab/lib/graphicsdoc0.py	Fri Mar 02 15:35:43 2001 +0000
+++ b/reportlab/lib/graphicsdoc0.py	Tue Mar 06 17:38:15 2001 +0000
@@ -50,7 +50,7 @@
     from rlextra.graphics import renderGD
 except ImportError, errMsg:
     if str(errMsg)!='No module named renderGD':
-    pass
+        pass
 
 
 ####################################################################
--- a/reportlab/pdfbase/pdfdoc.py	Fri Mar 02 15:35:43 2001 +0000
+++ b/reportlab/pdfbase/pdfdoc.py	Tue Mar 06 17:38:15 2001 +0000
@@ -2,8 +2,8 @@
 #copyright ReportLab Inc. 2000
 #see license.txt for license details
 #history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/pdfbase/pdfdoc.py?cvsroot=reportlab
-#$Header: /tmp/reportlab/reportlab/pdfbase/pdfdoc.py,v 1.38 2001/02/28 11:53:55 rgbecker Exp $
-__version__=''' $Id: pdfdoc.py,v 1.38 2001/02/28 11:53:55 rgbecker Exp $ '''
+#$Header: /tmp/reportlab/reportlab/pdfbase/pdfdoc.py,v 1.39 2001/03/06 17:38:15 andy_robinson Exp $
+__version__=''' $Id: pdfdoc.py,v 1.39 2001/03/06 17:38:15 andy_robinson Exp $ '''
 __doc__=""" 
 PDFgen is a library to generate PDF files containing text and graphics.  It is the 
 foundation for a complete reporting solution in Python.  
@@ -63,16 +63,16 @@
 LINEENDDICT = {"LINEEND": LINEEND, "PERCENT": "%"}
 
 def markfilename(filename):
-	# with the Mac, we need to tag the file in a special
-	#way so the system knows it is a PDF file.
-	#This supplied by Joe Strout
-	import os
-	if os.name == 'mac':
-		import macfs
-		try: 
-			macfs.FSSpec(filename).SetCreatorType('CARO','PDF ')
-		except:
-			pass
+    # with the Mac, we need to tag the file in a special
+    #way so the system knows it is a PDF file.
+    #This supplied by Joe Strout
+    import os
+    if os.name == 'mac':
+        import macfs
+        try: 
+            macfs.FSSpec(filename).SetCreatorType('CARO','PDF ')
+        except:
+            pass
 
 def format(element, document, toplevel=0):
     """Indirection step for formatting.
@@ -112,7 +112,7 @@
     # set this to define filters 
     defaultStreamFilters = None
     pageCounter = 1
-    def __init__(self, encoding=DEFAULT_ENCODING, dummyoutline=0, doFonts=1):
+    def __init__(self, encoding=DEFAULT_ENCODING, dummyoutline=0, doFonts=0):
         #self.defaultStreamFilters = [PDFBase85Encode, PDFZCompress] # for testing!
         #self.defaultStreamFilters = [PDFZCompress] # for testing!
         assert encoding in ['MacRomanEncoding',
@@ -145,7 +145,14 @@
         #self.Reference(self.Info)
         # make std fonts (this could be made optional
         self.fontMapping = {}
-        if doFonts: MakeStandardEnglishFontObjects(self, encoding)
+        if doFonts:
+            MakeStandardEnglishFontObjects(self, encoding)
+        else:
+            #make an empty font dictionary
+            DD = PDFDictionary({})
+            DD.__Comment__ = "The standard fonts dictionary"
+            DDR = self.Reference(DD, BasicFonts)
+    
 
     def SaveToFile(self, filename, canvas):
         # prepare outline
@@ -237,7 +244,37 @@
         fontnames = self.fontMapping.keys()
         fontnames.sort()
         return fontnames
-    
+
+
+    def addFont0(self, font):
+        """Add a new font object to the document.
+
+        Called from canvas.registerFont.  This does not handle extending
+        the font metrics database;  canvas.registerFont does that too."""
+        # may be several in succession
+        # get next font number
+##        nextFontId = 'F' + repr(len(self.fontMapping)+1)
+
+        font.addObjects(self)
+        # font must return at least one object, the first in the
+        # list is 'THE' font.  CID fonts may create 3 objects.
+##        objects = font.makeObjects(nextFontId)
+##        fontObj = objects[0]
+##        fontObj.__Comment__ = 'User-defined font %s' % font.name
+##
+##        ref = self.Reference(fontObj, nextFontId)
+##        
+##        # establish naming from public to internal name
+##        self.fontMapping[font.name] = '/' + nextFontId
+##
+##        # gets the BasicFonts dictionary        
+##        fontDict = self.idToObject['BasicFonts'].dict
+##        fontDict[nextFontId] = fontObj
+##
+##        # add any other objects generated
+##        for obj in objects[1:]:
+##            ref = self.Reference(obj)
+
     def format(self):
         # register the Catalog/INfo and then format the objects one by one until exhausted
         # (possible infinite loop if there is a bug that continually makes new objects/refs...)
@@ -402,8 +439,9 @@
             v = dict[k]
             fv = format(v, document)
             fk = format(PDFName(k), document)
-            a(fk)
-            a(" "+fv)
+            #a(fk)
+            #a(" "+fv)
+            a(fk + " " + fv)
         #L = map(str, L)
         if self.multiline:
             Lj = string.join(L, LINEEND)
@@ -572,8 +610,12 @@
         return "%s %s R" % (n,v)
 
 ### chapter 5
-
-PDFHeader = ("%PDF-1.3"+LINEEND+"%íì¶¾  "+LINEEND)
+# Following Ken Lunde's advice and the PDF spec, this includes
+# some high-order bytes.  I chose the characters for Tokyo
+# in Shift-JIS encoding, as these cannot be mistaken for
+# any other encoding, and we'll be able to tell if something
+# has run our PDF files through a dodgy Unicode conversion.
+PDFHeader = ("%PDF-1.3"+LINEEND+"%\223\214\213\236"+LINEEND)
 
 class PDFFile:
     ### just accumulates strings: keeps track of current offset
@@ -872,236 +914,236 @@
         
 
 class OutlineEntryObject:
-	"an entry in an outline"
-	Title = Dest = Parent = Prev = Next = First = Last = Count = None
-	def format(self, document):
-		D = {}
-		D["Title"] = PDFString(self.Title)
-		D["Parent"] = self.Parent
-		D["Dest"] = self.Dest
-		for n in ("Prev", "Next", "First", "Last", "Count"):
-			v = getattr(self, n)
-			if v is not None:
-				D[n] = v
-		PD = PDFDictionary(D)
-		return PD.format(document)
+    "an entry in an outline"
+    Title = Dest = Parent = Prev = Next = First = Last = Count = None
+    def format(self, document):
+        D = {}
+        D["Title"] = PDFString(self.Title)
+        D["Parent"] = self.Parent
+        D["Dest"] = self.Dest
+        for n in ("Prev", "Next", "First", "Last", "Count"):
+            v = getattr(self, n)
+            if v is not None:
+                D[n] = v
+        PD = PDFDictionary(D)
+        return PD.format(document)
 
 
 class PDFOutlines:
-	"""takes a recursive list of outline destinations
-	   like
-		   out = PDFOutline1()
-		   out.setNames(canvas, # requires canvas for name resolution
-			 "chapter1dest",
-			 ("chapter2dest",
-			  ["chapter2section1dest",
-			   "chapter2section2dest",
-			   "chapter2conclusiondest"]
-			 ), # end of chapter2 description
-			 "chapter3dest",
-			 ("chapter4dest", ["c4s1", "c4s2"])
-			 )
-	   Higher layers may build this structure incrementally. KISS at base level.
-	"""
-	# first attempt, many possible features missing.
-	#no init for now
-	mydestinations = ready = None
-	counter = 0
-	currentlevel = -1 # ie, no levels yet
-	
-	def __init__(self):
-		self.destinationnamestotitles = {}
-		self.destinationstotitles = {}
-		self.levelstack = []
-		self.buildtree = []
-		self.closedict = {} # dictionary of "closed" destinations in the outline
+    """takes a recursive list of outline destinations
+       like
+           out = PDFOutline1()
+           out.setNames(canvas, # requires canvas for name resolution
+             "chapter1dest",
+             ("chapter2dest",
+              ["chapter2section1dest",
+               "chapter2section2dest",
+               "chapter2conclusiondest"]
+             ), # end of chapter2 description
+             "chapter3dest",
+             ("chapter4dest", ["c4s1", "c4s2"])
+             )
+       Higher layers may build this structure incrementally. KISS at base level.
+    """
+    # first attempt, many possible features missing.
+    #no init for now
+    mydestinations = ready = None
+    counter = 0
+    currentlevel = -1 # ie, no levels yet
+    
+    def __init__(self):
+        self.destinationnamestotitles = {}
+        self.destinationstotitles = {}
+        self.levelstack = []
+        self.buildtree = []
+        self.closedict = {} # dictionary of "closed" destinations in the outline
 
-	def addOutlineEntry(self, destinationname, level=0, title=None, closed=None):
-		"""destinationname of None means "close the tree" """
-		from types import IntType, TupleType
-		if destinationname is None and level!=0:
-			raise ValueError, "close tree must have level of 0"
-		if type(level) is not IntType: raise ValueError, "level must be integer, got %s" % type(level)
-		if level<0: raise ValueError, "negative levels not allowed"
-		if title is None: title = destinationname
-		currentlevel = self.currentlevel
-		stack = self.levelstack
-		tree = self.buildtree
-		# adjust currentlevel and stack to match level
-		if level>currentlevel:
-			if level>currentlevel+1:
-				raise ValueError, "can't jump from outline level %s to level %s, need intermediates" %(currentlevel, level)
-			level = currentlevel = currentlevel+1
-			stack.append([])
-		while level<currentlevel:
-			# pop off levels to match
-			current = stack[-1]
-			del stack[-1]
-			previous = stack[-1]
-			lastinprevious = previous[-1]
-			if type(lastinprevious) is TupleType:
-				(name, sectionlist) = lastinprevious
-				raise ValueError, "cannot reset existing sections: " + repr(lastinprevious)
-			else:
-				name = lastinprevious
-				sectionlist = current
-				previous[-1] = (name, sectionlist)
-			#sectionlist.append(current)
-			currentlevel = currentlevel-1
-		if destinationname is None: return
-		stack[-1].append(destinationname)
-		self.destinationnamestotitles[destinationname] = title
-		if closed: self.closedict[destinationname] = 1
-		self.currentlevel = level
-		
-	def setDestinations(self, destinationtree):
-		self.mydestinations = destinationtree
-		
-	def format(self, document):
-		D = {}
-		D["Type"] = PDFName("Outlines")
-		c = self.count
-		D["Count"] = c
-		if c!=0:
-		    D["First"] = self.first
-		    D["Last"] = self.last
-		PD = PDFDictionary(D)
-		return PD.format(document)
-		
-	def setNames(self, canvas, *nametree):
-		desttree = self.translateNames(canvas, nametree)
-		self.setDestinations(desttree)
-		
-	def setNameList(self, canvas, nametree):
-		"Explicit list so I don't need to do apply(...) in the caller"
-		desttree = self.translateNames(canvas, nametree)
-		self.setDestinations(desttree)
-		
-	def translateNames(self, canvas, object):
-		"recursively translate tree of names into tree of destinations"
-		from types import StringType, ListType, TupleType
-		Ot = type(object)
-		destinationnamestotitles = self.destinationnamestotitles
-		destinationstotitles = self.destinationstotitles
-		closedict = self.closedict
-		if Ot is StringType:
-			destination = canvas._bookmarkReference(object)
-			title = object
-			if destinationnamestotitles.has_key(object):
-				title = destinationnamestotitles[object]
-			else:
-				destinationnamestotitles[title] = title
-			destinationstotitles[destination] = title
-			if closedict.has_key(object):
-				closedict[destination] = 1 # mark destination closed
-			return {object: canvas._bookmarkReference(object)} # name-->ref
-		if Ot is ListType or Ot is TupleType:
-			L = []
-			for o in object:
-				L.append(self.translateNames(canvas, o))
-			if Ot is TupleType:
-				return tuple(L)
-			return L
-		raise "in outline, destination name must be string: got a %s" % Ot
+    def addOutlineEntry(self, destinationname, level=0, title=None, closed=None):
+        """destinationname of None means "close the tree" """
+        from types import IntType, TupleType
+        if destinationname is None and level!=0:
+            raise ValueError, "close tree must have level of 0"
+        if type(level) is not IntType: raise ValueError, "level must be integer, got %s" % type(level)
+        if level<0: raise ValueError, "negative levels not allowed"
+        if title is None: title = destinationname
+        currentlevel = self.currentlevel
+        stack = self.levelstack
+        tree = self.buildtree
+        # adjust currentlevel and stack to match level
+        if level>currentlevel:
+            if level>currentlevel+1:
+                raise ValueError, "can't jump from outline level %s to level %s, need intermediates" %(currentlevel, level)
+            level = currentlevel = currentlevel+1
+            stack.append([])
+        while level<currentlevel:
+            # pop off levels to match
+            current = stack[-1]
+            del stack[-1]
+            previous = stack[-1]
+            lastinprevious = previous[-1]
+            if type(lastinprevious) is TupleType:
+                (name, sectionlist) = lastinprevious
+                raise ValueError, "cannot reset existing sections: " + repr(lastinprevious)
+            else:
+                name = lastinprevious
+                sectionlist = current
+                previous[-1] = (name, sectionlist)
+            #sectionlist.append(current)
+            currentlevel = currentlevel-1
+        if destinationname is None: return
+        stack[-1].append(destinationname)
+        self.destinationnamestotitles[destinationname] = title
+        if closed: self.closedict[destinationname] = 1
+        self.currentlevel = level
+        
+    def setDestinations(self, destinationtree):
+        self.mydestinations = destinationtree
+        
+    def format(self, document):
+        D = {}
+        D["Type"] = PDFName("Outlines")
+        c = self.count
+        D["Count"] = c
+        if c!=0:
+            D["First"] = self.first
+            D["Last"] = self.last
+        PD = PDFDictionary(D)
+        return PD.format(document)
+        
+    def setNames(self, canvas, *nametree):
+        desttree = self.translateNames(canvas, nametree)
+        self.setDestinations(desttree)
+        
+    def setNameList(self, canvas, nametree):
+        "Explicit list so I don't need to do apply(...) in the caller"
+        desttree = self.translateNames(canvas, nametree)
+        self.setDestinations(desttree)
+        
+    def translateNames(self, canvas, object):
+        "recursively translate tree of names into tree of destinations"
+        from types import StringType, ListType, TupleType
+        Ot = type(object)
+        destinationnamestotitles = self.destinationnamestotitles
+        destinationstotitles = self.destinationstotitles
+        closedict = self.closedict
+        if Ot is StringType:
+            destination = canvas._bookmarkReference(object)
+            title = object
+            if destinationnamestotitles.has_key(object):
+                title = destinationnamestotitles[object]
+            else:
+                destinationnamestotitles[title] = title
+            destinationstotitles[destination] = title
+            if closedict.has_key(object):
+                closedict[destination] = 1 # mark destination closed
+            return {object: canvas._bookmarkReference(object)} # name-->ref
+        if Ot is ListType or Ot is TupleType:
+            L = []
+            for o in object:
+                L.append(self.translateNames(canvas, o))
+            if Ot is TupleType:
+                return tuple(L)
+            return L
+        raise "in outline, destination name must be string: got a %s" % Ot
 
-	def prepare(self, document, canvas):
-		"""prepare all data structures required for save operation (create related objects)"""
-		if self.mydestinations is None:
-			if self.levelstack:
-				self.addOutlineEntry(None) # close the tree
-				destnames = self.levelstack[0]
-				#from pprint import pprint; pprint(destnames); stop
-				self.mydestinations = self.translateNames(canvas, destnames)
-			else:
-				self.first = self.last = None
-				self.count = 0
-				self.ready = 1
-				return
-		#self.first = document.objectReference("Outline.First")
-		#self.last = document.objectReference("Outline.Last")
-		# XXXX this needs to be generalized for closed entries!
-		self.count = count(self.mydestinations, self.closedict)
-		(self.first, self.last) = self.maketree(document, self.mydestinations, toplevel=1)
-		self.ready = 1
+    def prepare(self, document, canvas):
+        """prepare all data structures required for save operation (create related objects)"""
+        if self.mydestinations is None:
+            if self.levelstack:
+                self.addOutlineEntry(None) # close the tree
+                destnames = self.levelstack[0]
+                #from pprint import pprint; pprint(destnames); stop
+                self.mydestinations = self.translateNames(canvas, destnames)
+            else:
+                self.first = self.last = None
+                self.count = 0
+                self.ready = 1
+                return
+        #self.first = document.objectReference("Outline.First")
+        #self.last = document.objectReference("Outline.Last")
+        # XXXX this needs to be generalized for closed entries!
+        self.count = count(self.mydestinations, self.closedict)
+        (self.first, self.last) = self.maketree(document, self.mydestinations, toplevel=1)
+        self.ready = 1
 
-	def maketree(self, document, destinationtree, Parent=None, toplevel=0):
-		from types import ListType, TupleType, DictType
-		tdestinationtree = type(destinationtree)
-		if toplevel:
-			levelname = "Outline"
-			Parent = document.Reference(document.Outlines)
-		else:
-			self.count = self.count+1
-			levelname = "Outline.%s" % self.count
-			if Parent is None:
-				raise ValueError, "non-top level outline elt parent must be specified"
-		if tdestinationtree is not ListType and tdestinationtree is not TupleType:
-			raise ValueError, "destinationtree must be list or tuple, got %s"
-		nelts = len(destinationtree)
-		lastindex = nelts-1
-		lastelt = firstref = lastref = None
-		destinationnamestotitles = self.destinationnamestotitles
-		closedict = self.closedict
-		for index in range(nelts):
-			eltobj = OutlineEntryObject()
-			eltobj.Parent = Parent
-			eltname = "%s.%s" % (levelname, index)
-			eltref = document.Reference(eltobj, eltname)
-			#document.add(eltname, eltobj)
-			if lastelt is not None:
-				lastelt.Next = eltref
-				eltobj.Prev = lastref
-			if firstref is None:
-				firstref = eltref
-			lastref = eltref
-			lastelt = eltobj # advance eltobj
-			lastref = eltref
-			elt = destinationtree[index]
-			te = type(elt)
-			if te is DictType:
-				# simple leaf {name: dest}
-				leafdict = elt
-			elif te is TupleType:
-				# leaf with subsections: ({name: ref}, subsections) XXXX should clean up (see count(...))
-				try:
-					(leafdict, subsections) = elt
-				except:
-					raise ValueError, "destination tree elt tuple should have two elts, got %s" % len(elt)
-				eltobj.Count = count(subsections, closedict)
-				(eltobj.First, eltobj.Last) = self.maketree(document, subsections, eltref)
-			else:
-				raise ValueError, "destination tree elt should be dict or tuple, got %s" % te
-			try:
-				[(Title, Dest)] = leafdict.items()
-			except:
-				raise ValueError, "bad outline leaf dictionary, should have one entry "+str(elt)
-			eltobj.Title = destinationnamestotitles[Title]
-			eltobj.Dest = Dest
-			if te is TupleType and closedict.has_key(Dest):
-				# closed subsection, count should be negative
-				eltobj.Count = -eltobj.Count
-		return (firstref, lastref)
-		
+    def maketree(self, document, destinationtree, Parent=None, toplevel=0):
+        from types import ListType, TupleType, DictType
+        tdestinationtree = type(destinationtree)
+        if toplevel:
+            levelname = "Outline"
+            Parent = document.Reference(document.Outlines)
+        else:
+            self.count = self.count+1
+            levelname = "Outline.%s" % self.count
+            if Parent is None:
+                raise ValueError, "non-top level outline elt parent must be specified"
+        if tdestinationtree is not ListType and tdestinationtree is not TupleType:
+            raise ValueError, "destinationtree must be list or tuple, got %s"
+        nelts = len(destinationtree)
+        lastindex = nelts-1
+        lastelt = firstref = lastref = None
+        destinationnamestotitles = self.destinationnamestotitles
+        closedict = self.closedict
+        for index in range(nelts):
+            eltobj = OutlineEntryObject()
+            eltobj.Parent = Parent
+            eltname = "%s.%s" % (levelname, index)
+            eltref = document.Reference(eltobj, eltname)
+            #document.add(eltname, eltobj)
+            if lastelt is not None:
+                lastelt.Next = eltref
+                eltobj.Prev = lastref
+            if firstref is None:
+                firstref = eltref
+            lastref = eltref
+            lastelt = eltobj # advance eltobj
+            lastref = eltref
+            elt = destinationtree[index]
+            te = type(elt)
+            if te is DictType:
+                # simple leaf {name: dest}
+                leafdict = elt
+            elif te is TupleType:
+                # leaf with subsections: ({name: ref}, subsections) XXXX should clean up (see count(...))
+                try:
+                    (leafdict, subsections) = elt
+                except:
+                    raise ValueError, "destination tree elt tuple should have two elts, got %s" % len(elt)
+                eltobj.Count = count(subsections, closedict)
+                (eltobj.First, eltobj.Last) = self.maketree(document, subsections, eltref)
+            else:
+                raise ValueError, "destination tree elt should be dict or tuple, got %s" % te
+            try:
+                [(Title, Dest)] = leafdict.items()
+            except:
+                raise ValueError, "bad outline leaf dictionary, should have one entry "+str(elt)
+            eltobj.Title = destinationnamestotitles[Title]
+            eltobj.Dest = Dest
+            if te is TupleType and closedict.has_key(Dest):
+                # closed subsection, count should be negative
+                eltobj.Count = -eltobj.Count
+        return (firstref, lastref)
+        
 def count(tree, closedict=None): 
-	"""utility for outline: recursively count leaves in a tuple/list tree"""
-	from operator import add
-	from types import TupleType, ListType
-	tt = type(tree)
-	if tt is TupleType:
-		# leaf with subsections XXXX should clean up this structural usage
-		(leafdict, subsections) = tree
-		[(Title, Dest)] = leafdict.items()
-		if closedict and closedict.has_key(Dest):
-			return 1 # closed tree element
-	if tt is TupleType or tt is ListType:
-		#return reduce(add, map(count, tree))
-		counts = []
-		for e in tree:
-			counts.append(count(e, closedict))
-		return reduce(add, counts)
-	return 1
-	
-	
+    """utility for outline: recursively count leaves in a tuple/list tree"""
+    from operator import add
+    from types import TupleType, ListType
+    tt = type(tree)
+    if tt is TupleType:
+        # leaf with subsections XXXX should clean up this structural usage
+        (leafdict, subsections) = tree
+        [(Title, Dest)] = leafdict.items()
+        if closedict and closedict.has_key(Dest):
+            return 1 # closed tree element
+    if tt is TupleType or tt is ListType:
+        #return reduce(add, map(count, tree))
+        counts = []
+        for e in tree:
+            counts.append(count(e, closedict))
+        return reduce(add, counts)
+    return 1
+    
+    
 
 #### dummy info
 DUMMYINFO = """
--- a/reportlab/pdfbase/pdfmetrics.py	Fri Mar 02 15:35:43 2001 +0000
+++ b/reportlab/pdfbase/pdfmetrics.py	Tue Mar 06 17:38:15 2001 +0000
@@ -1,335 +1,2706 @@
-#copyright ReportLab Inc. 2000
-#see license.txt for license details
-#history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/pdfbase/pdfmetrics.py?cvsroot=reportlab
-#$Header: /tmp/reportlab/reportlab/pdfbase/pdfmetrics.py,v 1.21 2001/03/01 00:32:41 rgbecker Exp $
-__version__=''' $Id: pdfmetrics.py,v 1.21 2001/03/01 00:32:41 rgbecker Exp $ '''
-__doc__="""This contains pre-canned text metrics for the PDFgen package, and may also
-be used for any other PIDDLE back ends or packages which use the standard
-Type 1 postscript fonts.
+# widths database for 14 standard fonts - faster to parse then AFM
+"""This provides the character widths database for calculating
+text metrics.  Everything for the base 14 fonts is pre-computed
+and available in dictionaries and lists in this module.  The
+machinery is also available to parse AFM files annd add new fonts
+and encodings of fonts at run-time.
+
+There are two steps to adding a new font.  First, the width of each names
+glyph in the font must be added to the glyphs-by-name database. Then
+for a particular encoding of a font, # how to explain this.
+loadAFMFile() loads an AFM file, adding the glyph widths by name to the
+database.
+
+
+The static database portion of the file contains three dictionaries
+keyed on font names and leading to more data:
+    ascent_descent - ascent and descent for each font
+    widthsByName - glyph names and widths for each glyph in each font
+    encodings - encoding vectors for WinAnsiEncoding and MacRomanEncoding
+
+When the C accelerator module _rl_accel is not present, a dictionary
+widthsByOrdinal is populated each time a font is added.  This has
+vectors of 256 elements and is the data used by the stringWidth function.
+When _rl_accel is present, it maintains a similar database for itself.
+
+"""
+# mapping of name to width array, starts empty until fonts are added
+# e.g. widths['Courier'] = [...600,600,600,...]
+widthsByOrdinal = {}
+fontsByName = {}
+# conditional import - try both import techniques, and set a flag
+try:
+    from reportlab.lib import _rl_accel
+    hasAccel = 1
+except ImportError:
+    try:
+        import _rl_accel
+        hasAccel = 1
+    except ImportError:
+        hasAccel = 0
+
+
+def addFont(font):
+    """This lets us use the optimized C stringWidth or pdfmetrics stringwidth
+    function, saving one method call over asking the fonts to do it.  For
+    e.g. CID fonts, it falls back to asking the font itself."""
+    fontsByName[font.name] = font
+    if hasattr(font, 'getWidths'):
+        widthsByOrdinal[font.name] = font.getWidths()
+    
+        
+
+def stringWidth(text, fontName, fontSize):
+    try:
+        widths = widthsByOrdinal[fontName]
+        w = 0
+        for char in text:
+            w = w + widths[ord(char)]
+        return w*fontSize*0.001
+    except KeyError:
+        # CID Font?  ask the font itself
+        font = fonts[fontName]
+        return font.stringWidth(text, fontSize)
+
+
+
+# this is a list of the standard 14 font names in Acrobat Reader
+standardEnglishFonts = [
+    'Courier', 'Courier-Bold', 'Courier-Oblique', 'Courier-BoldOblique',
+    'Helvetica', 'Helvetica-Bold', 'Helvetica-Oblique', 'Helvetica-BoldOblique',
+    'Times-Roman', 'Times-Bold', 'Times-Italic', 'Times-BoldItalic',
+    'Symbol','ZapfDingbats']
+
+# this lists the predefined font encodings - WinAnsi and MacRoman.  We have
+# not added MacExpert - it's possible, but would complicate life and nobody
+# is asking.  StandardEncoding means something special.
+
+encodings = {}
+encodings['WinAnsiEncoding'] = [
+                None, None, None, None, None, None, None, None, None, None, None, None,
+                None, None, None, None, None, None, None, None, None, None, None, None,
+                None, None, None, None, None, None, None, None, 'space', 'exclam',
+                'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand',
+                'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma',
+                'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
+                'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
+                'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
+                'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+                'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
+                'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f',
+                'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+                'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright',
+                'asciitilde', 'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin',
+                'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', 'circumflex',
+                'perthousand', 'Scaron', 'guilsinglleft', 'OE', 'bullet', 'Zcaron',
+                'bullet', 'bullet', 'quoteleft', 'quoteright', 'quotedblleft',
+                'quotedblright', 'bullet', 'endash', 'emdash', 'tilde', 'trademark',
+                'scaron', 'guilsinglright', 'oe', 'bullet', 'zcaron', 'Ydieresis',
+                'space', 'exclamdown', 'cent', 'sterling', 'currency', 'yen', 'brokenbar',
+                'section', 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft',
+                'logicalnot', 'hyphen', 'registered', 'macron', 'degree', 'plusminus',
+                'twosuperior', 'threesuperior', 'acute', 'mu', 'paragraph', 'periodcentered',
+                'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright', 'onequarter',
+                'onehalf', 'threequarters', 'questiondown', 'Agrave', 'Aacute',
+                'Acircumflex', 'Atilde', 'Adieresis', 'Aring', 'AE', 'Ccedilla',
+                'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', 'Igrave', 'Iacute',
+                'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve', 'Oacute',
+                'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash', 'Ugrave',
+                'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn', 'germandbls',
+                'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis', 'aring', 'ae',
+                'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis', 'igrave',
+                'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve', 'oacute',
+                'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash', 'ugrave', 'uacute',
+                'ucircumflex', 'udieresis', 'yacute', 'thorn', 'ydieresis']
+
+encodings['MacRomanEncoding'] = [
+                 None, None, None, None, None, None, None, None, None, None, None, None,
+                 None, None, None, None, None, None, None, None, None, None, None, None,
+                 None, None, None, None, None, None, None, None, 'space', 'exclam',
+                 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand',
+                 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma',
+                 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
+                 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
+                 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
+                 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+                 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
+                 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f',
+                 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+                 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright',
+                 'asciitilde', None, 'Adieresis', 'Aring', 'Ccedilla', 'Eacute',
+                 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex',
+                 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave',
+                 'ecircumflex', 'edieresis', 'iacute', 'igrave', 'icircumflex',
+                 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis',
+                 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger',
+                 'degree', 'cent', 'sterling', 'section', 'bullet', 'paragraph',
+                 'germandbls', 'registered', 'copyright', 'trademark', 'acute',
+                 'dieresis', None, 'AE', 'Oslash', None, 'plusminus', None, None, 'yen',
+                 'mu', None, None, None, None, None, 'ordfeminine', 'ordmasculine', None,
+                 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', None, 'florin',
+                 None, None, 'guillemotleft', 'guillemotright', 'ellipsis', 'space', 'Agrave',
+                 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft',
+                 'quotedblright', 'quoteleft', 'quoteright', 'divide', None, 'ydieresis',
+                 'Ydieresis', 'fraction', 'currency', 'guilsinglleft', 'guilsinglright',
+                 'fi', 'fl', 'daggerdbl', 'periodcentered', 'quotesinglbase',
+                 'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute',
+                 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave',
+                 'Oacute', 'Ocircumflex', None, 'Ograve', 'Uacute', 'Ucircumflex',
+                 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve',
+                 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron']
+
+
+encodings['iso8859-2'] = [
+                 None, None, None, None, None, None, None, None, None, None, None, None,
+                 None, None, None, None, None, None, None, None, None, None, None, None,
+                 None, None, None, None, None, None, None, None, 'space', 'exclam',
+                 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand',
+                 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma',
+                 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
+                 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
+                 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
+                 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+                 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
+                 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f',
+                 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+                 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright',
+                 'asciitilde', 'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin',
+                 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', 'circumflex',
+                 'perthousand', 'Scaron', 'guilsinglleft', 'sacute', 'tcaron', 'zcaron',
+                 'zacute', 'bullet', 'quoteleft', 'quoteright', 'quotedblleft',
+                 'quotedblright', 'bullet', 'endash', 'emdash', 'tilde', 'trademark',
+                 'scaron', 'guilsinglright', 'oe', 'bullet', 'zcaron', 'Ydieresis', 'space',
+                 'Aogonek', 'breve', 'Lslash', 'currency', 'Lcaron', 'Sacute', 'section',
+                 'dieresis', 'Scaron', 'Scedilla', 'Tcaron', 'Zacute', 'hyphen', 'Zcaron',
+                 'Zdotaccent', 'degree', 'aogonek', 'ogonek', 'lslash', 'acute', 'lcaron',
+                 'sacute', 'caron', 'cedilla', 'scaron', 'scedilla', 'tcaron', 'zacute',
+                 'hungarumlaut', 'zcaron', 'zdotaccent', 'Racute', 'Aacute', 'Acircumflex',
+                 'Abreve', 'Adieresis', 'Lacute', 'Cacute', 'Ccedilla', 'Ccaron', 'Eacute',
+                 'Eogonek', 'Edieresis', 'Ecaron', 'Iacute', 'Icircumflex', 'Dcaron',
+                 'Dcroat', 'Nacute', 'Ncaron', 'Oacute', 'Ocircumflex', 'Ohungarumlaut',
+                 'Odieresis', 'multiply', 'Rcaron', 'Uring', 'Uacute', 'Uhungarumlaut',
+                 'Udieresis', 'Yacute', 'Tcommaaccent', 'germandbls', 'racute', 'aacute',
+                 'acircumflex', 'abreve', 'adieresis', 'lacute', 'cacute', 'ccedilla',
+                 'ccaron', 'eacute', 'eogonek', 'edieresis', 'ecaron', 'iacute', 'icircumflex',
+                 'dcaron', 'dcroat', 'nacute', 'ncaron', 'oacute', 'ocircumflex', 'ohungarumlaut',
+                 'odieresis', 'divide', 'rcaron', 'uring', 'uacute', 'uhungarumlaut', 'udieresis',
+                 'yacute', 'tcommaaccent', 'dotaccent']
+
+ascent_descent = {
+    'Courier': (629, -157),
+    'Courier-Bold': (626, -142),
+    'Courier-BoldOblique': (626, -142),
+    'Courier-Oblique': (629, -157),
+    'Helvetica': (718, -207),
+    'Helvetica-Bold': (718, -207),
+    'Helvetica-BoldOblique': (718, -207),
+    'Helvetica-Oblique': (718, -207),
+    'Times-Roman': (683, -217),
+    'Times-Bold': (676, -205),
+    'Times-BoldItalic': (699, -205),
+    'Times-Italic': (683, -205),
+    'Symbol': (0, 0),
+    'ZapfDingbats': (0, 0)
+    }
+
+# nuild this up one entry at a time to stay under JPython's 64k limit.
+widthsByName = {}
+widthsByName['Helvetica'] = {'A': 667,
+ 'AE': 1000,
+ 'Aacute': 667,
+ 'Acircumflex': 667,
+ 'Adieresis': 667,
+ 'Agrave': 667,
+ 'Aring': 667,
+ 'Atilde': 667,
+ 'B': 667,
+ 'C': 722,
+ 'Ccedilla': 722,
+ 'D': 722,
+ 'E': 667,
+ 'Eacute': 667,
+ 'Ecircumflex': 667,
+ 'Edieresis': 667,
+ 'Egrave': 667,
+ 'Eth': 722,
+ 'Euro': 556,
+ 'F': 611,
+ 'G': 778,
+ 'H': 722,
+ 'I': 278,
+ 'Iacute': 278,
+ 'Icircumflex': 278,
+ 'Idieresis': 278,
+ 'Igrave': 278,
+ 'J': 500,
+ 'K': 667,
+ 'L': 556,
+ 'Lslash': 556,
+ 'M': 833,
+ 'N': 722,
+ 'Ntilde': 722,
+ 'O': 778,
+ 'OE': 1000,
+ 'Oacute': 778,
+ 'Ocircumflex': 778,
+ 'Odieresis': 778,
+ 'Ograve': 778,
+ 'Oslash': 778,
+ 'Otilde': 778,
+ 'P': 667,
+ 'Q': 778,
+ 'R': 722,
+ 'S': 667,
+ 'Scaron': 667,
+ 'T': 611,
+ 'Thorn': 667,
+ 'U': 722,
+ 'Uacute': 722,
+ 'Ucircumflex': 722,
+ 'Udieresis': 722,
+ 'Ugrave': 722,
+ 'V': 667,
+ 'W': 944,
+ 'X': 667,
+ 'Y': 667,
+ 'Yacute': 667,
+ 'Ydieresis': 667,
+ 'Z': 611,
+ 'Zcaron': 611,
+ 'a': 556,
+ 'aacute': 556,
+ 'acircumflex': 556,
+ 'acute': 333,
+ 'adieresis': 556,
+ 'ae': 889,
+ 'agrave': 556,
+ 'ampersand': 667,
+ 'aring': 556,
+ 'asciicircum': 469,
+ 'asciitilde': 584,
+ 'asterisk': 389,
+ 'at': 1015,
+ 'atilde': 556,
+ 'b': 556,
+ 'backslash': 278,
+ 'bar': 260,
+ 'braceleft': 334,
+ 'braceright': 334,
+ 'bracketleft': 278,
+ 'bracketright': 278,
+ 'breve': 333,
+ 'brokenbar': 260,
+ 'bullet': 350,
+ 'c': 500,
+ 'caron': 333,
+ 'ccedilla': 500,
+ 'cedilla': 333,
+ 'cent': 556,
+ 'circumflex': 333,
+ 'colon': 278,
+ 'comma': 278,
+ 'copyright': 737,
+ 'currency': 556,
+ 'd': 556,
+ 'dagger': 556,
+ 'daggerdbl': 556,
+ 'degree': 400,
+ 'dieresis': 333,
+ 'divide': 584,
+ 'dollar': 556,
+ 'dotaccent': 333,
+ 'dotlessi': 278,
+ 'e': 556,
+ 'eacute': 556,
+ 'ecircumflex': 556,
+ 'edieresis': 556,
+ 'egrave': 556,
+ 'eight': 556,
+ 'ellipsis': 1000,
+ 'emdash': 1000,
+ 'endash': 556,
+ 'equal': 584,
+ 'eth': 556,
+ 'exclam': 278,
+ 'exclamdown': 333,
+ 'f': 278,
+ 'fi': 500,
+ 'five': 556,
+ 'fl': 500,
+ 'florin': 556,
+ 'four': 556,
+ 'fraction': 167,
+ 'g': 556,
+ 'germandbls': 611,
+ 'grave': 333,
+ 'greater': 584,
+ 'guillemotleft': 556,
+ 'guillemotright': 556,
+ 'guilsinglleft': 333,
+ 'guilsinglright': 333,
+ 'h': 556,
+ 'hungarumlaut': 333,
+ 'hyphen': 333,
+ 'i': 222,
+ 'iacute': 278,
+ 'icircumflex': 278,
+ 'idieresis': 278,
+ 'igrave': 278,
+ 'j': 222,
+ 'k': 500,
+ 'l': 222,
+ 'less': 584,
+ 'logicalnot': 584,
+ 'lslash': 222,
+ 'm': 833,
+ 'macron': 333,
+ 'minus': 584,
+ 'mu': 556,
+ 'multiply': 584,
+ 'n': 556,
+ 'nine': 556,
+ 'ntilde': 556,
+ 'numbersign': 556,
+ 'o': 556,
+ 'oacute': 556,
+ 'ocircumflex': 556,
+ 'odieresis': 556,
+ 'oe': 944,
+ 'ogonek': 333,
+ 'ograve': 556,
+ 'one': 556,
+ 'onehalf': 834,
+ 'onequarter': 834,
+ 'onesuperior': 333,
+ 'ordfeminine': 370,
+ 'ordmasculine': 365,
+ 'oslash': 611,
+ 'otilde': 556,
+ 'p': 556,
+ 'paragraph': 537,
+ 'parenleft': 333,
+ 'parenright': 333,
+ 'percent': 889,
+ 'period': 278,
+ 'periodcentered': 278,
+ 'perthousand': 1000,
+ 'plus': 584,
+ 'plusminus': 584,
+ 'q': 556,
+ 'question': 556,
+ 'questiondown': 611,
+ 'quotedbl': 355,
+ 'quotedblbase': 333,
+ 'quotedblleft': 333,
+ 'quotedblright': 333,
+ 'quoteleft': 222,
+ 'quoteright': 222,
+ 'quotesinglbase': 222,
+ 'quotesingle': 191,
+ 'r': 333,
+ 'registered': 737,
+ 'ring': 333,
+ 's': 500,
+ 'scaron': 500,
+ 'section': 556,
+ 'semicolon': 278,
+ 'seven': 556,
+ 'six': 556,
+ 'slash': 278,
+ 'space': 278,
+ 'sterling': 556,
+ 't': 278,
+ 'thorn': 556,
+ 'three': 556,
+ 'threequarters': 834,
+ 'threesuperior': 333,
+ 'tilde': 333,
+ 'trademark': 1000,
+ 'two': 556,
+ 'twosuperior': 333,
+ 'u': 556,
+ 'uacute': 556,
+ 'ucircumflex': 556,
+ 'udieresis': 556,
+ 'ugrave': 556,
+ 'underscore': 556,
+ 'v': 500,
+ 'w': 722,
+ 'x': 500,
+ 'y': 500,
+ 'yacute': 500,
+ 'ydieresis': 500,
+ 'yen': 556,
+ 'z': 500,
+ 'zcaron': 500,
+ 'zero': 556}
 
-Its main function is to let you work out the width of strings; it exposes a
-single function, stringWidth(text, fontName, fontSize), which works out the width of a
-string in the given font in points.
+widthsByName['Helvetica-Bold'] = {'A': 722,
+ 'AE': 1000,
+ 'Aacute': 722,
+ 'Acircumflex': 722,
+ 'Adieresis': 722,
+ 'Agrave': 722,
+ 'Aring': 722,
+ 'Atilde': 722,
+ 'B': 722,
+ 'C': 722,
+ 'Ccedilla': 722,
+ 'D': 722,
+ 'E': 667,
+ 'Eacute': 667,
+ 'Ecircumflex': 667,
+ 'Edieresis': 667,
+ 'Egrave': 667,
+ 'Eth': 722,
+ 'Euro': 556,
+ 'F': 611,
+ 'G': 778,
+ 'H': 722,
+ 'I': 278,
+ 'Iacute': 278,
+ 'Icircumflex': 278,
+ 'Idieresis': 278,
+ 'Igrave': 278,
+ 'J': 556,
+ 'K': 722,
+ 'L': 611,
+ 'Lslash': 611,
+ 'M': 833,
+ 'N': 722,
+ 'Ntilde': 722,
+ 'O': 778,
+ 'OE': 1000,
+ 'Oacute': 778,
+ 'Ocircumflex': 778,
+ 'Odieresis': 778,
+ 'Ograve': 778,
+ 'Oslash': 778,
+ 'Otilde': 778,
+ 'P': 667,
+ 'Q': 778,
+ 'R': 722,
+ 'S': 667,
+ 'Scaron': 667,
+ 'T': 611,
+ 'Thorn': 667,
+ 'U': 722,
+ 'Uacute': 722,
+ 'Ucircumflex': 722,
+ 'Udieresis': 722,
+ 'Ugrave': 722,
+ 'V': 667,
+ 'W': 944,
+ 'X': 667,
+ 'Y': 667,
+ 'Yacute': 667,
+ 'Ydieresis': 667,
+ 'Z': 611,
+ 'Zcaron': 611,
+ 'a': 556,
+ 'aacute': 556,
+ 'acircumflex': 556,
+ 'acute': 333,
+ 'adieresis': 556,
+ 'ae': 889,
+ 'agrave': 556,
+ 'ampersand': 722,
+ 'aring': 556,
+ 'asciicircum': 584,
+ 'asciitilde': 584,
+ 'asterisk': 389,
+ 'at': 975,
+ 'atilde': 556,
+ 'b': 611,
+ 'backslash': 278,
+ 'bar': 280,
+ 'braceleft': 389,
+ 'braceright': 389,
+ 'bracketleft': 333,
+ 'bracketright': 333,
+ 'breve': 333,
+ 'brokenbar': 280,
+ 'bullet': 350,
+ 'c': 556,
+ 'caron': 333,
+ 'ccedilla': 556,
+ 'cedilla': 333,
+ 'cent': 556,
+ 'circumflex': 333,
+ 'colon': 333,
+ 'comma': 278,
+ 'copyright': 737,
+ 'currency': 556,
+ 'd': 611,
+ 'dagger': 556,
+ 'daggerdbl': 556,
+ 'degree': 400,
+ 'dieresis': 333,
+ 'divide': 584,
+ 'dollar': 556,
+ 'dotaccent': 333,
+ 'dotlessi': 278,
+ 'e': 556,
+ 'eacute': 556,
+ 'ecircumflex': 556,
+ 'edieresis': 556,
+ 'egrave': 556,
+ 'eight': 556,
+ 'ellipsis': 1000,
+ 'emdash': 1000,
+ 'endash': 556,
+ 'equal': 584,
+ 'eth': 611,
+ 'exclam': 333,
+ 'exclamdown': 333,
+ 'f': 333,
+ 'fi': 611,
+ 'five': 556,
+ 'fl': 611,
+ 'florin': 556,
+ 'four': 556,
+ 'fraction': 167,
+ 'g': 611,
+ 'germandbls': 611,
+ 'grave': 333,
+ 'greater': 584,
+ 'guillemotleft': 556,
+ 'guillemotright': 556,
+ 'guilsinglleft': 333,
+ 'guilsinglright': 333,
+ 'h': 611,
+ 'hungarumlaut': 333,
+ 'hyphen': 333,
+ 'i': 278,
+ 'iacute': 278,
+ 'icircumflex': 278,
+ 'idieresis': 278,
+ 'igrave': 278,
+ 'j': 278,
+ 'k': 556,
+ 'l': 278,
+ 'less': 584,
+ 'logicalnot': 584,
+ 'lslash': 278,
+ 'm': 889,
+ 'macron': 333,
+ 'minus': 584,
+ 'mu': 611,
+ 'multiply': 584,
+ 'n': 611,
+ 'nine': 556,
+ 'ntilde': 611,
+ 'numbersign': 556,
+ 'o': 611,
+ 'oacute': 611,
+ 'ocircumflex': 611,
+ 'odieresis': 611,
+ 'oe': 944,
+ 'ogonek': 333,
+ 'ograve': 611,
+ 'one': 556,
+ 'onehalf': 834,
+ 'onequarter': 834,
+ 'onesuperior': 333,
+ 'ordfeminine': 370,
+ 'ordmasculine': 365,
+ 'oslash': 611,
+ 'otilde': 611,
+ 'p': 611,
+ 'paragraph': 556,
+ 'parenleft': 333,
+ 'parenright': 333,
+ 'percent': 889,
+ 'period': 278,
+ 'periodcentered': 278,
+ 'perthousand': 1000,
+ 'plus': 584,
+ 'plusminus': 584,
+ 'q': 611,
+ 'question': 611,
+ 'questiondown': 611,
+ 'quotedbl': 474,
+ 'quotedblbase': 500,
+ 'quotedblleft': 500,
+ 'quotedblright': 500,
+ 'quoteleft': 278,
+ 'quoteright': 278,
+ 'quotesinglbase': 278,
+ 'quotesingle': 238,
+ 'r': 389,
+ 'registered': 737,
+ 'ring': 333,
+ 's': 556,
+ 'scaron': 556,
+ 'section': 556,
+ 'semicolon': 333,
+ 'seven': 556,
+ 'six': 556,
+ 'slash': 278,
+ 'space': 278,
+ 'sterling': 556,
+ 't': 333,
+ 'thorn': 611,
+ 'three': 556,
+ 'threequarters': 834,
+ 'threesuperior': 333,
+ 'tilde': 333,
+ 'trademark': 1000,
+ 'two': 556,
+ 'twosuperior': 333,
+ 'u': 611,
+ 'uacute': 611,
+ 'ucircumflex': 611,
+ 'udieresis': 611,
+ 'ugrave': 611,
+ 'underscore': 556,
+ 'v': 556,
+ 'w': 778,
+ 'x': 556,
+ 'y': 556,
+ 'yacute': 556,
+ 'ydieresis': 556,
+ 'yen': 556,
+ 'z': 500,
+ 'zcaron': 500,
+ 'zero': 556}
 
-The AFM loading stuff worked for me but is not being heavily tested, as pre-canning
-the widths for the standard 14 fonts in Acrobat Reader is so much more useful. One
-could easily extend it to get the exact bounding box for each characterm useful for
-kerning.
+widthsByName['Helvetica-Oblique'] = {'A': 667,
+ 'AE': 1000,
+ 'Aacute': 667,
+ 'Acircumflex': 667,
+ 'Adieresis': 667,
+ 'Agrave': 667,
+ 'Aring': 667,
+ 'Atilde': 667,
+ 'B': 667,
+ 'C': 722,
+ 'Ccedilla': 722,
+ 'D': 722,
+ 'E': 667,
+ 'Eacute': 667,
+ 'Ecircumflex': 667,
+ 'Edieresis': 667,
+ 'Egrave': 667,
+ 'Eth': 722,
+ 'Euro': 556,
+ 'F': 611,
+ 'G': 778,
+ 'H': 722,
+ 'I': 278,
+ 'Iacute': 278,
+ 'Icircumflex': 278,
+ 'Idieresis': 278,
+ 'Igrave': 278,
+ 'J': 500,
+ 'K': 667,
+ 'L': 556,
+ 'Lslash': 556,
+ 'M': 833,
+ 'N': 722,
+ 'Ntilde': 722,
+ 'O': 778,
+ 'OE': 1000,
+ 'Oacute': 778,
+ 'Ocircumflex': 778,
+ 'Odieresis': 778,
+ 'Ograve': 778,
+ 'Oslash': 778,
+ 'Otilde': 778,
+ 'P': 667,
+ 'Q': 778,
+ 'R': 722,
+ 'S': 667,
+ 'Scaron': 667,
+ 'T': 611,
+ 'Thorn': 667,
+ 'U': 722,
+ 'Uacute': 722,
+ 'Ucircumflex': 722,
+ 'Udieresis': 722,
+ 'Ugrave': 722,
+ 'V': 667,
+ 'W': 944,
+ 'X': 667,
+ 'Y': 667,
+ 'Yacute': 667,
+ 'Ydieresis': 667,
+ 'Z': 611,
+ 'Zcaron': 611,
+ 'a': 556,
+ 'aacute': 556,
+ 'acircumflex': 556,
+ 'acute': 333,
+ 'adieresis': 556,
+ 'ae': 889,
+ 'agrave': 556,
+ 'ampersand': 667,
+ 'aring': 556,
+ 'asciicircum': 469,
+ 'asciitilde': 584,
+ 'asterisk': 389,
+ 'at': 1015,
+ 'atilde': 556,
+ 'b': 556,
+ 'backslash': 278,
+ 'bar': 260,
+ 'braceleft': 334,
+ 'braceright': 334,
+ 'bracketleft': 278,
+ 'bracketright': 278,
+ 'breve': 333,
+ 'brokenbar': 260,
+ 'bullet': 350,
+ 'c': 500,
+ 'caron': 333,
+ 'ccedilla': 500,
+ 'cedilla': 333,
+ 'cent': 556,
+ 'circumflex': 333,
+ 'colon': 278,
+ 'comma': 278,
+ 'copyright': 737,
+ 'currency': 556,
+ 'd': 556,
+ 'dagger': 556,
+ 'daggerdbl': 556,
+ 'degree': 400,
+ 'dieresis': 333,
+ 'divide': 584,
+ 'dollar': 556,
+ 'dotaccent': 333,
+ 'dotlessi': 278,
+ 'e': 556,
+ 'eacute': 556,
+ 'ecircumflex': 556,
+ 'edieresis': 556,
+ 'egrave': 556,
+ 'eight': 556,
+ 'ellipsis': 1000,
+ 'emdash': 1000,
+ 'endash': 556,
+ 'equal': 584,
+ 'eth': 556,
+ 'exclam': 278,
+ 'exclamdown': 333,
+ 'f': 278,
+ 'fi': 500,
+ 'five': 556,
+ 'fl': 500,
+ 'florin': 556,
+ 'four': 556,
+ 'fraction': 167,
+ 'g': 556,
+ 'germandbls': 611,
+ 'grave': 333,
+ 'greater': 584,
+ 'guillemotleft': 556,
+ 'guillemotright': 556,
+ 'guilsinglleft': 333,
+ 'guilsinglright': 333,
+ 'h': 556,
+ 'hungarumlaut': 333,
+ 'hyphen': 333,
+ 'i': 222,
+ 'iacute': 278,
+ 'icircumflex': 278,
+ 'idieresis': 278,
+ 'igrave': 278,
+ 'j': 222,
+ 'k': 500,
+ 'l': 222,
+ 'less': 584,
+ 'logicalnot': 584,
+ 'lslash': 222,
+ 'm': 833,
+ 'macron': 333,
+ 'minus': 584,
+ 'mu': 556,
+ 'multiply': 584,
+ 'n': 556,
+ 'nine': 556,
+ 'ntilde': 556,
+ 'numbersign': 556,
+ 'o': 556,
+ 'oacute': 556,
+ 'ocircumflex': 556,
+ 'odieresis': 556,
+ 'oe': 944,
+ 'ogonek': 333,
+ 'ograve': 556,
+ 'one': 556,
+ 'onehalf': 834,
+ 'onequarter': 834,
+ 'onesuperior': 333,
+ 'ordfeminine': 370,
+ 'ordmasculine': 365,
+ 'oslash': 611,
+ 'otilde': 556,
+ 'p': 556,
+ 'paragraph': 537,
+ 'parenleft': 333,
+ 'parenright': 333,
+ 'percent': 889,
+ 'period': 278,
+ 'periodcentered': 278,
+ 'perthousand': 1000,
+ 'plus': 584,
+ 'plusminus': 584,
+ 'q': 556,
+ 'question': 556,
+ 'questiondown': 611,
+ 'quotedbl': 355,
+ 'quotedblbase': 333,
+ 'quotedblleft': 333,
+ 'quotedblright': 333,
+ 'quoteleft': 222,
+ 'quoteright': 222,
+ 'quotesinglbase': 222,
+ 'quotesingle': 191,
+ 'r': 333,
+ 'registered': 737,
+ 'ring': 333,
+ 's': 500,
+ 'scaron': 500,
+ 'section': 556,
+ 'semicolon': 278,
+ 'seven': 556,
+ 'six': 556,
+ 'slash': 278,
+ 'space': 278,
+ 'sterling': 556,
+ 't': 278,
+ 'thorn': 556,
+ 'three': 556,
+ 'threequarters': 834,
+ 'threesuperior': 333,
+ 'tilde': 333,
+ 'trademark': 1000,
+ 'two': 556,
+ 'twosuperior': 333,
+ 'u': 556,
+ 'uacute': 556,
+ 'ucircumflex': 556,
+ 'udieresis': 556,
+ 'ugrave': 556,
+ 'underscore': 556,
+ 'v': 500,
+ 'w': 722,
+ 'x': 500,
+ 'y': 500,
+ 'yacute': 500,
+ 'ydieresis': 500,
+ 'yen': 556,
+ 'z': 500,
+ 'zcaron': 500,
+ 'zero': 556}
+
 
 
-The ascent_descent attribute of the module is a dictionary mapping font names
-(with the proper Postscript capitalisation) to ascents and descents.  I ought
-to sort out the fontname case issue and the resolution of PIDDLE fonts to
-Postscript font names within this module, but have not yet done so.
-"""
-import string
-import os
-from reportlab.lib.logger import warnOnce, infoOnce
-DEFAULT_ENCODING='WinAnsiEncoding'
-AFMDIR = 'C:\\code\\users\\andy\\fontembed'
-
-StandardEnglishFonts = [
-	'Courier', 'Courier-Bold', 'Courier-Oblique', 'Courier-BoldOblique',
-	'Helvetica', 'Helvetica-Bold', 'Helvetica-Oblique',
-	'Helvetica-BoldOblique',
-	'Times-Roman', 'Times-Bold', 'Times-Italic', 'Times-BoldItalic',
-	'Symbol','ZapfDingbats']
-
-##############################################################
-#
-#			PDF Metrics
-# This is a preamble to give us a stringWidth function.
-# loads and caches AFM files, but won't need to as the
-# standard fonts are there already
-##############################################################
-
-macromanencodingwidths={
-		'courier': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 0, 600, 0, 0, 600, 600, 0, 0, 0, 0, 0, 600, 600, 0, 600, 600, 600, 600, 600, 0, 600, 0, 0, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600],
-		'courier-bold': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 0, 600, 0, 0, 600, 600, 0, 0, 0, 0, 0, 600, 600, 0, 600, 600, 600, 600, 600, 0, 600, 0, 0, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600],
-		'courier-boldoblique': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 0, 600, 0, 0, 600, 600, 0, 0, 0, 0, 0, 600, 600, 0, 600, 600, 600, 600, 600, 0, 600, 0, 0, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600],
-		'courier-oblique': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 0, 600, 0, 0, 600, 600, 0, 0, 0, 0, 0, 600, 600, 0, 600, 600, 600, 600, 600, 0, 600, 0, 0, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600],
-		'helvetica': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 0, 667, 667, 722, 667, 722, 778, 722, 556, 556, 556, 556, 556, 556, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 400, 556, 556, 556, 350, 537, 611, 737, 737, 1000, 333, 333, 0, 1000, 778, 0, 584, 0, 0, 556, 556, 0, 0, 0, 0, 0, 370, 365, 0, 889, 611, 611, 333, 584, 0, 556, 0, 0, 556, 556, 1000, 0, 667, 667, 778, 1000, 944, 556, 1000, 333, 333, 222, 222, 584, 0, 500, 667, 167, 556, 333, 333, 500, 500, 556, 278, 222, 333, 1000, 667, 667, 667, 667, 667, 278, 278, 278, 278, 778, 778, 0, 778, 722, 722, 722, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667],
-		'helvetica-bold': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 0, 722, 722, 722, 667, 722, 778, 722, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 611, 611, 611, 556, 400, 556, 556, 556, 350, 556, 611, 737, 737, 1000, 333, 333, 0, 1000, 778, 0, 584, 0, 0, 556, 611, 0, 0, 0, 0, 0, 370, 365, 0, 889, 611, 611, 333, 584, 0, 556, 0, 0, 556, 556, 1000, 0, 722, 722, 778, 1000, 944, 556, 1000, 500, 500, 278, 278, 584, 0, 556, 667, 167, 556, 333, 333, 611, 611, 556, 278, 278, 500, 1000, 722, 667, 722, 667, 667, 278, 278, 278, 278, 778, 778, 0, 778, 722, 722, 722, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667],
-		'helvetica-boldoblique': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 0, 722, 722, 722, 667, 722, 778, 722, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 611, 611, 611, 556, 400, 556, 556, 556, 350, 556, 611, 737, 737, 1000, 333, 333, 0, 1000, 778, 0, 584, 0, 0, 556, 611, 0, 0, 0, 0, 0, 370, 365, 0, 889, 611, 611, 333, 584, 0, 556, 0, 0, 556, 556, 1000, 0, 722, 722, 778, 1000, 944, 556, 1000, 500, 500, 278, 278, 584, 0, 556, 667, 167, 556, 333, 333, 611, 611, 556, 278, 278, 500, 1000, 722, 667, 722, 667, 667, 278, 278, 278, 278, 778, 778, 0, 778, 722, 722, 722, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667],
-		'helvetica-oblique': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 0, 667, 667, 722, 667, 722, 778, 722, 556, 556, 556, 556, 556, 556, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 400, 556, 556, 556, 350, 537, 611, 737, 737, 1000, 333, 333, 0, 1000, 778, 0, 584, 0, 0, 556, 556, 0, 0, 0, 0, 0, 370, 365, 0, 889, 611, 611, 333, 584, 0, 556, 0, 0, 556, 556, 1000, 0, 667, 667, 778, 1000, 944, 556, 1000, 333, 333, 222, 222, 584, 0, 500, 667, 167, 556, 333, 333, 500, 500, 556, 278, 222, 333, 1000, 667, 667, 667, 667, 667, 278, 278, 278, 278, 778, 778, 0, 778, 722, 722, 722, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667],
-		'symbol': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 333, 0, 500, 0, 833, 778, 0, 333, 333, 0, 549, 250, 0, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 549, 549, 549, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 0, 333, 0, 500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 480, 200, 480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 400, 0, 0, 0, 460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 549, 0, 0, 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 713, 0, 500, 0, 0, 0, 0, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 549, 0, 0, 0, 167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 790],
-		'times-bold': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 333, 555, 500, 500, 1000, 833, 278, 333, 333, 500, 570, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, 930, 722, 667, 722, 722, 667, 611, 778, 778, 389, 500, 778, 667, 944, 722, 778, 611, 778, 722, 556, 667, 722, 722, 1000, 722, 722, 667, 333, 278, 333, 581, 500, 333, 500, 556, 444, 556, 444, 333, 500, 556, 278, 333, 556, 278, 833, 556, 500, 556, 556, 444, 389, 333, 556, 500, 722, 500, 500, 444, 394, 220, 394, 520, 0, 722, 722, 722, 667, 722, 778, 722, 500, 500, 500, 500, 500, 500, 444, 444, 444, 444, 444, 278, 278, 278, 278, 556, 500, 500, 500, 500, 500, 556, 556, 556, 556, 500, 400, 500, 500, 500, 350, 540, 556, 747, 747, 1000, 333, 333, 0, 1000, 778, 0, 570, 0, 0, 500, 556, 0, 0, 0, 0, 0, 300, 330, 0, 722, 500, 500, 333, 570, 0, 500, 0, 0, 500, 500, 1000, 0, 722, 722, 778, 1000, 722, 500, 1000, 500, 500, 333, 333, 570, 0, 500, 722, 167, 500, 333, 333, 556, 556, 500, 250, 333, 500, 1000, 722, 667, 722, 667, 667, 389, 389, 389, 389, 778, 778, 0, 778, 722, 722, 722, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 611],
-		'times-bolditalic': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 389, 555, 500, 500, 833, 778, 278, 333, 333, 500, 570, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, 832, 667, 667, 667, 722, 667, 667, 722, 778, 389, 500, 667, 611, 889, 722, 722, 611, 722, 667, 556, 611, 722, 667, 889, 667, 611, 611, 333, 278, 333, 570, 500, 333, 500, 500, 444, 500, 444, 333, 500, 556, 278, 278, 500, 278, 778, 556, 500, 500, 500, 389, 389, 278, 556, 444, 667, 500, 444, 389, 348, 220, 348, 570, 0, 667, 667, 667, 667, 722, 722, 722, 500, 500, 500, 500, 500, 500, 444, 444, 444, 444, 444, 278, 278, 278, 278, 556, 500, 500, 500, 500, 500, 556, 556, 556, 556, 500, 400, 500, 500, 500, 350, 500, 500, 747, 747, 1000, 333, 333, 0, 944, 722, 0, 570, 0, 0, 500, 576, 0, 0, 0, 0, 0, 266, 300, 0, 722, 500, 500, 389, 606, 0, 500, 0, 0, 500, 500, 1000, 0, 667, 667, 722, 944, 722, 500, 1000, 500, 500, 333, 333, 570, 0, 444, 611, 167, 500, 333, 333, 556, 556, 500, 250, 333, 500, 1000, 667, 667, 667, 667, 667, 389, 389, 389, 389, 722, 722, 0, 722, 722, 722, 722, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 611],
-		'times-italic': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 333, 420, 500, 500, 833, 778, 214, 333, 333, 500, 675, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 675, 675, 675, 500, 920, 611, 611, 667, 722, 611, 611, 722, 722, 333, 444, 667, 556, 833, 667, 722, 611, 722, 611, 500, 556, 722, 611, 833, 611, 556, 556, 389, 278, 389, 422, 500, 333, 500, 500, 444, 500, 444, 278, 500, 500, 278, 278, 444, 278, 722, 500, 500, 500, 500, 389, 389, 278, 500, 444, 667, 444, 444, 389, 400, 275, 400, 541, 0, 611, 611, 667, 611, 667, 722, 722, 500, 500, 500, 500, 500, 500, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 400, 500, 500, 500, 350, 523, 500, 760, 760, 980, 333, 333, 0, 889, 722, 0, 675, 0, 0, 500, 500, 0, 0, 0, 0, 0, 276, 310, 0, 667, 500, 500, 389, 675, 0, 500, 0, 0, 500, 500, 889, 0, 611, 611, 722, 944, 667, 500, 889, 556, 556, 333, 333, 675, 0, 444, 556, 167, 500, 333, 333, 500, 500, 500, 250, 333, 556, 1000, 611, 611, 611, 611, 611, 333, 333, 333, 333, 722, 722, 0, 722, 722, 722, 722, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 611],
-		'times-roman': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 333, 408, 500, 500, 833, 778, 180, 333, 333, 500, 564, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 564, 564, 564, 444, 921, 722, 667, 667, 722, 611, 556, 722, 722, 333, 389, 722, 611, 889, 722, 722, 556, 722, 667, 556, 611, 722, 722, 944, 722, 722, 611, 333, 278, 333, 469, 500, 333, 444, 500, 444, 500, 444, 333, 500, 500, 278, 278, 500, 278, 778, 500, 500, 500, 500, 333, 389, 278, 500, 500, 722, 500, 500, 444, 480, 200, 480, 541, 0, 722, 722, 667, 611, 722, 722, 722, 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 400, 500, 500, 500, 350, 453, 500, 760, 760, 980, 333, 333, 0, 889, 722, 0, 564, 0, 0, 500, 500, 0, 0, 0, 0, 0, 276, 310, 0, 667, 500, 444, 333, 564, 0, 500, 0, 0, 500, 500, 1000, 0, 722, 722, 722, 889, 722, 500, 1000, 444, 444, 333, 333, 564, 0, 500, 722, 167, 500, 333, 333, 556, 556, 500, 250, 333, 444, 1000, 722, 611, 722, 611, 611, 333, 333, 333, 333, 722, 722, 0, 722, 722, 722, 722, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 556],
-		'zapfdingbats': [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,278,974,961,974,980,719,789,790,791,690,960,939,549,855,911,933,911,945,974,755,846,762,761,571,677,763,760,759,754,494,552,537,577,692,786,788,788,790,793,794,816,823,789,841,823,833,816,831,923,744,723,749,790,792,695,776,768,792,759,707,708,682,701,826,815,789,789,707,687,696,689,786,787,713,791,785,791,873,761,762,762,759,759,892,892,788,784,438,138,277,415,392,392,668,668,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,732,544,544,910,667,760,760,776,595,694,626,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,894,838,1016,458,748,924,748,918,927,928,928,834,873,828,924,924,917,930,931,463,883,836,836,867,867,696,696,874,0,874,760,946,771,865,771,888,967,888,831,873,927,970,234,0]
-		}
-
-winansiencodingwidths={
-		'courier': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600],
-		'courier-bold': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600],
-		'courier-boldoblique': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600],
-		'courier-oblique': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 0, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 0, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600],
-		'helvetica': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 0, 0, 0, 222, 556, 333, 1000, 556, 556, 333, 1000, 667, 333, 1000, 0, 611, 0, 0, 222, 222, 333, 333, 350, 556, 1000, 333, 1000, 500, 333, 944, 0, 500, 667, 0, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 0, 737, 333, 400, 584, 333, 333, 333, 556, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 584, 611, 556, 556, 556, 556, 500, 556, 500],
-		'helvetica-bold': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 0, 0, 0, 278, 556, 500, 1000, 556, 556, 333, 1000, 667, 333, 1000, 0, 611, 0, 0, 278, 278, 500, 500, 350, 556, 1000, 333, 1000, 556, 333, 944, 0, 500, 667, 0, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 0, 737, 333, 400, 584, 333, 333, 333, 611, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 584, 611, 611, 611, 611, 611, 556, 611, 556],
-		'helvetica-boldoblique': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 0, 0, 0, 278, 556, 500, 1000, 556, 556, 333, 1000, 667, 333, 1000, 0, 611, 0, 0, 278, 278, 500, 500, 350, 556, 1000, 333, 1000, 556, 333, 944, 0, 500, 667, 0, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 0, 737, 333, 400, 584, 333, 333, 333, 611, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 584, 611, 611, 611, 611, 611, 556, 611, 556],
-		'helvetica-oblique': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 0, 0, 0, 222, 556, 333, 1000, 556, 556, 333, 1000, 667, 333, 1000, 0, 611, 0, 0, 222, 222, 333, 333, 350, 556, 1000, 333, 1000, 500, 333, 944, 0, 500, 667, 0, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 0, 737, 333, 400, 584, 333, 333, 333, 556, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 584, 611, 556, 556, 556, 556, 500, 556, 500],
-		'symbol': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 333, 0, 500, 0, 833, 778, 0, 333, 333, 0, 549, 250, 0, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 549, 549, 549, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 0, 333, 0, 500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 480, 200, 480, 0, 0, 750, 0, 0, 500, 0, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 713, 0, 0, 0, 400, 549, 0, 0, 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 549, 0, 0, 0, 0, 0, 0, 0, 790],
-		'times-bold': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 333, 555, 500, 500, 1000, 833, 278, 333, 333, 500, 570, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, 930, 722, 667, 722, 722, 667, 611, 778, 778, 389, 500, 778, 667, 944, 722, 778, 611, 778, 722, 556, 667, 722, 722, 1000, 722, 722, 667, 333, 278, 333, 581, 500, 333, 500, 556, 444, 556, 444, 333, 500, 556, 278, 333, 556, 278, 833, 556, 500, 556, 556, 444, 389, 333, 556, 500, 722, 500, 500, 444, 394, 220, 394, 520, 0, 0, 0, 333, 500, 500, 1000, 500, 500, 333, 1000, 556, 333, 1000, 0, 667, 0, 0, 333, 333, 500, 500, 350, 500, 1000, 333, 1000, 389, 333, 722, 0, 444, 722, 0, 333, 500, 500, 500, 500, 220, 500, 333, 747, 300, 500, 570, 0, 747, 333, 400, 570, 300, 300, 333, 556, 540, 250, 333, 300, 330, 500, 750, 750, 750, 500, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 389, 389, 389, 389, 722, 722, 778, 778, 778, 778, 778, 570, 778, 722, 722, 722, 722, 722, 611, 556, 500, 500, 500, 500, 500, 500, 722, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 556, 500, 500, 500, 500, 500, 570, 500, 556, 556, 556, 556, 500, 556, 500],
-		'times-bolditalic': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 389, 555, 500, 500, 833, 778, 278, 333, 333, 500, 570, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, 832, 667, 667, 667, 722, 667, 667, 722, 778, 389, 500, 667, 611, 889, 722, 722, 611, 722, 667, 556, 611, 722, 667, 889, 667, 611, 611, 333, 278, 333, 570, 500, 333, 500, 500, 444, 500, 444, 333, 500, 556, 278, 278, 500, 278, 778, 556, 500, 500, 500, 389, 389, 278, 556, 444, 667, 500, 444, 389, 348, 220, 348, 570, 0, 0, 0, 333, 500, 500, 1000, 500, 500, 333, 1000, 556, 333, 944, 0, 611, 0, 0, 333, 333, 500, 500, 350, 500, 1000, 333, 1000, 389, 333, 722, 0, 389, 611, 0, 389, 500, 500, 500, 500, 220, 500, 333, 747, 266, 500, 606, 0, 747, 333, 400, 570, 300, 300, 333, 576, 500, 250, 333, 300, 300, 500, 750, 750, 750, 500, 667, 667, 667, 667, 667, 667, 944, 667, 667, 667, 667, 667, 389, 389, 389, 389, 722, 722, 722, 722, 722, 722, 722, 570, 722, 722, 722, 722, 722, 611, 611, 500, 500, 500, 500, 500, 500, 500, 722, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 556, 500, 500, 500, 500, 500, 570, 500, 556, 556, 556, 556, 444, 500, 444],
-		'times-italic': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 333, 420, 500, 500, 833, 778, 214, 333, 333, 500, 675, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 675, 675, 675, 500, 920, 611, 611, 667, 722, 611, 611, 722, 722, 333, 444, 667, 556, 833, 667, 722, 611, 722, 611, 500, 556, 722, 611, 833, 611, 556, 556, 389, 278, 389, 422, 500, 333, 500, 500, 444, 500, 444, 278, 500, 500, 278, 278, 444, 278, 722, 500, 500, 500, 500, 389, 389, 278, 500, 444, 667, 444, 444, 389, 400, 275, 400, 541, 0, 0, 0, 333, 500, 556, 889, 500, 500, 333, 1000, 500, 333, 944, 0, 556, 0, 0, 333, 333, 556, 556, 350, 500, 889, 333, 980, 389, 333, 667, 0, 389, 556, 0, 389, 500, 500, 500, 500, 275, 500, 333, 760, 276, 500, 675, 0, 760, 333, 400, 675, 300, 300, 333, 500, 523, 250, 333, 300, 310, 500, 750, 750, 750, 500, 611, 611, 611, 611, 611, 611, 889, 667, 611, 611, 611, 611, 333, 333, 333, 333, 722, 667, 722, 722, 722, 722, 722, 675, 722, 722, 722, 722, 722, 556, 611, 500, 500, 500, 500, 500, 500, 500, 667, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 500, 500, 500, 500, 500, 500, 675, 500, 500, 500, 500, 500, 444, 500, 444],
-		'times-roman': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 333, 408, 500, 500, 833, 778, 180, 333, 333, 500, 564, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 564, 564, 564, 444, 921, 722, 667, 667, 722, 611, 556, 722, 722, 333, 389, 722, 611, 889, 722, 722, 556, 722, 667, 556, 611, 722, 722, 944, 722, 722, 611, 333, 278, 333, 469, 500, 333, 444, 500, 444, 500, 444, 333, 500, 500, 278, 278, 500, 278, 778, 500, 500, 500, 500, 333, 389, 278, 500, 500, 722, 500, 500, 444, 480, 200, 480, 541, 0, 0, 0, 333, 500, 444, 1000, 500, 500, 333, 1000, 556, 333, 889, 0, 611, 0, 0, 333, 333, 444, 444, 350, 500, 1000, 333, 980, 389, 333, 722, 0, 444, 722, 0, 333, 500, 500, 500, 500, 200, 500, 333, 760, 276, 500, 564, 0, 760, 333, 400, 564, 300, 300, 333, 500, 453, 250, 333, 300, 310, 500, 750, 750, 750, 444, 722, 722, 722, 722, 722, 722, 889, 667, 611, 611, 611, 611, 333, 333, 333, 333, 722, 722, 722, 722, 722, 722, 722, 564, 722, 722, 722, 722, 722, 722, 556, 500, 444, 444, 444, 444, 444, 444, 667, 444, 444, 444, 444, 444, 278, 278, 278, 278, 500, 500, 500, 500, 500, 500, 500, 564, 500, 500, 500, 500, 500, 500, 500, 500],
-		'zapfdingbats': [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,278,974,961,974,980,719,789,790,791,690,960,939,549,855,911,933,911,945,974,755,846,762,761,571,677,763,760,759,754,494,552,537,577,692,786,788,788,790,793,794,816,823,789,841,823,833,816,831,923,744,723,749,790,792,695,776,768,792,759,707,708,682,701,826,815,789,789,707,687,696,689,786,787,713,791,785,791,873,761,762,762,759,759,892,892,788,784,438,138,277,415,392,392,668,668,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,732,544,544,910,667,760,760,776,595,694,626,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,894,838,1016,458,748,924,748,918,927,928,928,834,873,828,924,924,917,930,931,463,883,836,836,867,867,696,696,874,0,874,760,946,771,865,771,888,967,888,831,873,927,970,234,0]
-		}
-
-widths={
-	'MacRomanEncoding': macromanencodingwidths , 'WinAnsiEncoding': winansiencodingwidths
-	}
-
-#HACK to get proper bullet metrics - don't know why they are zero!
-winansiencodingwidths['courier'][129] = 6
+widthsByName['Helvetica-BoldOblique'] = {'A': 722,
+ 'AE': 1000,
+ 'Aacute': 722,
+ 'Acircumflex': 722,
+ 'Adieresis': 722,
+ 'Agrave': 722,
+ 'Aring': 722,
+ 'Atilde': 722,
+ 'B': 722,
+ 'C': 722,
+ 'Ccedilla': 722,
+ 'D': 722,
+ 'E': 667,
+ 'Eacute': 667,
+ 'Ecircumflex': 667,
+ 'Edieresis': 667,
+ 'Egrave': 667,
+ 'Eth': 722,
+ 'Euro': 556,
+ 'F': 611,
+ 'G': 778,
+ 'H': 722,
+ 'I': 278,
+ 'Iacute': 278,
+ 'Icircumflex': 278,
+ 'Idieresis': 278,
+ 'Igrave': 278,
+ 'J': 556,
+ 'K': 722,
+ 'L': 611,
+ 'Lslash': 611,
+ 'M': 833,
+ 'N': 722,
+ 'Ntilde': 722,
+ 'O': 778,
+ 'OE': 1000,
+ 'Oacute': 778,
+ 'Ocircumflex': 778,
+ 'Odieresis': 778,
+ 'Ograve': 778,
+ 'Oslash': 778,
+ 'Otilde': 778,
+ 'P': 667,
+ 'Q': 778,
+ 'R': 722,
+ 'S': 667,
+ 'Scaron': 667,
+ 'T': 611,
+ 'Thorn': 667,
+ 'U': 722,
+ 'Uacute': 722,
+ 'Ucircumflex': 722,
+ 'Udieresis': 722,
+ 'Ugrave': 722,
+ 'V': 667,
+ 'W': 944,
+ 'X': 667,
+ 'Y': 667,
+ 'Yacute': 667,
+ 'Ydieresis': 667,
+ 'Z': 611,
+ 'Zcaron': 611,
+ 'a': 556,
+ 'aacute': 556,
+ 'acircumflex': 556,
+ 'acute': 333,
+ 'adieresis': 556,
+ 'ae': 889,
+ 'agrave': 556,
+ 'ampersand': 722,
+ 'aring': 556,
+ 'asciicircum': 584,
+ 'asciitilde': 584,
+ 'asterisk': 389,
+ 'at': 975,
+ 'atilde': 556,
+ 'b': 611,
+ 'backslash': 278,
+ 'bar': 280,
+ 'braceleft': 389,
+ 'braceright': 389,
+ 'bracketleft': 333,
+ 'bracketright': 333,
+ 'breve': 333,
+ 'brokenbar': 280,
+ 'bullet': 350,
+ 'c': 556,
+ 'caron': 333,
+ 'ccedilla': 556,
+ 'cedilla': 333,
+ 'cent': 556,
+ 'circumflex': 333,
+ 'colon': 333,
+ 'comma': 278,
+ 'copyright': 737,
+ 'currency': 556,
+ 'd': 611,
+ 'dagger': 556,
+ 'daggerdbl': 556,
+ 'degree': 400,
+ 'dieresis': 333,
+ 'divide': 584,
+ 'dollar': 556,
+ 'dotaccent': 333,
+ 'dotlessi': 278,
+ 'e': 556,
+ 'eacute': 556,
+ 'ecircumflex': 556,
+ 'edieresis': 556,
+ 'egrave': 556,
+ 'eight': 556,
+ 'ellipsis': 1000,
+ 'emdash': 1000,
+ 'endash': 556,
+ 'equal': 584,
+ 'eth': 611,
+ 'exclam': 333,
+ 'exclamdown': 333,
+ 'f': 333,
+ 'fi': 611,
+ 'five': 556,
+ 'fl': 611,
+ 'florin': 556,
+ 'four': 556,
+ 'fraction': 167,
+ 'g': 611,
+ 'germandbls': 611,
+ 'grave': 333,
+ 'greater': 584,
+ 'guillemotleft': 556,
+ 'guillemotright': 556,
+ 'guilsinglleft': 333,
+ 'guilsinglright': 333,
+ 'h': 611,
+ 'hungarumlaut': 333,
+ 'hyphen': 333,
+ 'i': 278,
+ 'iacute': 278,
+ 'icircumflex': 278,
+ 'idieresis': 278,
+ 'igrave': 278,
+ 'j': 278,
+ 'k': 556,
+ 'l': 278,
+ 'less': 584,
+ 'logicalnot': 584,
+ 'lslash': 278,
+ 'm': 889,
+ 'macron': 333,
+ 'minus': 584,
+ 'mu': 611,
+ 'multiply': 584,
+ 'n': 611,
+ 'nine': 556,
+ 'ntilde': 611,
+ 'numbersign': 556,
+ 'o': 611,
+ 'oacute': 611,
+ 'ocircumflex': 611,
+ 'odieresis': 611,
+ 'oe': 944,
+ 'ogonek': 333,
+ 'ograve': 611,
+ 'one': 556,
+ 'onehalf': 834,
+ 'onequarter': 834,
+ 'onesuperior': 333,
+ 'ordfeminine': 370,
+ 'ordmasculine': 365,
+ 'oslash': 611,
+ 'otilde': 611,
+ 'p': 611,
+ 'paragraph': 556,
+ 'parenleft': 333,
+ 'parenright': 333,
+ 'percent': 889,
+ 'period': 278,
+ 'periodcentered': 278,
+ 'perthousand': 1000,
+ 'plus': 584,
+ 'plusminus': 584,
+ 'q': 611,
+ 'question': 611,
+ 'questiondown': 611,
+ 'quotedbl': 474,
+ 'quotedblbase': 500,
+ 'quotedblleft': 500,
+ 'quotedblright': 500,
+ 'quoteleft': 278,
+ 'quoteright': 278,
+ 'quotesinglbase': 278,
+ 'quotesingle': 238,
+ 'r': 389,
+ 'registered': 737,
+ 'ring': 333,
+ 's': 556,
+ 'scaron': 556,
+ 'section': 556,
+ 'semicolon': 333,
+ 'seven': 556,
+ 'six': 556,
+ 'slash': 278,
+ 'space': 278,
+ 'sterling': 556,
+ 't': 333,
+ 'thorn': 611,
+ 'three': 556,
+ 'threequarters': 834,
+ 'threesuperior': 333,
+ 'tilde': 333,
+ 'trademark': 1000,
+ 'two': 556,
+ 'twosuperior': 333,
+ 'u': 611,
+ 'uacute': 611,
+ 'ucircumflex': 611,
+ 'udieresis': 611,
+ 'ugrave': 611,
+ 'underscore': 556,
+ 'v': 556,
+ 'w': 778,
+ 'x': 556,
+ 'y': 556,
+ 'yacute': 556,
+ 'ydieresis': 556,
+ 'yen': 556,
+ 'z': 500,
+ 'zcaron': 500,
+ 'zero': 556}
 
-ascent_descent = {'courier': (629, -157), 'courier-bold': (626, -142), 'courier-boldoblique': (626, -142), 'courier-oblique': (629, -157), 'helvetica': (718, -207), 'helvetica-bold': (718, -207), 'helvetica-boldoblique': (718, -207), 'helvetica-oblique': (718, -207), 'symbol': (0, 0), 'times-bold': (676, -205), 'times-bolditalic': (699, -205), 'times-italic': (683, -205), 'times-roman': (683, -217), 'zapfdingbats': (0, 0)}
-try:
-	try:
-		from reportlab.lib import _rl_accel
-	except ImportError, errMsg:
-		if str(errMsg)!='cannot import name _rl_accel': raise
-		import _rl_accel
-	_stringWidth = _rl_accel.stringWidth
-except ImportError, errMsg:
-	if str(errMsg)!='No module named _rl_accel': raise
-	_stringWidth = None
-
-	####################################################################################
-	#
-	#  Everything below here is concerned with parsing AFM files and adding metrics
-	#  for new fonts at runtime.
-	#
-	####################################################################################
+# Courier can be expressed more compactly!
+_w = {}
+for charname in widthsByName['Helvetica'].keys():
+    _w[charname] = 600
+widthsByName['Courier'] = _w
+widthsByName['Courier-Bold'] = _w
+widthsByName['Courier-Oblique'] = _w
+widthsByName['Courier-BoldOblique'] = _w
 
-WinAnsiNames = [None, None, None, None, None, None, None, None, None, None, None, None,
-				None, None, None, None, None, None, None, None, None, None, None, None,
-				None, None, None, None, None, None, None, None, 'space', 'exclam',
-				'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand',
-				'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma',
-				'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
-				'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
-				'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
-				'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
-				'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
-				'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f',
-				'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
-				'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright',
-				'asciitilde', 'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin',
-				'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', 'circumflex',
-				'perthousand', 'Scaron', 'guilsinglleft', 'OE', 'bullet', 'Zcaron',
-				'bullet', 'bullet', 'quoteleft', 'quoteright', 'quotedblleft',
-				'quotedblright', 'bullet', 'endash', 'emdash', 'tilde', 'trademark',
-				'scaron', 'guilsinglright', 'oe', 'bullet', 'zcaron', 'Ydieresis',
-				'space', 'exclamdown', 'cent', 'sterling', 'currency', 'yen', 'brokenbar',
-				'section', 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft',
-				'logicalnot', 'hyphen', 'registered', 'macron', 'degree', 'plusminus',
-				'twosuperior', 'threesuperior', 'acute', 'mu', 'paragraph', 'periodcentered',
-				'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright', 'onequarter',
-				'onehalf', 'threequarters', 'questiondown', 'Agrave', 'Aacute',
-				'Acircumflex', 'Atilde', 'Adieresis', 'Aring', 'AE', 'Ccedilla',
-				'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', 'Igrave', 'Iacute',
-				'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve', 'Oacute',
-				'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash', 'Ugrave',
-				'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn', 'germandbls',
-				'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis', 'aring', 'ae',
-				'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis', 'igrave',
-				'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve', 'oacute',
-				'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash', 'ugrave', 'uacute',
-				'ucircumflex', 'udieresis', 'yacute', 'thorn', 'ydieresis']
-
-MacRomanNames = [None, None, None, None, None, None, None, None, None, None, None, None,
-				 None, None, None, None, None, None, None, None, None, None, None, None,
-				 None, None, None, None, None, None, None, None, 'space', 'exclam',
-				 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand',
-				 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma',
-				 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
-				 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
-				 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
-				 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
-				 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
-				 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f',
-				 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
-				 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright',
-				 'asciitilde', None, 'Adieresis', 'Aring', 'Ccedilla', 'Eacute',
-				 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex',
-				 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave',
-				 'ecircumflex', 'edieresis', 'iacute', 'igrave', 'icircumflex',
-				 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis',
-				 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger',
-				 'degree', 'cent', 'sterling', 'section', 'bullet', 'paragraph',
-				 'germandbls', 'registered', 'copyright', 'trademark', 'acute',
-				 'dieresis', None, 'AE', 'Oslash', None, 'plusminus', None, None, 'yen',
-				 'mu', None, None, None, None, None, 'ordfeminine', 'ordmasculine', None,
-				 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', None, 'florin',
-				 None, None, 'guillemotleft', 'guillemotright', 'ellipsis', 'space', 'Agrave',
-				 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft',
-				 'quotedblright', 'quoteleft', 'quoteright', 'divide', None, 'ydieresis',
-				 'Ydieresis', 'fraction', 'currency', 'guilsinglleft', 'guilsinglright',
-				 'fi', 'fl', 'daggerdbl', 'periodcentered', 'quotesinglbase',
-				 'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute',
-				 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave',
-				 'Oacute', 'Ocircumflex', None, 'Ograve', 'Uacute', 'Ucircumflex',
-				 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve',
-				 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron']
+#
+widthsByName['Times-Romans'] = {'A': 722,
+ 'AE': 889,
+ 'Aacute': 722,
+ 'Acircumflex': 722,
+ 'Adieresis': 722,
+ 'Agrave': 722,
+ 'Aring': 722,
+ 'Atilde': 722,
+ 'B': 667,
+ 'C': 667,
+ 'Ccedilla': 667,
+ 'D': 722,
+ 'E': 611,
+ 'Eacute': 611,
+ 'Ecircumflex': 611,
+ 'Edieresis': 611,
+ 'Egrave': 611,
+ 'Eth': 722,
+ 'Euro': 500,
+ 'F': 556,
+ 'G': 722,
+ 'H': 722,
+ 'I': 333,
+ 'Iacute': 333,
+ 'Icircumflex': 333,
+ 'Idieresis': 333,
+ 'Igrave': 333,
+ 'J': 389,
+ 'K': 722,
+ 'L': 611,
+ 'Lslash': 611,
+ 'M': 889,
+ 'N': 722,
+ 'Ntilde': 722,
+ 'O': 722,
+ 'OE': 889,
+ 'Oacute': 722,
+ 'Ocircumflex': 722,
+ 'Odieresis': 722,
+ 'Ograve': 722,
+ 'Oslash': 722,
+ 'Otilde': 722,
+ 'P': 556,
+ 'Q': 722,
+ 'R': 667,
+ 'S': 556,
+ 'Scaron': 556,
+ 'T': 611,
+ 'Thorn': 556,
+ 'U': 722,
+ 'Uacute': 722,
+ 'Ucircumflex': 722,
+ 'Udieresis': 722,
+ 'Ugrave': 722,
+ 'V': 722,
+ 'W': 944,
+ 'X': 722,
+ 'Y': 722,
+ 'Yacute': 722,
+ 'Ydieresis': 722,
+ 'Z': 611,
+ 'Zcaron': 611,
+ 'a': 444,
+ 'aacute': 444,
+ 'acircumflex': 444,
+ 'acute': 333,
+ 'adieresis': 444,
+ 'ae': 667,
+ 'agrave': 444,
+ 'ampersand': 778,
+ 'aring': 444,
+ 'asciicircum': 469,
+ 'asciitilde': 541,
+ 'asterisk': 500,
+ 'at': 921,
+ 'atilde': 444,
+ 'b': 500,
+ 'backslash': 278,
+ 'bar': 200,
+ 'braceleft': 480,
+ 'braceright': 480,
+ 'bracketleft': 333,
+ 'bracketright': 333,
+ 'breve': 333,
+ 'brokenbar': 200,
+ 'bullet': 350,
+ 'c': 444,
+ 'caron': 333,
+ 'ccedilla': 444,
+ 'cedilla': 333,
+ 'cent': 500,
+ 'circumflex': 333,
+ 'colon': 278,
+ 'comma': 250,
+ 'copyright': 760,
+ 'currency': 500,
+ 'd': 500,
+ 'dagger': 500,
+ 'daggerdbl': 500,
+ 'degree': 400,
+ 'dieresis': 333,
+ 'divide': 564,
+ 'dollar': 500,
+ 'dotaccent': 333,
+ 'dotlessi': 278,
+ 'e': 444,
+ 'eacute': 444,
+ 'ecircumflex': 444,
+ 'edieresis': 444,
+ 'egrave': 444,
+ 'eight': 500,
+ 'ellipsis': 1000,
+ 'emdash': 1000,
+ 'endash': 500,
+ 'equal': 564,
+ 'eth': 500,
+ 'exclam': 333,
+ 'exclamdown': 333,
+ 'f': 333,
+ 'fi': 556,
+ 'five': 500,
+ 'fl': 556,
+ 'florin': 500,
+ 'four': 500,
+ 'fraction': 167,
+ 'g': 500,
+ 'germandbls': 500,
+ 'grave': 333,
+ 'greater': 564,
+ 'guillemotleft': 500,
+ 'guillemotright': 500,
+ 'guilsinglleft': 333,
+ 'guilsinglright': 333,
+ 'h': 500,
+ 'hungarumlaut': 333,
+ 'hyphen': 333,
+ 'i': 278,
+ 'iacute': 278,
+ 'icircumflex': 278,
+ 'idieresis': 278,
+ 'igrave': 278,
+ 'j': 278,
+ 'k': 500,
+ 'l': 278,
+ 'less': 564,
+ 'logicalnot': 564,
+ 'lslash': 278,
+ 'm': 778,
+ 'macron': 333,
+ 'minus': 564,
+ 'mu': 500,
+ 'multiply': 564,
+ 'n': 500,
+ 'nine': 500,
+ 'ntilde': 500,
+ 'numbersign': 500,
+ 'o': 500,
+ 'oacute': 500,
+ 'ocircumflex': 500,
+ 'odieresis': 500,
+ 'oe': 722,
+ 'ogonek': 333,
+ 'ograve': 500,
+ 'one': 500,
+ 'onehalf': 750,
+ 'onequarter': 750,
+ 'onesuperior': 300,
+ 'ordfeminine': 276,
+ 'ordmasculine': 310,
+ 'oslash': 500,
+ 'otilde': 500,
+ 'p': 500,
+ 'paragraph': 453,
+ 'parenleft': 333,
+ 'parenright': 333,
+ 'percent': 833,
+ 'period': 250,
+ 'periodcentered': 250,
+ 'perthousand': 1000,
+ 'plus': 564,
+ 'plusminus': 564,
+ 'q': 500,
+ 'question': 444,
+ 'questiondown': 444,
+ 'quotedbl': 408,
+ 'quotedblbase': 444,
+ 'quotedblleft': 444,
+ 'quotedblright': 444,
+ 'quoteleft': 333,
+ 'quoteright': 333,
+ 'quotesinglbase': 333,
+ 'quotesingle': 180,
+ 'r': 333,
+ 'registered': 760,
+ 'ring': 333,
+ 's': 389,
+ 'scaron': 389,
+ 'section': 500,
+ 'semicolon': 278,
+ 'seven': 500,
+ 'six': 500,
+ 'slash': 278,
+ 'space': 250,
+ 'sterling': 500,
+ 't': 278,
+ 'thorn': 500,
+ 'three': 500,
+ 'threequarters': 750,
+ 'threesuperior': 300,
+ 'tilde': 333,
+ 'trademark': 980,
+ 'two': 500,
+ 'twosuperior': 300,
+ 'u': 500,
+ 'uacute': 500,
+ 'ucircumflex': 500,
+ 'udieresis': 500,
+ 'ugrave': 500,
+ 'underscore': 500,
+ 'v': 500,
+ 'w': 722,
+ 'x': 500,
+ 'y': 500,
+ 'yacute': 500,
+ 'ydieresis': 500,
+ 'yen': 500,
+ 'z': 444,
+ 'zcaron': 444,
+ 'zero': 500}
 
 
-class FontMetrics:
-	"""This is an object which parses AFM files and holds all the
-	data they contain."""
-	def __init__(self, afmFileName):
-		self.fontName = None
-		self.widthsByPosition = []
-		self.parseAFMFile(afmFileName)
-
-	def parseAFMFile(self, filename):
-		"""Returns an array holding the widths of all characters in the font.
-		Ultra-crude parser"""
-		alllines = open(filename, 'r').readlines()
-		# get stuff between StartCharMetrics and EndCharMetrics
-		metriclines = []
-		between = 0
-		for line in alllines:
-			lline = string.lower(line)
-			i = string.find(lline,'fontName')
-			if i>=0:
-				fontName = string.strip(line[i+9:])
-				self.fontName = fontName
-			if string.find(lline, 'endcharmetrics') > -1:
-				between = 0
-				break
-			if between:
-				metriclines.append(line)
-			if string.find(lline, 'startcharmetrics') > -1:
-				between = 1
-
-		# break up - very shaky assumption about array size
-		widths = [0] * 256
-		widthsByName = {}
-		for line in metriclines:
-			chunks = string.split(line, ';')
+widthsByName['Times-Roman'] = {'A': 722,
+ 'AE': 889,
+ 'Aacute': 722,
+ 'Acircumflex': 722,
+ 'Adieresis': 722,
+ 'Agrave': 722,
+ 'Aring': 722,
+ 'Atilde': 722,
+ 'B': 667,
+ 'C': 667,
+ 'Ccedilla': 667,
+ 'D': 722,
+ 'E': 611,
+ 'Eacute': 611,
+ 'Ecircumflex': 611,
+ 'Edieresis': 611,
+ 'Egrave': 611,
+ 'Eth': 722,
+ 'Euro': 500,
+ 'F': 556,
+ 'G': 722,
+ 'H': 722,
+ 'I': 333,
+ 'Iacute': 333,
+ 'Icircumflex': 333,
+ 'Idieresis': 333,
+ 'Igrave': 333,
+ 'J': 389,
+ 'K': 722,
+ 'L': 611,
+ 'Lslash': 611,
+ 'M': 889,
+ 'N': 722,
+ 'Ntilde': 722,
+ 'O': 722,
+ 'OE': 889,
+ 'Oacute': 722,
+ 'Ocircumflex': 722,
+ 'Odieresis': 722,
+ 'Ograve': 722,
+ 'Oslash': 722,
+ 'Otilde': 722,
+ 'P': 556,
+ 'Q': 722,
+ 'R': 667,
+ 'S': 556,
+ 'Scaron': 556,
+ 'T': 611,
+ 'Thorn': 556,
+ 'U': 722,
+ 'Uacute': 722,
+ 'Ucircumflex': 722,
+ 'Udieresis': 722,
+ 'Ugrave': 722,
+ 'V': 722,
+ 'W': 944,
+ 'X': 722,
+ 'Y': 722,
+ 'Yacute': 722,
+ 'Ydieresis': 722,
+ 'Z': 611,
+ 'Zcaron': 611,
+ 'a': 444,
+ 'aacute': 444,
+ 'acircumflex': 444,
+ 'acute': 333,
+ 'adieresis': 444,
+ 'ae': 667,
+ 'agrave': 444,
+ 'ampersand': 778,
+ 'aring': 444,
+ 'asciicircum': 469,
+ 'asciitilde': 541,
+ 'asterisk': 500,
+ 'at': 921,
+ 'atilde': 444,
+ 'b': 500,
+ 'backslash': 278,
+ 'bar': 200,
+ 'braceleft': 480,
+ 'braceright': 480,
+ 'bracketleft': 333,
+ 'bracketright': 333,
+ 'breve': 333,
+ 'brokenbar': 200,
+ 'bullet': 350,
+ 'c': 444,
+ 'caron': 333,
+ 'ccedilla': 444,
+ 'cedilla': 333,
+ 'cent': 500,
+ 'circumflex': 333,
+ 'colon': 278,
+ 'comma': 250,
+ 'copyright': 760,
+ 'currency': 500,
+ 'd': 500,
+ 'dagger': 500,
+ 'daggerdbl': 500,
+ 'degree': 400,
+ 'dieresis': 333,
+ 'divide': 564,
+ 'dollar': 500,
+ 'dotaccent': 333,
+ 'dotlessi': 278,
+ 'e': 444,
+ 'eacute': 444,
+ 'ecircumflex': 444,
+ 'edieresis': 444,
+ 'egrave': 444,
+ 'eight': 500,
+ 'ellipsis': 1000,
+ 'emdash': 1000,
+ 'endash': 500,
+ 'equal': 564,
+ 'eth': 500,
+ 'exclam': 333,
+ 'exclamdown': 333,
+ 'f': 333,
+ 'fi': 556,
+ 'five': 500,
+ 'fl': 556,
+ 'florin': 500,
+ 'four': 500,
+ 'fraction': 167,
+ 'g': 500,
+ 'germandbls': 500,
+ 'grave': 333,
+ 'greater': 564,
+ 'guillemotleft': 500,
+ 'guillemotright': 500,
+ 'guilsinglleft': 333,
+ 'guilsinglright': 333,
+ 'h': 500,
+ 'hungarumlaut': 333,
+ 'hyphen': 333,
+ 'i': 278,
+ 'iacute': 278,
+ 'icircumflex': 278,
+ 'idieresis': 278,
+ 'igrave': 278,
+ 'j': 278,
+ 'k': 500,
+ 'l': 278,
+ 'less': 564,
+ 'logicalnot': 564,
+ 'lslash': 278,
+ 'm': 778,
+ 'macron': 333,
+ 'minus': 564,
+ 'mu': 500,
+ 'multiply': 564,
+ 'n': 500,
+ 'nine': 500,
+ 'ntilde': 500,
+ 'numbersign': 500,
+ 'o': 500,
+ 'oacute': 500,
+ 'ocircumflex': 500,
+ 'odieresis': 500,
+ 'oe': 722,
+ 'ogonek': 333,
+ 'ograve': 500,
+ 'one': 500,
+ 'onehalf': 750,
+ 'onequarter': 750,
+ 'onesuperior': 300,
+ 'ordfeminine': 276,
+ 'ordmasculine': 310,
+ 'oslash': 500,
+ 'otilde': 500,
+ 'p': 500,
+ 'paragraph': 453,
+ 'parenleft': 333,
+ 'parenright': 333,
+ 'percent': 833,
+ 'period': 250,
+ 'periodcentered': 250,
+ 'perthousand': 1000,
+ 'plus': 564,
+ 'plusminus': 564,
+ 'q': 500,
+ 'question': 444,
+ 'questiondown': 444,
+ 'quotedbl': 408,
+ 'quotedblbase': 444,
+ 'quotedblleft': 444,
+ 'quotedblright': 444,
+ 'quoteleft': 333,
+ 'quoteright': 333,
+ 'quotesinglbase': 333,
+ 'quotesingle': 180,
+ 'r': 333,
+ 'registered': 760,
+ 'ring': 333,
+ 's': 389,
+ 'scaron': 389,
+ 'section': 500,
+ 'semicolon': 278,
+ 'seven': 500,
+ 'six': 500,
+ 'slash': 278,
+ 'space': 250,
+ 'sterling': 500,
+ 't': 278,
+ 'thorn': 500,
+ 'three': 500,
+ 'threequarters': 750,
+ 'threesuperior': 300,
+ 'tilde': 333,
+ 'trademark': 980,
+ 'two': 500,
+ 'twosuperior': 300,
+ 'u': 500,
+ 'uacute': 500,
+ 'ucircumflex': 500,
+ 'udieresis': 500,
+ 'ugrave': 500,
+ 'underscore': 500,
+ 'v': 500,
+ 'w': 722,
+ 'x': 500,
+ 'y': 500,
+ 'yacute': 500,
+ 'ydieresis': 500,
+ 'yen': 500,
+ 'z': 444,
+ 'zcaron': 444,
+ 'zero': 500}
 
-			(c, cid) = string.split(chunks[0])
-			(wx, width) = string.split(chunks[1])
-			(n, name) = string.split(chunks[2])
-			#(b, x1, y1, x2, y2) = string.split(chunks[3])
-			widths[string.atoi(cid)] = string.atoi(width)
-			widthsByName[name] = string.atoi(width)
-
-		# by default, any empties should get the width of a space
-		for i in range(len(widths)):
-			if widths[i] == 0:
-				widths[i] == widths[32]
-
-		self.widthsByPosition = widths
-		self.widthsByName = widthsByName
-
-	def getWinAnsiWidths(self):
-		#derive a WinAnsi encoding vector
-		winAnsiWidths = [0] * 256
-		for i in range(255):
-			name = WinAnsiNames[i]
-			try:
-				width = self.widthsByName[name]
-			except:
-				width = 0
-			winAnsiWidths[i] = width
-		return winAnsiWidths
-
-	def getMacRomanWidths(self):
-		#derive a MacRoman encoding vector
-		MacRomanWidths = [0] * 256
-		for i in range(255):
-			name = MacRomanNames[i]
-			try:
-				width = self.widthsByName[name]
-			except:
-				width = 0
-			MacRomanWidths[i] = width
-		return MacRomanWidths
+widthsByName['Times-Bold'] = {'A': 722,
+ 'AE': 1000,
+ 'Aacute': 722,
+ 'Acircumflex': 722,
+ 'Adieresis': 722,
+ 'Agrave': 722,
+ 'Aring': 722,
+ 'Atilde': 722,
+ 'B': 667,
+ 'C': 722,
+ 'Ccedilla': 722,
+ 'D': 722,
+ 'E': 667,
+ 'Eacute': 667,
+ 'Ecircumflex': 667,
+ 'Edieresis': 667,
+ 'Egrave': 667,
+ 'Eth': 722,
+ 'Euro': 500,
+ 'F': 611,
+ 'G': 778,
+ 'H': 778,
+ 'I': 389,
+ 'Iacute': 389,
+ 'Icircumflex': 389,
+ 'Idieresis': 389,
+ 'Igrave': 389,
+ 'J': 500,
+ 'K': 778,
+ 'L': 667,
+ 'Lslash': 667,
+ 'M': 944,
+ 'N': 722,
+ 'Ntilde': 722,
+ 'O': 778,
+ 'OE': 1000,
+ 'Oacute': 778,
+ 'Ocircumflex': 778,
+ 'Odieresis': 778,
+ 'Ograve': 778,
+ 'Oslash': 778,
+ 'Otilde': 778,
+ 'P': 611,
+ 'Q': 778,
+ 'R': 722,
+ 'S': 556,
+ 'Scaron': 556,
+ 'T': 667,
+ 'Thorn': 611,
+ 'U': 722,
+ 'Uacute': 722,
+ 'Ucircumflex': 722,
+ 'Udieresis': 722,
+ 'Ugrave': 722,
+ 'V': 722,
+ 'W': 1000,
+ 'X': 722,
+ 'Y': 722,
+ 'Yacute': 722,
+ 'Ydieresis': 722,
+ 'Z': 667,
+ 'Zcaron': 667,
+ 'a': 500,
+ 'aacute': 500,
+ 'acircumflex': 500,
+ 'acute': 333,
+ 'adieresis': 500,
+ 'ae': 722,
+ 'agrave': 500,
+ 'ampersand': 833,
+ 'aring': 500,
+ 'asciicircum': 581,
+ 'asciitilde': 520,
+ 'asterisk': 500,
+ 'at': 930,
+ 'atilde': 500,
+ 'b': 556,
+ 'backslash': 278,
+ 'bar': 220,
+ 'braceleft': 394,
+ 'braceright': 394,
+ 'bracketleft': 333,
+ 'bracketright': 333,
+ 'breve': 333,
+ 'brokenbar': 220,
+ 'bullet': 350,
+ 'c': 444,
+ 'caron': 333,
+ 'ccedilla': 444,
+ 'cedilla': 333,
+ 'cent': 500,
+ 'circumflex': 333,
+ 'colon': 333,
+ 'comma': 250,
+ 'copyright': 747,
+ 'currency': 500,
+ 'd': 556,
+ 'dagger': 500,
+ 'daggerdbl': 500,
+ 'degree': 400,
+ 'dieresis': 333,
+ 'divide': 570,
+ 'dollar': 500,
+ 'dotaccent': 333,
+ 'dotlessi': 278,
+ 'e': 444,
+ 'eacute': 444,
+ 'ecircumflex': 444,
+ 'edieresis': 444,
+ 'egrave': 444,
+ 'eight': 500,
+ 'ellipsis': 1000,
+ 'emdash': 1000,
+ 'endash': 500,
+ 'equal': 570,
+ 'eth': 500,
+ 'exclam': 333,
+ 'exclamdown': 333,
+ 'f': 333,
+ 'fi': 556,
+ 'five': 500,
+ 'fl': 556,
+ 'florin': 500,
+ 'four': 500,
+ 'fraction': 167,
+ 'g': 500,
+ 'germandbls': 556,
+ 'grave': 333,
+ 'greater': 570,
+ 'guillemotleft': 500,
+ 'guillemotright': 500,
+ 'guilsinglleft': 333,
+ 'guilsinglright': 333,
+ 'h': 556,
+ 'hungarumlaut': 333,
+ 'hyphen': 333,
+ 'i': 278,
+ 'iacute': 278,
+ 'icircumflex': 278,
+ 'idieresis': 278,
+ 'igrave': 278,
+ 'j': 333,
+ 'k': 556,
+ 'l': 278,
+ 'less': 570,
+ 'logicalnot': 570,
+ 'lslash': 278,
+ 'm': 833,
+ 'macron': 333,
+ 'minus': 570,
+ 'mu': 556,
+ 'multiply': 570,
+ 'n': 556,
+ 'nine': 500,
+ 'ntilde': 556,
+ 'numbersign': 500,
+ 'o': 500,
+ 'oacute': 500,
+ 'ocircumflex': 500,
+ 'odieresis': 500,
+ 'oe': 722,
+ 'ogonek': 333,
+ 'ograve': 500,
+ 'one': 500,
+ 'onehalf': 750,
+ 'onequarter': 750,
+ 'onesuperior': 300,
+ 'ordfeminine': 300,
+ 'ordmasculine': 330,
+ 'oslash': 500,
+ 'otilde': 500,
+ 'p': 556,
+ 'paragraph': 540,
+ 'parenleft': 333,
+ 'parenright': 333,
+ 'percent': 1000,
+ 'period': 250,
+ 'periodcentered': 250,
+ 'perthousand': 1000,
+ 'plus': 570,
+ 'plusminus': 570,
+ 'q': 556,
+ 'question': 500,
+ 'questiondown': 500,
+ 'quotedbl': 555,
+ 'quotedblbase': 500,
+ 'quotedblleft': 500,
+ 'quotedblright': 500,
+ 'quoteleft': 333,
+ 'quoteright': 333,
+ 'quotesinglbase': 333,
+ 'quotesingle': 278,
+ 'r': 444,
+ 'registered': 747,
+ 'ring': 333,
+ 's': 389,
+ 'scaron': 389,
+ 'section': 500,
+ 'semicolon': 333,
+ 'seven': 500,
+ 'six': 500,
+ 'slash': 278,
+ 'space': 250,
+ 'sterling': 500,
+ 't': 333,
+ 'thorn': 556,
+ 'three': 500,
+ 'threequarters': 750,
+ 'threesuperior': 300,
+ 'tilde': 333,
+ 'trademark': 1000,
+ 'two': 500,
+ 'twosuperior': 300,
+ 'u': 556,
+ 'uacute': 556,
+ 'ucircumflex': 556,
+ 'udieresis': 556,
+ 'ugrave': 556,
+ 'underscore': 500,
+ 'v': 500,
+ 'w': 722,
+ 'x': 500,
+ 'y': 500,
+ 'yacute': 500,
+ 'ydieresis': 500,
+ 'yen': 500,
+ 'z': 444,
+ 'zcaron': 444,
+ 'zero': 500}
 
-if _stringWidth:
-	from reportlab.lib import RL_DEBUG
-	for e, F in widths.items():
-		for f, W in  F.items():
-			ad = ascent_descent[f]
-			_rl_accel.setFontInfo(f,e,ad[0],ad[1],W)
-			if RL_DEBUG:
-				for c in xrange(256):
-					wPy = W[c]
-					if wPy>0:
-						wX = int(1000*_stringWidth(chr(c),f,1,e))
-						if wX!=wPy:
-							raise ValueError, "_stringWidth(chr(%d),%s,1,%s)==>%d != %d" % (c,f,e,wX,wPy)
-	
-
-	def _loadfont(fontName, filename):
-		infoOnce('cache loading %s' % filename)
-		assert os.path.exists(filename)
-##		W = parseAFMfile(filename)
-##		ad = (0,0)	# TODO don't have this yet?
-##		_rl_accel.setFontInfo(fontName,encoding,ad[0],ad[1],W)
-		fm = FontMetrics(filename)
-		_rl_accel.setFontInfo(string.lower(fontName), 'WinAnsiEncoding', ad[0], ad[1], fm.getWinAnsiWidths())
-		_rl_accel.setFontInfo(string.lower(fontName), 'MacRomanEncoding', ad[0], ad[1], fm.getMacRomanWidths())
-
-
-	def _SWRecover(text, font, fontSize, encoding):
-		#infoOnce('_SWRecover('...',%s,%s,%s')%(font,str(fontSize),encoding))
-		try:
-			_loadFont(font,encoding)
-			return _stringWidth(text,font,fontSize,encoding)
-		except:
-			warnOnce('Font %s:%s not found - using Courier:%s for widths'%(font,encoding,encoding))
-			return _stringWidth(text,'courier',fontSize,encoding)
-
-	_rl_accel.defaultEncoding(DEFAULT_ENCODING)
-	_rl_accel._SWRecover(_SWRecover)
-	stringWidth = _stringWidth
-	loadFont = _loadfont
+widthsByName['Times-Italic'] = {'A': 611,
+ 'AE': 889,
+ 'Aacute': 611,
+ 'Acircumflex': 611,
+ 'Adieresis': 611,
+ 'Agrave': 611,
+ 'Aring': 611,
+ 'Atilde': 611,
+ 'B': 611,
+ 'C': 667,
+ 'Ccedilla': 667,
+ 'D': 722,
+ 'E': 611,
+ 'Eacute': 611,
+ 'Ecircumflex': 611,
+ 'Edieresis': 611,
+ 'Egrave': 611,
+ 'Eth': 722,
+ 'Euro': 500,
+ 'F': 611,
+ 'G': 722,
+ 'H': 722,
+ 'I': 333,
+ 'Iacute': 333,
+ 'Icircumflex': 333,
+ 'Idieresis': 333,
+ 'Igrave': 333,
+ 'J': 444,
+ 'K': 667,
+ 'L': 556,
+ 'Lslash': 556,
+ 'M': 833,
+ 'N': 667,
+ 'Ntilde': 667,
+ 'O': 722,
+ 'OE': 944,
+ 'Oacute': 722,
+ 'Ocircumflex': 722,
+ 'Odieresis': 722,
+ 'Ograve': 722,
+ 'Oslash': 722,
+ 'Otilde': 722,
+ 'P': 611,
+ 'Q': 722,
+ 'R': 611,
+ 'S': 500,
+ 'Scaron': 500,
+ 'T': 556,
+ 'Thorn': 611,
+ 'U': 722,
+ 'Uacute': 722,
+ 'Ucircumflex': 722,
+ 'Udieresis': 722,
+ 'Ugrave': 722,
+ 'V': 611,
+ 'W': 833,
+ 'X': 611,
+ 'Y': 556,
+ 'Yacute': 556,
+ 'Ydieresis': 556,
+ 'Z': 556,
+ 'Zcaron': 556,
+ 'a': 500,
+ 'aacute': 500,
+ 'acircumflex': 500,
+ 'acute': 333,
+ 'adieresis': 500,
+ 'ae': 667,
+ 'agrave': 500,
+ 'ampersand': 778,
+ 'aring': 500,
+ 'asciicircum': 422,
+ 'asciitilde': 541,
+ 'asterisk': 500,
+ 'at': 920,
+ 'atilde': 500,
+ 'b': 500,
+ 'backslash': 278,
+ 'bar': 275,
+ 'braceleft': 400,
+ 'braceright': 400,
+ 'bracketleft': 389,
+ 'bracketright': 389,
+ 'breve': 333,
+ 'brokenbar': 275,
+ 'bullet': 350,
+ 'c': 444,
+ 'caron': 333,
+ 'ccedilla': 444,
+ 'cedilla': 333,
+ 'cent': 500,
+ 'circumflex': 333,
+ 'colon': 333,
+ 'comma': 250,
+ 'copyright': 760,
+ 'currency': 500,
+ 'd': 500,
+ 'dagger': 500,
+ 'daggerdbl': 500,
+ 'degree': 400,
+ 'dieresis': 333,
+ 'divide': 675,
+ 'dollar': 500,
+ 'dotaccent': 333,
+ 'dotlessi': 278,
+ 'e': 444,
+ 'eacute': 444,
+ 'ecircumflex': 444,
+ 'edieresis': 444,
+ 'egrave': 444,
+ 'eight': 500,
+ 'ellipsis': 889,
+ 'emdash': 889,
+ 'endash': 500,
+ 'equal': 675,
+ 'eth': 500,
+ 'exclam': 333,
+ 'exclamdown': 389,
+ 'f': 278,
+ 'fi': 500,
+ 'five': 500,
+ 'fl': 500,
+ 'florin': 500,
+ 'four': 500,
+ 'fraction': 167,
+ 'g': 500,
+ 'germandbls': 500,
+ 'grave': 333,
+ 'greater': 675,
+ 'guillemotleft': 500,
+ 'guillemotright': 500,
+ 'guilsinglleft': 333,
+ 'guilsinglright': 333,
+ 'h': 500,
+ 'hungarumlaut': 333,
+ 'hyphen': 333,
+ 'i': 278,
+ 'iacute': 278,
+ 'icircumflex': 278,
+ 'idieresis': 278,
+ 'igrave': 278,
+ 'j': 278,
+ 'k': 444,
+ 'l': 278,
+ 'less': 675,
+ 'logicalnot': 675,
+ 'lslash': 278,
+ 'm': 722,
+ 'macron': 333,
+ 'minus': 675,
+ 'mu': 500,
+ 'multiply': 675,
+ 'n': 500,
+ 'nine': 500,
+ 'ntilde': 500,
+ 'numbersign': 500,
+ 'o': 500,
+ 'oacute': 500,
+ 'ocircumflex': 500,
+ 'odieresis': 500,
+ 'oe': 667,
+ 'ogonek': 333,
+ 'ograve': 500,
+ 'one': 500,
+ 'onehalf': 750,
+ 'onequarter': 750,
+ 'onesuperior': 300,
+ 'ordfeminine': 276,
+ 'ordmasculine': 310,
+ 'oslash': 500,
+ 'otilde': 500,
+ 'p': 500,
+ 'paragraph': 523,
+ 'parenleft': 333,
+ 'parenright': 333,
+ 'percent': 833,
+ 'period': 250,
+ 'periodcentered': 250,
+ 'perthousand': 1000,
+ 'plus': 675,
+ 'plusminus': 675,
+ 'q': 500,
+ 'question': 500,
+ 'questiondown': 500,
+ 'quotedbl': 420,
+ 'quotedblbase': 556,
+ 'quotedblleft': 556,
+ 'quotedblright': 556,
+ 'quoteleft': 333,
+ 'quoteright': 333,
+ 'quotesinglbase': 333,
+ 'quotesingle': 214,
+ 'r': 389,
+ 'registered': 760,
+ 'ring': 333,
+ 's': 389,
+ 'scaron': 389,
+ 'section': 500,
+ 'semicolon': 333,
+ 'seven': 500,
+ 'six': 500,
+ 'slash': 278,
+ 'space': 250,
+ 'sterling': 500,
+ 't': 278,
+ 'thorn': 500,
+ 'three': 500,
+ 'threequarters': 750,
+ 'threesuperior': 300,
+ 'tilde': 333,
+ 'trademark': 980,
+ 'two': 500,
+ 'twosuperior': 300,
+ 'u': 500,
+ 'uacute': 500,
+ 'ucircumflex': 500,
+ 'udieresis': 500,
+ 'ugrave': 500,
+ 'underscore': 500,
+ 'v': 444,
+ 'w': 667,
+ 'x': 444,
+ 'y': 444,
+ 'yacute': 444,
+ 'ydieresis': 444,
+ 'yen': 500,
+ 'z': 389,
+ 'zcaron': 389,
+ 'zero': 500}
 
-else:
-	class FontCache:
-		"""Loads and caches font width information on demand.  Font names
-		converted to lower case for indexing.  Public interface is stringWidth"""
-		def __init__(self):
-			global widths
-			self.__widtharrays = widths
-
-		def loadFont(self, fontName, filename):
-			infoOnce('Info: cache loading%s' % filename)
-			assert os.path.exists(filename)
-			fm = FontMetrics(filename)
-			self.__widtharrays['WinAnsiEncoding'][string.lower(fontName)] = fm.getWinAnsiWidths()
-			self.__widtharrays['MacRomanEncoding'][string.lower(fontName)] = fm.getMacRomanWidths()
-
+widthsByName['Times-BoldItalic'] = {'A': 667,
+ 'AE': 944,
+ 'Aacute': 667,
+ 'Acircumflex': 667,
+ 'Adieresis': 667,
+ 'Agrave': 667,
+ 'Aring': 667,
+ 'Atilde': 667,
+ 'B': 667,
+ 'C': 667,
+ 'Ccedilla': 667,
+ 'D': 722,
+ 'E': 667,
+ 'Eacute': 667,
+ 'Ecircumflex': 667,
+ 'Edieresis': 667,
+ 'Egrave': 667,
+ 'Eth': 722,
+ 'Euro': 500,
+ 'F': 667,
+ 'G': 722,
+ 'H': 778,
+ 'I': 389,
+ 'Iacute': 389,
+ 'Icircumflex': 389,
+ 'Idieresis': 389,
+ 'Igrave': 389,
+ 'J': 500,
+ 'K': 667,
+ 'L': 611,
+ 'Lslash': 611,
+ 'M': 889,
+ 'N': 722,
+ 'Ntilde': 722,
+ 'O': 722,
+ 'OE': 944,
+ 'Oacute': 722,
+ 'Ocircumflex': 722,
+ 'Odieresis': 722,
+ 'Ograve': 722,
+ 'Oslash': 722,
+ 'Otilde': 722,
+ 'P': 611,
+ 'Q': 722,
+ 'R': 667,
+ 'S': 556,
+ 'Scaron': 556,
+ 'T': 611,
+ 'Thorn': 611,
+ 'U': 722,
+ 'Uacute': 722,
+ 'Ucircumflex': 722,
+ 'Udieresis': 722,
+ 'Ugrave': 722,
+ 'V': 667,
+ 'W': 889,
+ 'X': 667,
+ 'Y': 611,
+ 'Yacute': 611,
+ 'Ydieresis': 611,
+ 'Z': 611,
+ 'Zcaron': 611,
+ 'a': 500,
+ 'aacute': 500,
+ 'acircumflex': 500,
+ 'acute': 333,
+ 'adieresis': 500,
+ 'ae': 722,
+ 'agrave': 500,
+ 'ampersand': 778,
+ 'aring': 500,
+ 'asciicircum': 570,
+ 'asciitilde': 570,
+ 'asterisk': 500,
+ 'at': 832,
+ 'atilde': 500,
+ 'b': 500,
+ 'backslash': 278,
+ 'bar': 220,
+ 'braceleft': 348,
+ 'braceright': 348,
+ 'bracketleft': 333,
+ 'bracketright': 333,
+ 'breve': 333,
+ 'brokenbar': 220,
+ 'bullet': 350,
+ 'c': 444,
+ 'caron': 333,
+ 'ccedilla': 444,
+ 'cedilla': 333,
+ 'cent': 500,
+ 'circumflex': 333,
+ 'colon': 333,
+ 'comma': 250,
+ 'copyright': 747,
+ 'currency': 500,
+ 'd': 500,
+ 'dagger': 500,
+ 'daggerdbl': 500,
+ 'degree': 400,
+ 'dieresis': 333,
+ 'divide': 570,
+ 'dollar': 500,
+ 'dotaccent': 333,
+ 'dotlessi': 278,
+ 'e': 444,
+ 'eacute': 444,
+ 'ecircumflex': 444,
+ 'edieresis': 444,
+ 'egrave': 444,
+ 'eight': 500,
+ 'ellipsis': 1000,
+ 'emdash': 1000,
+ 'endash': 500,
+ 'equal': 570,
+ 'eth': 500,
+ 'exclam': 389,
+ 'exclamdown': 389,
+ 'f': 333,
+ 'fi': 556,
+ 'five': 500,
+ 'fl': 556,
+ 'florin': 500,
+ 'four': 500,
+ 'fraction': 167,
+ 'g': 500,
+ 'germandbls': 500,
+ 'grave': 333,
+ 'greater': 570,
+ 'guillemotleft': 500,
+ 'guillemotright': 500,
+ 'guilsinglleft': 333,
+ 'guilsinglright': 333,
+ 'h': 556,
+ 'hungarumlaut': 333,
+ 'hyphen': 333,
+ 'i': 278,
+ 'iacute': 278,
+ 'icircumflex': 278,
+ 'idieresis': 278,
+ 'igrave': 278,
+ 'j': 278,
+ 'k': 500,
+ 'l': 278,
+ 'less': 570,
+ 'logicalnot': 606,
+ 'lslash': 278,
+ 'm': 778,
+ 'macron': 333,
+ 'minus': 606,
+ 'mu': 576,
+ 'multiply': 570,
+ 'n': 556,
+ 'nine': 500,
+ 'ntilde': 556,
+ 'numbersign': 500,
+ 'o': 500,
+ 'oacute': 500,
+ 'ocircumflex': 500,
+ 'odieresis': 500,
+ 'oe': 722,
+ 'ogonek': 333,
+ 'ograve': 500,
+ 'one': 500,
+ 'onehalf': 750,
+ 'onequarter': 750,
+ 'onesuperior': 300,
+ 'ordfeminine': 266,
+ 'ordmasculine': 300,
+ 'oslash': 500,
+ 'otilde': 500,
+ 'p': 500,
+ 'paragraph': 500,
+ 'parenleft': 333,
+ 'parenright': 333,
+ 'percent': 833,
+ 'period': 250,
+ 'periodcentered': 250,
+ 'perthousand': 1000,
+ 'plus': 570,
+ 'plusminus': 570,
+ 'q': 500,
+ 'question': 500,
+ 'questiondown': 500,
+ 'quotedbl': 555,
+ 'quotedblbase': 500,
+ 'quotedblleft': 500,
+ 'quotedblright': 500,
+ 'quoteleft': 333,
+ 'quoteright': 333,
+ 'quotesinglbase': 333,
+ 'quotesingle': 278,
+ 'r': 389,
+ 'registered': 747,
+ 'ring': 333,
+ 's': 389,
+ 'scaron': 389,
+ 'section': 500,
+ 'semicolon': 333,
+ 'seven': 500,
+ 'six': 500,
+ 'slash': 278,
+ 'space': 250,
+ 'sterling': 500,
+ 't': 278,
+ 'thorn': 500,
+ 'three': 500,
+ 'threequarters': 750,
+ 'threesuperior': 300,
+ 'tilde': 333,
+ 'trademark': 1000,
+ 'two': 500,
+ 'twosuperior': 300,
+ 'u': 556,
+ 'uacute': 556,
+ 'ucircumflex': 556,
+ 'udieresis': 556,
+ 'ugrave': 556,
+ 'underscore': 500,
+ 'v': 444,
+ 'w': 667,
+ 'x': 500,
+ 'y': 444,
+ 'yacute': 444,
+ 'ydieresis': 444,
+ 'yen': 500,
+ 'z': 389,
+ 'zcaron': 389,
+ 'zero': 500}
 
-		def getfont(self, fontName, encoding):
-			try:
-				return self.__widtharrays[encoding][fontName]
-			except:
-				try:
-					self.loadfont(fontName,encoding)
-					return self.__widtharrays[encoding][fontName]
-				except:
-					# font not found, use Courier
-					warnOnce('Font %s:%s not found - using Courier:%s for widths'%(fontName,encoding,encoding))
-					return self.getfont('courier',encoding)
+widthsByName['Symbol'] = {'Alpha': 722,
+ 'Beta': 667,
+ 'Chi': 722,
+ 'Delta': 612,
+ 'Epsilon': 611,
+ 'Eta': 722,
+ 'Euro': 750,
+ 'Gamma': 603,
+ 'Ifraktur': 686,
+ 'Iota': 333,
+ 'Kappa': 722,
+ 'Lambda': 686,
+ 'Mu': 889,
+ 'Nu': 722,
+ 'Omega': 768,
+ 'Omicron': 722,
+ 'Phi': 763,
+ 'Pi': 768,
+ 'Psi': 795,
+ 'Rfraktur': 795,
+ 'Rho': 556,
+ 'Sigma': 592,
+ 'Tau': 611,
+ 'Theta': 741,
+ 'Upsilon': 690,
+ 'Upsilon1': 620,
+ 'Xi': 645,
+ 'Zeta': 611,
+ 'aleph': 823,
+ 'alpha': 631,
+ 'ampersand': 778,
+ 'angle': 768,
+ 'angleleft': 329,
+ 'angleright': 329,
+ 'apple': 790,
+ 'approxequal': 549,
+ 'arrowboth': 1042,
+ 'arrowdblboth': 1042,
+ 'arrowdbldown': 603,
+ 'arrowdblleft': 987,
+ 'arrowdblright': 987,
+ 'arrowdblup': 603,
+ 'arrowdown': 603,
+ 'arrowhorizex': 1000,
+ 'arrowleft': 987,
+ 'arrowright': 987,
+ 'arrowup': 603,
+ 'arrowvertex': 603,
+ 'asteriskmath': 500,
+ 'bar': 200,
+ 'beta': 549,
+ 'braceex': 494,
+ 'braceleft': 480,
+ 'braceleftbt': 494,
+ 'braceleftmid': 494,
+ 'bracelefttp': 494,
+ 'braceright': 480,
+ 'bracerightbt': 494,
+ 'bracerightmid': 494,
+ 'bracerighttp': 494,
+ 'bracketleft': 333,
+ 'bracketleftbt': 384,
+ 'bracketleftex': 384,
+ 'bracketlefttp': 384,
+ 'bracketright': 333,
+ 'bracketrightbt': 384,
+ 'bracketrightex': 384,
+ 'bracketrighttp': 384,
+ 'bullet': 460,
+ 'carriagereturn': 658,
+ 'chi': 549,
+ 'circlemultiply': 768,
+ 'circleplus': 768,
+ 'club': 753,
+ 'colon': 278,
+ 'comma': 250,
+ 'congruent': 549,
+ 'copyrightsans': 790,
+ 'copyrightserif': 790,
+ 'degree': 400,
+ 'delta': 494,
+ 'diamond': 753,
+ 'divide': 549,
+ 'dotmath': 250,
+ 'eight': 500,
+ 'element': 713,
+ 'ellipsis': 1000,
+ 'emptyset': 823,
+ 'epsilon': 439,
+ 'equal': 549,
+ 'equivalence': 549,
+ 'eta': 603,
+ 'exclam': 333,
+ 'existential': 549,
+ 'five': 500,
+ 'florin': 500,
+ 'four': 500,
+ 'fraction': 167,
+ 'gamma': 411,
+ 'gradient': 713,
+ 'greater': 549,
+ 'greaterequal': 549,
+ 'heart': 753,
+ 'infinity': 713,
+ 'integral': 274,
+ 'integralbt': 686,
+ 'integralex': 686,
+ 'integraltp': 686,
+ 'intersection': 768,
+ 'iota': 329,
+ 'kappa': 549,
+ 'lambda': 549,
+ 'less': 549,
+ 'lessequal': 549,
+ 'logicaland': 603,
+ 'logicalnot': 713,
+ 'logicalor': 603,
+ 'lozenge': 494,
+ 'minus': 549,
+ 'minute': 247,
+ 'mu': 576,
+ 'multiply': 549,
+ 'nine': 500,
+ 'notelement': 713,
+ 'notequal': 549,
+ 'notsubset': 713,
+ 'nu': 521,
+ 'numbersign': 500,
+ 'omega': 686,
+ 'omega1': 713,
+ 'omicron': 549,
+ 'one': 500,
+ 'parenleft': 333,
+ 'parenleftbt': 384,
+ 'parenleftex': 384,
+ 'parenlefttp': 384,
+ 'parenright': 333,
+ 'parenrightbt': 384,
+ 'parenrightex': 384,
+ 'parenrighttp': 384,
+ 'partialdiff': 494,
+ 'percent': 833,
+ 'period': 250,
+ 'perpendicular': 658,
+ 'phi': 521,
+ 'phi1': 603,
+ 'pi': 549,
+ 'plus': 549,
+ 'plusminus': 549,
+ 'product': 823,
+ 'propersubset': 713,
+ 'propersuperset': 713,
+ 'proportional': 713,
+ 'psi': 686,
+ 'question': 444,
+ 'radical': 549,
+ 'radicalex': 500,
+ 'reflexsubset': 713,
+ 'reflexsuperset': 713,
+ 'registersans': 790,
+ 'registerserif': 790,
+ 'rho': 549,
+ 'second': 411,
+ 'semicolon': 278,
+ 'seven': 500,
+ 'sigma': 603,
+ 'sigma1': 439,
+ 'similar': 549,
+ 'six': 500,
+ 'slash': 278,
+ 'space': 250,
+ 'spade': 753,
+ 'suchthat': 439,
+ 'summation': 713,
+ 'tau': 439,
+ 'therefore': 863,
+ 'theta': 521,
+ 'theta1': 631,
+ 'three': 500,
+ 'trademarksans': 786,
+ 'trademarkserif': 890,
+ 'two': 500,
+ 'underscore': 500,
+ 'union': 768,
+ 'universal': 713,
+ 'upsilon': 576,
+ 'weierstrass': 987,
+ 'xi': 493,
+ 'zero': 500,
+ 'zeta': 494}
 
-		def stringWidth(self, text, font, fontSize, encoding=DEFAULT_ENCODING):
-			widths = self.getfont(string.lower(font),encoding)
-			w = 0
-			for char in text:
-				w = w + widths[ord(char)]
-			return w*fontSize*0.001
+widthsByName['ZapfDingbats'] = {'a1': 974,
+ 'a10': 692,
+ 'a100': 668,
+ 'a101': 732,
+ 'a102': 544,
+ 'a103': 544,
+ 'a104': 910,
+ 'a105': 911,
+ 'a106': 667,
+ 'a107': 760,
+ 'a108': 760,
+ 'a109': 626,
+ 'a11': 960,
+ 'a110': 694,
+ 'a111': 595,
+ 'a112': 776,
+ 'a117': 690,
+ 'a118': 791,
+ 'a119': 790,
+ 'a12': 939,
+ 'a120': 788,
+ 'a121': 788,
+ 'a122': 788,
+ 'a123': 788,
+ 'a124': 788,
+ 'a125': 788,
+ 'a126': 788,
+ 'a127': 788,
+ 'a128': 788,
+ 'a129': 788,
+ 'a13': 549,
+ 'a130': 788,
+ 'a131': 788,
+ 'a132': 788,
+ 'a133': 788,
+ 'a134': 788,
+ 'a135': 788,
+ 'a136': 788,
+ 'a137': 788,
+ 'a138': 788,
+ 'a139': 788,
+ 'a14': 855,
+ 'a140': 788,
+ 'a141': 788,
+ 'a142': 788,
+ 'a143': 788,
+ 'a144': 788,
+ 'a145': 788,
+ 'a146': 788,
+ 'a147': 788,
+ 'a148': 788,
+ 'a149': 788,
+ 'a15': 911,
+ 'a150': 788,
+ 'a151': 788,
+ 'a152': 788,
+ 'a153': 788,
+ 'a154': 788,
+ 'a155': 788,
+ 'a156': 788,
+ 'a157': 788,
+ 'a158': 788,
+ 'a159': 788,
+ 'a16': 933,
+ 'a160': 894,
+ 'a161': 838,
+ 'a162': 924,
+ 'a163': 1016,
+ 'a164': 458,
+ 'a165': 924,
+ 'a166': 918,
+ 'a167': 927,
+ 'a168': 928,
+ 'a169': 928,
+ 'a17': 945,
+ 'a170': 834,
+ 'a171': 873,
+ 'a172': 828,
+ 'a173': 924,
+ 'a174': 917,
+ 'a175': 930,
+ 'a176': 931,
+ 'a177': 463,
+ 'a178': 883,
+ 'a179': 836,
+ 'a18': 974,
+ 'a180': 867,
+ 'a181': 696,
+ 'a182': 874,
+ 'a183': 760,
+ 'a184': 946,
+ 'a185': 865,
+ 'a186': 967,
+ 'a187': 831,
+ 'a188': 873,
+ 'a189': 927,
+ 'a19': 755,
+ 'a190': 970,
+ 'a191': 918,
+ 'a192': 748,
+ 'a193': 836,
+ 'a194': 771,
+ 'a195': 888,
+ 'a196': 748,
+ 'a197': 771,
+ 'a198': 888,
+ 'a199': 867,
+ 'a2': 961,
+ 'a20': 846,
+ 'a200': 696,
+ 'a201': 874,
+ 'a202': 974,
+ 'a203': 762,
+ 'a204': 759,
+ 'a205': 509,
+ 'a206': 410,
+ 'a21': 762,
+ 'a22': 761,
+ 'a23': 571,
+ 'a24': 677,
+ 'a25': 763,
+ 'a26': 760,
+ 'a27': 759,
+ 'a28': 754,
+ 'a29': 786,
+ 'a3': 980,
+ 'a30': 788,
+ 'a31': 788,
+ 'a32': 790,
+ 'a33': 793,
+ 'a34': 794,
+ 'a35': 816,
+ 'a36': 823,
+ 'a37': 789,
+ 'a38': 841,
+ 'a39': 823,
+ 'a4': 719,
+ 'a40': 833,
+ 'a41': 816,
+ 'a42': 831,
+ 'a43': 923,
+ 'a44': 744,
+ 'a45': 723,
+ 'a46': 749,
+ 'a47': 790,
+ 'a48': 792,
+ 'a49': 695,
+ 'a5': 789,
+ 'a50': 776,
+ 'a51': 768,
+ 'a52': 792,
+ 'a53': 759,
+ 'a54': 707,
+ 'a55': 708,
+ 'a56': 682,
+ 'a57': 701,
+ 'a58': 826,
+ 'a59': 815,
+ 'a6': 494,
+ 'a60': 789,
+ 'a61': 789,
+ 'a62': 707,
+ 'a63': 687,
+ 'a64': 696,
+ 'a65': 689,
+ 'a66': 786,
+ 'a67': 787,
+ 'a68': 713,
+ 'a69': 791,
+ 'a7': 552,
+ 'a70': 785,
+ 'a71': 791,
+ 'a72': 873,
+ 'a73': 761,
+ 'a74': 762,
+ 'a75': 759,
+ 'a76': 892,
+ 'a77': 892,
+ 'a78': 788,
+ 'a79': 784,
+ 'a8': 537,
+ 'a81': 438,
+ 'a82': 138,
+ 'a83': 277,
+ 'a84': 415,
+ 'a85': 509,
+ 'a86': 410,
+ 'a87': 234,
+ 'a88': 234,
+ 'a89': 390,
+ 'a9': 577,
+ 'a90': 390,
+ 'a91': 276,
+ 'a92': 276,
+ 'a93': 317,
+ 'a94': 317,
+ 'a95': 334,
+ 'a96': 334,
+ 'a97': 392,
+ 'a98': 392,
+ 'a99': 668,
+ 'space': 278}
 
-		def status(self):
-			#returns loaded fonts
-			return self.__widtharrays.keys()
+# this is a hack - these are declared as 'StandardEncoding' in the PDF file,
+# which seems to mean 'ignore the names, always use this order'.  The font
+# classes have special case code to use these.
+SymbolWidths = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,278,974,961,974,980,719,789,790,791,690,960,939,549,855,911,933,911,945,974,755,846,762,761,571,677,763,760,759,754,494,552,537,577,692,786,788,788,790,793,794,816,823,789,841,823,833,816,831,923,744,723,749,790,792,695,776,768,792,759,707,708,682,701,826,815,789,789,707,687,696,689,786,787,713,791,785,791,873,761,762,762,759,759,892,892,788,784,438,138,277,415,392,392,668,668,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,732,544,544,910,667,760,760,776,595,694,626,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,894,838,1016,458,748,924,748,918,927,928,928,834,873,828,924,924,917,930,931,463,883,836,836,867,867,696,696,874,0,874,760,946,771,865,771,888,967,888,831,873,927,970,234,0]
+ZapfDingbatsWidths = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 333, 0, 500, 0, 833, 778, 0, 333, 333, 0, 549, 250, 0, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 549, 549, 549, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 0, 333, 0, 500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 480, 200, 480, 0, 0, 750, 0, 0, 500, 0, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 713, 0, 0, 0, 400, 549, 0, 0, 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 549, 0, 0, 0, 0, 0, 0, 0, 790]
 
-	TheFontCache = FontCache()
+def test():
+    # load the standard ones:
+    from reportlab.pdfgen import fonts0
+    for baseFontName in standardEnglishFonts:
+        encoding = fonts0.WinAnsi
+        fontName = baseFontName + '-WinAnsi'
+        font = fonts0.BuiltInType1Font(fontName, baseFontName, encoding)
+        addWidths(fontName, font.getWidths())
+        #test it
+        msg = 'Hello World'
+        w = stringWidth(msg, fontName, 10)#
+        print 'width of "%s" in 10-point %s = %0.2f' % (msg, fontName, w)
 
-	#expose the singleton as a single function
-	stringWidth = TheFontCache.stringWidth
-	loadFont = TheFontCache.loadFont
+if __name__=='__main__':
+    test()
+    
\ No newline at end of file
--- a/reportlab/pdfgen/canvas.py	Fri Mar 02 15:35:43 2001 +0000
+++ b/reportlab/pdfgen/canvas.py	Tue Mar 06 17:38:15 2001 +0000
@@ -1,37 +1,12 @@
 #copyright ReportLab Inc. 2000
 #see license.txt for license details
 #history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/pdfgen/canvas.py?cvsroot=reportlab
-#$Header: /tmp/reportlab/reportlab/pdfgen/canvas.py,v 1.62 2001/02/28 11:53:20 rgbecker Exp $
-__version__=''' $Id: canvas.py,v 1.62 2001/02/28 11:53:20 rgbecker Exp $ '''
+#$Header: /tmp/reportlab/reportlab/pdfgen/canvas.py,v 1.63 2001/03/06 17:38:15 andy_robinson Exp $
+__version__=''' $Id: canvas.py,v 1.63 2001/03/06 17:38:15 andy_robinson Exp $ '''
 __doc__=""" 
-PDFgen is a library to generate PDF files containing text and graphics.  It is the 
-foundation for a complete reporting solution in Python.  It is also the
-foundation for piddlePDF, the PDF back end for PIDDLE.
-
-Documentation is a little slim right now; run then look at testpdfgen.py
-to get a clue.
-
-Progress Reports:
-8.83, 2000-01-13, gmcm:
-    Packagizing:
-        renamed from pdfgen.py to canvas.py
-        broke out PDFTextObject to textobject.py
-        broke out PDFPathObject to pathobject.py
-        placed all three in a package directory named pdfgen
-0.82, 1999-10-27, AR:
-        Fixed some bugs on printing to Postscript.  Added 'Text Object'
-        analogous to Path Object to control entry and exit from text mode.
-        Much simpler clipping API.  All verified to export Postscript and
-        redistill.
-        One limitation still - clipping to text paths is fine in Acrobat
-        but not in Postscript (any level)
-        
-0.81,1999-10-13, AR:
-        Adding RoundRect; changed all format strings to use %0.2f instead of %s,
-        so we don't get exponentials in the output.
-0.8,1999-10-07, AR:  all changed!
+The Canvas object is the primary interface for creating PDF files. See
+doc/userguide.pdf for copious examples.
 """
-##  0.81    1999-10-13:
 
 
 import os
@@ -126,14 +101,14 @@
     def __init__(self,filename,
                  pagesize=(595.27,841.89),
                  bottomup = 1,
-                 pageCompression=0,
+                 pageCompression=1,
                  encoding=pdfdoc.DEFAULT_ENCODING,
                  verbosity=0):
         """Create a canvas of a given size. etc.
         Most of the attributes are private - we will use set/get methods
         as the preferred interface.  Default page size is A4."""
         self._filename = filename
-
+        self._encodingName = encoding
         self._doc = pdfdoc.PDFDocument(encoding)
 
         #this only controls whether it prints 'saved ...' - 0 disables
@@ -192,6 +167,8 @@
         self._fillColorRGB = (0,0,0)
         self._strokeColorRGB = (0,0,0)
 
+        self._registerStandardFonts()
+        
     def _make_preamble(self):
         if self.bottomup:
             #set initial font
@@ -841,11 +818,42 @@
   
     def getAvailableFonts(self):
         """Returns the list of PostScript font names available.
+        
         Standard set now, but may grow in future with font embedding."""
         fontnames = self._doc.getAvailableFonts()
         fontnames.sort()
         return fontnames
 
+    def registerFont0(self, fontObj):
+        "Register a new font for subsequent use."
+        self._doc.addFont0(fontObj)
+
+        # extend the new metrics
+        pdfmetrics.addFont(fontObj)
+        
+    def _registerStandardFonts(self):
+        """Ensures the standard 14 fonts are available in the system encoding.
+
+        Called by canvas on initialization"""
+        
+        from reportlab.pdfgen import fonts0
+        enc = fonts0.defaultEncoding
+        for fontName in pdfmetrics.standardEnglishFonts[0:12]:
+            fontObj = fonts0.BuiltInType1Font(fontName, fontName, enc)
+            self.registerFont0(fontObj)
+        for fontName in ['Symbol','ZapfDingbats']:
+            fontObj = fonts0.BuiltInType1Font(fontName, fontName, 'StandardEncoding')
+            self.registerFont0(fontObj)
+            
+                    
+            
+    def listLoadedFonts0(self):
+        "Convenience function to list all loaded fonts"
+        names = pdfmetrics.widths.keys()
+        names.sort()
+        return names
+    
+        
     def setFont(self, psfontname, size, leading = None):
         """Sets the font.  If leading not specified, defaults to 1.2 x
         font size. Raises a readable exception if an illegal font
@@ -861,7 +869,10 @@
 
     def stringWidth(self, text, fontName, fontSize, encoding=None):
         "gets width of a string in the given font and size"
-        if encoding is None: encoding = self._doc.encoding
+        if encoding is not None:
+            import logger
+            logger.warnOnce('encoding argument to Canvas.stringWidth is deprecated and has no effect!')
+        #if encoding is None: encoding = self._doc.encoding
         return pdfmetrics.stringWidth(text, fontName, fontSize)
         
     # basic graphics modes
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/reportlab/pdfgen/fonts0.py	Tue Mar 06 17:38:15 2001 +0000
@@ -0,0 +1,410 @@
+#copyright ReportLab Inc. 2001
+#see license.txt for license details
+#history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/pdfgen/fonts0.py?cvsroot=reportlab
+#$Header $
+__version__=''' $Id: fonts0.py,v 1.1 2001/03/06 17:38:15 andy_robinson Exp $ '''
+__doc__=""" 
+This is an attempt to break out fonts as user-accessible objects.  You can explicitly
+construct a font object with any desired encoding and add it to the document.  The
+font objects here are a base to build more complex fonts onto in future. For example
+the even more experimental jpsupport.py module adds CIDFonts, which have thousands
+of characters and multiple encodings.
+
+You construct fonts and register them with the canvas.  Every font knows its encoding.
+Encodings can either be objects, or just string names if you don't want to mess with
+them; the latter saves some time and file size.
+
+The simplest way to construct a font is like this:
+    >>> f1 = fonts0.BuiltInType1Font('myFont', 'Helvetica', 'WinAnsiEncoding')
+    >>> myCanvas.registerFont0(f1)
+
+The first argument is the name you will use later in stringWidth, setFont and so on.
+The second must be one of the 14 built-in font names.  The third must be
+'WinAnsiEncoding' or 'MacRomanEncoding'.
+
+This is not interesting; in fact the canvas auto-creates 14 fonts with the standard
+names when it starts up.  However, you can customize the encodings by using a
+SingleByteEncoding object instead of a string.  Here we construct a special
+encoding where every vowel is replaced with the letter 'z', and use it:
+
+    zenc = SingleByteEncoding('WinAnsiEncoding')
+    for ch in 'aeiou':
+        zenc[ord(ch)] = 'z'
+    for ch in 'AEIOU':
+        zenc[ord(ch)] = 'Z'
+    f = BuiltInType1Font('FontWithoutVowels', 'Helvetica-Oblique', zenc)
+    c.registerFont0(f)
+    
+    c.setFont('FontWithoutVowels', 12)
+    c.drawString(125, 675, "The magic word is squamish ossifrage")
+
+If you execute this script, you will see the results.
+Re-encoding has one or two uses even with the built-in fonts; you can make
+all-caps fonts.  We also found one more relevant use; MacRoman encoding lacks
+the Euro character, even though it is in all Adobe fonts. Adobe recommend
+re-encoding the font with the Euro at position 219.  Here we make a Mac
+font with a Euro:
+
+    euroMacEncoding = SingleByteEncoding('MacRomanEncoding')
+    euroMacEncoding[219] = 'Euro'
+    c.registerFont0(BuiltInType1Font('MacHelvWithEuro', 'Helvetica-Oblique', euroMacEncoding))
+    c.setFont('MacHelvWithEuro', 12)
+    c.drawString(125, 575, 'Hacked MacRoman with Euro: Character 219 = "\333"') # oct(219)=0333
+
+The ability to re-encode fonts is critical when we start embedding fonts,
+or referring to fonts in Adobe add-on language packs.
+
+
+
+
+In progress - see to-do list at bottom
+
+
+
+
+To Do:
+------
+(1) Make encoding vectors for ZapfDingbats and Symbol based on the AFM files.
+Add special-casing to extract their widths, and check test_pdfbase_pdfmetrics.py
+gets them all correct.
+
+(2) Discuss - can we delegate stringWidth to the fonts?  That's the right way
+to let CIDFonts or TrueType fonts do their own thing.  
+If the canvas does it, stringWdth come right out of pdfmetrics.  Add one call to
+use the C function. Otherwise, pdfmetrics should keep a font list and 
+
+(3) Get it working with _rl_accel
+
+
+"""
+
+import string
+import types
+from reportlab.pdfbase import pdfmetrics
+from reportlab.pdfbase import pdfdoc
+
+class Encoding:
+    """This is an abstract base class for encodings.  """
+
+    def __init__(self):
+        "Warning to deter them from creating these directly"
+        raise "Error", "Do not create Encoding objects - use a derived class such as SingleByteEncoding"
+
+    def getGlyphs(self):
+        "Return list of glyph names, in undefined order"
+        return []
+
+    def getDifferences(self, otherEnc):
+        """Return a compact list of the code points differing between two encodings
+        This is in the Adobe format: list of
+           [[b1, name1, name2, name3],
+           [b2, name4]]
+        where b1...bn is the starting code point, and the glyph names following
+        are assigned consecutive code points."""
+        return []
+    
+    def makePDFObject(self):
+        pass
+
+class SingleByteEncoding(Encoding):
+    """Represents a mapping of code points to character names.  Unassigned
+    code points are given the value 'None'"""
+    # in PDF, encodings are based on a list of differences
+    # over a standard encoding.
+    def __init__(self, vector):
+        errMsg = "Single-byte encodings may only be initialized with the strings 'MacRomanEncoding' or 'WinAnsiEncoding', or a 256-element list"
+        if type(vector) in (types.ListType, types.TupleType):
+            assert len(vector) == 256, 'Encoding vector must have 256 elements'
+            self.vector = vector[:]  # TAKE A COPY so they don't mess up pdfmetrics
+            self._encodingName = None
+            self._baseEncodingName = pdfdoc.DEFAULT_ENCODING
+        elif type(vector) is types.StringType:
+            try:
+                self.vector = pdfmetrics.encodings[vector][:]  # TAKE A COPY!
+                self._encodingName = vector
+                self._baseEncodingName = vector
+            except KeyError:
+                raise KeyError('Unknown font encoding "%s", allowed values are %s' % (vector, pdfmetrics.encodings.keys()))
+        else:
+            raise TypeError, errMsg
+
+    def __getitem__(self, index):
+        "Return glyph name for that code point, or None"
+        return self.vector[index]
+
+    def __setitem__(self, index, value):
+        self.vector[index] = value
+
+    def makePDFObject(self):
+        "Returns a PDF Object representing self"
+        #if self._encodingName:
+            # it's a predefined one, we only need a string
+            
+        D = {}
+        baseEnc = pdfmetrics.encodings[self._baseEncodingName]
+        differences = self.getDifferences(baseEnc) #[None] * 256)
+
+        # if no differences, we just need the base name
+        if differences == []:
+            return pdfdoc.PDFName(self._baseEncodingName)
+        else:
+            #make up a dictionary describing the new encoding
+            diffArray = []
+            for range in differences:
+                diffArray.append(range[0])  # numbers go 'as is'
+                for glyphName in range[1:]:
+                    if glyphName is not None:
+                        # there is no way to 'unset' a character in the base font.
+                        diffArray.append('/' + glyphName)
+                
+            #print 'diffArray = %s' % diffArray
+            D["Differences"] = pdfdoc.PDFArray(diffArray)
+            D["BaseEncoding"] = pdfdoc.PDFName(self._baseEncodingName)
+            D["Type"] = pdfdoc.PDFName("Encoding")
+            PD = pdfdoc.PDFDictionary(D)
+            return PD
+    
+    def getGlyphs(self):
+        "Return glyph names, in no particular order"
+        glyphs = []
+        for glyph in self.vector: # copy it
+            if glyph:
+                glyphs.append(glyph)
+        glyphs.sort()
+        return glyphs
+
+    def modifyRange(self, base, newNames):
+        """Set a group of character names starting at the code point 'base'."""
+        idx = base
+        for name in newNames:
+            self.vector[idx] = name
+            idx = idx + 1
+
+    def getDifferences(self, otherEnc):
+        """Return a compact list of the code points differing between two encodings
+
+        This is in the Adobe format: list of
+           [[b1, name1, name2, name3],
+           [b2, name4]]
+        where b1...bn is the starting code point, and the glyph names following
+        are assigned consecutive code points."""
+           
+        ranges = []
+        curRange = None
+        for i in range(256):
+            glyph = self[i]
+            if glyph == otherEnc[i]:
+                if curRange:
+                    ranges.append(curRange)
+                    curRange = []
+            else:
+                if curRange:
+                    curRange.append(glyph)
+                else:
+                    curRange = [i, glyph]
+        if curRange:
+            ranges.append(curRange)
+        return ranges
+                
+        
+WinAnsiEncoding = SingleByteEncoding('WinAnsiEncoding')
+MacRomanEncoding = SingleByteEncoding('MacRomanEncoding')
+defaultEncoding = SingleByteEncoding(pdfdoc.DEFAULT_ENCODING)
+
+        
+
+class Font:
+    """Base class for a font.  Not sure yet what it needs to do"""
+    def __init__(self):
+        self.ascent = None
+        self.descent = None
+        self.widths = []
+
+    def addObjects(self, doc):
+        """Adds PDF objects to the document as needed to represent self."""
+        pass
+
+    def stringWidth(self, text, size):
+        "Calculates width of text for given point size"
+        pass
+
+class BuiltInType1Font(Font):
+    """Defines a standard font with a new name, possibly with
+    a new encoding."""
+    def __init__(self, newName, baseFontName, encoding):
+        """The new name should be distinct from any other font
+        in the document.  baseFontName is one of the standard
+        14 fonts.  encoding is either a predefined string such
+        as 'WinAnsiEncoding' or 'MacRomanEncoding', or a valid
+        Encoding object."""
+        
+        Font.__init__(self)
+        assert baseFontName in pdfmetrics.standardEnglishFonts, "baseFontName must be one of the following: %s" % pdfmetrics.StandardEnglishFonts
+        self.name = newName
+        self.baseFontName = baseFontName
+        #assert isinstance(encoding, Encoding)
+        self.encoding = encoding
+        self._widths = None 
+
+        self._calcWidths()
+
+    def addObjects(self, doc):
+        """Makes and returns one or more PDF objects to be added
+        to the document.  The caller supplies the internal name
+        to be used (typically F1, F2... in sequence) """
+
+        # construct a Type 1 Font internal object
+        internalName = 'F' + repr(len(doc.fontMapping)+1)
+        pdfFont = pdfdoc.PDFType1Font()
+        pdfFont.Name = internalName
+        pdfFont.BaseFont = self.baseFontName
+        pdfFont.__Comment__ = 'Font %s' % self.name
+        if type(self.encoding) is types.StringType:
+            pdfFont.Encoding = pdfdoc.PDFName(self.encoding)
+        else:
+            enc = self.encoding.makePDFObject()
+            pdfFont.Encoding = enc
+            #objects.append(enc)
+
+        # now link it in
+        ref = doc.Reference(pdfFont, internalName)
+
+        # also refer to it in the BasicFonts dictionary
+        fontDict = doc.idToObject['BasicFonts'].dict
+        fontDict[internalName] = pdfFont
+
+        # and in the font mappings
+        doc.fontMapping[self.name] = '/' + internalName
+        
+    def _calcWidths(self):
+        "Computes widths array, if not done already"
+        # get the dictionary of glyph -> width
+        if self._widths:
+            return self._widths
+        else:
+            if self.baseFontName == 'Symbol':
+                self._widths = pdfmetrics.SymbolWidths[:]
+            elif self.baseFontName == 'ZapfDingbats':
+                self._widths = pdfmetrics.ZapfDingbatsWidths[:]
+            else:
+                widthVector = []
+                thisFontWidths = pdfmetrics.widthsByName[self.baseFontName]
+                if type(self.encoding) is types.StringType:
+                    vector = pdfmetrics.encodings[self.encoding]
+                else:
+                    vector = self.encoding
+                for glyphName in vector:
+                    try:
+                        glyphWidth = thisFontWidths[glyphName]
+                    except KeyError:
+                        glyphWidth = 0 # None?
+                    widthVector.append(glyphWidth)
+                self._widths = widthVector
+            return self._widths
+
+    
+    def getWidths(self):
+        "Returns width array for use in optimized pdfmetrics database"
+        return self._widths
+    
+    def stringWidth(self, text, size):
+        # weakness - assumes getWidths called.  do the latter on _init_
+        w = 0
+        for ch in text:
+            w = w + self._widths[ord(ch)]
+        return w * 0.001 * size
+    
+def checkWidths(fontName, encName):
+    if encName == 'WinAnsiEncoding':
+        enc = WinAnsi
+        names = pdfmetrics.WinAnsiNames
+    elif encName == 'MacRomanEncoding':
+        enc = MacRoman
+        names = pdfmetrics.MacRomanNames
+    f = BuiltInType1Font('NewFont',fontName, enc)
+    
+    new_w = f.getWidths()
+    lowerFontName = string.lower(fontName)
+    old_w = pdfmetrics.widths['WinAnsiEncoding'][lowerFontName]
+
+    if new_w == old_w:
+        print 'Font %s compares same' % fontName
+    else:
+        print 'Font %s differs as follows:' % fontName
+        for i in range(256):
+            if new_w[i] <> old_w[i]:
+                print '    %d (%s): old = %s, new = %s' % (i, names[i], old_w[i], new_w[i])
+        
+        
+if __name__=='__main__':
+    # make a custom encoded font.
+    import reportlab.pdfgen.canvas
+    c = reportlab.pdfgen.canvas.Canvas('testfonts.pdf')
+    c.setPageCompression(0)
+    c.setFont('Helvetica', 12)
+    c.drawString(100, 700, 'The text below should be in a custom encoding in which all vowels become "z"')
+
+    # invent a new language where vowels are replaced with letter 'z'
+    zenc = SingleByteEncoding('WinAnsiEncoding')
+    for ch in 'aeiou':
+        zenc[ord(ch)] = 'z'
+    for ch in 'AEIOU':
+        zenc[ord(ch)] = 'Z'
+    f = BuiltInType1Font('FontWithoutVowels', 'Helvetica-Oblique', zenc)
+    c.registerFont0(f)
+    
+    c.setFont('FontWithoutVowels', 12)
+    c.drawString(125, 675, "The magic word is squamish ossifrage")
+
+    # now demonstrate adding a Euro to MacRoman, which lacks one
+    c.setFont('Helvetica', 12)
+    c.drawString(100, 650, "MacRoman encoding lacks a Euro.  We'll make a Mac font with the Euro at #219:")
+
+    # WinAnsi Helvetica
+    c.registerFont0(BuiltInType1Font('Helvetica-WinAnsi', 'Helvetica-Oblique', WinAnsiEncoding))
+    c.setFont('Helvetica-WinAnsi', 12)
+    c.drawString(125, 625, 'WinAnsi with Euro: character 128 = "\200"') 
+
+    c.registerFont0(BuiltInType1Font('MacHelvNoEuro', 'Helvetica-Oblique', MacRomanEncoding))
+    c.setFont('MacHelvNoEuro', 12)
+    c.drawString(125, 600, 'Standard MacRoman, no Euro: Character 219 = "\333"') # oct(219)=0333
+
+    # now make our hacked encoding    
+    euroMac = SingleByteEncoding('MacRomanEncoding')
+    euroMac[219] = 'Euro'
+    c.registerFont0(BuiltInType1Font('MacHelvWithEuro', 'Helvetica-Oblique', euroMac))
+    c.setFont('MacHelvWithEuro', 12)
+    c.drawString(125, 575, 'Hacked MacRoman with Euro: Character 219 = "\333"') # oct(219)=0333
+
+    # now test width setting with and without _rl_accel - harder
+    # make an encoding where 'm' becomes 'i'
+    c.setFont('Helvetica', 12)
+    c.drawString(100, 500, "Recode 'm' to 'i' and check we can measure widths.  Boxes should surround letters.")
+    sample = 'Mmmmm. ' * 6 + 'Mmmm'
+
+    c.setFont('Helvetica-Oblique',12)
+    c.drawString(125, 475, sample)
+    w = c.stringWidth(sample, 'Helvetica-Oblique', 12)
+    c.rect(125, 475, w, 12)
+
+    narrowEnc = SingleByteEncoding('WinAnsiEncoding')
+    narrowEnc[ord('m')] = 'i'
+    narrowEnc[ord('M')] = 'I'
+    c.registerFont0(BuiltInType1Font('narrow', 'Helvetica-Oblique', narrowEnc))
+    c.setFont('narrow', 12)
+    c.drawString(125, 450, sample)
+    w = c.stringWidth(sample, 'narrow', 12)
+    c.rect(125, 450, w, 12)
+
+    c.setFont('Helvetica', 12)
+    c.drawString(100, 400, "Symbol & Dingbats fonts - check we still get valid PDF in StandardEncoding")
+    c.setFont('Symbol', 12)
+    c.drawString(100, 375, 'abcdefghijklmn')    
+    c.setFont('ZapfDingbats', 12)
+    c.drawString(300, 375, 'abcdefghijklmn')    
+    
+    c.save()
+
+        
+    print 'saved testfonts.pdf'
+    
\ No newline at end of file
--- a/reportlab/platypus/doctemplate.py	Fri Mar 02 15:35:43 2001 +0000
+++ b/reportlab/platypus/doctemplate.py	Tue Mar 06 17:38:15 2001 +0000
@@ -1,9 +1,9 @@
 #copyright ReportLab Inc. 2000
 #see license.txt for license details
 #history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/platypus/doctemplate.py?cvsroot=reportlab
-#$Header: /tmp/reportlab/reportlab/platypus/doctemplate.py,v 1.35 2001/02/08 21:44:05 dinu_gherman Exp $
+#$Header: /tmp/reportlab/reportlab/platypus/doctemplate.py,v 1.36 2001/03/06 17:38:15 andy_robinson Exp $
 
-__version__=''' $Id: doctemplate.py,v 1.35 2001/02/08 21:44:05 dinu_gherman Exp $ '''
+__version__=''' $Id: doctemplate.py,v 1.36 2001/03/06 17:38:15 andy_robinson Exp $ '''
 
 __doc__="""
 This module contains the core structure of platypus.
@@ -514,7 +514,7 @@
 		passes = 0
 		while 1:
 			passes = passes + 1
-			## print 'building pass '+str(passes) + '...',
+			print 'building pass '+str(passes) + '...',
 
 			for fl in self._indexingFlowables:
 				fl.beforeBuild()
@@ -544,7 +544,7 @@
 			if passes > maxPasses:
 				raise IndexError, "Index entries not resolved after %d passes" % maxPasses
 		
-		## print 'saved', filename
+		print 'saved'
 
 	#these are pure virtuals override in derived classes
 	#NB these get called at suitable places by the base class
--- a/reportlab/platypus/paragraph.py	Fri Mar 02 15:35:43 2001 +0000
+++ b/reportlab/platypus/paragraph.py	Tue Mar 06 17:38:15 2001 +0000
@@ -1,8 +1,8 @@
 #copyright ReportLab Inc. 2000
 #see license.txt for license details
 #history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/platypus/paragraph.py?cvsroot=reportlab
-#$Header: /tmp/reportlab/reportlab/platypus/paragraph.py,v 1.49 2000/12/18 09:24:15 rgbecker Exp $
-__version__=''' $Id: paragraph.py,v 1.49 2000/12/18 09:24:15 rgbecker Exp $ '''
+#$Header: /tmp/reportlab/reportlab/platypus/paragraph.py,v 1.50 2001/03/06 17:38:15 andy_robinson Exp $
+__version__=''' $Id: paragraph.py,v 1.50 2001/03/06 17:38:15 andy_robinson Exp $ '''
 from string import split, strip, join, whitespace
 from operator import truth
 from types import StringType, ListType
@@ -791,11 +791,11 @@
 <onDraw name=myIndex label="Eingabeaufforderung :: (&gt;&gt;&gt;)">
 <b><font color=red>&gt;&gt;&gt; (Eingabeaufforderung)</font></b>
 <onDraw name=myIndex label="&gt;&gt;&gt; (Eingabeaufforderung)">
-Einführung in Python <b><font color=red>Python :: Einführung</font></b>
-<onDraw name=myIndex label="Python :: Einführung">.
+Einf\374hrung in Python <b><font color=red>Python :: Einf\374hrung</font></b>
+<onDraw name=myIndex label="Python :: Einf\374hrung">.
 Das Ziel ist, die grundlegenden Eigenschaften von Python darzustellen, ohne
 sich zu sehr in speziellen Regeln oder Details zu verstricken. Dazu behandelt
-dieses Kapitel kurz die wesentlichen Konzepte wie Variablen, Ausdrücke,
+dieses Kapitel kurz die wesentlichen Konzepte wie Variablen, Ausdr\374cke,
 Kontrollfluss, Funktionen sowie Ein- und Ausgabe. Es erhebt nicht den Anspruch,
 umfassend zu sein."""
 		P=Paragraph(text, styleSheet['Code'])
@@ -804,7 +804,7 @@
 		dumpParagraphLines(P)
 
 	if '4' in TESTS:
-		text='''Die eingebaute Funktion <font name=Courier>range(i, j [, stride])</font><onDraw name=myIndex label="eingebaute Funktionen::range()"><onDraw name=myIndex label="range() (Funktion)"><onDraw name=myIndex label="Funktionen::range()"> erzeugt eine Liste von Ganzzahlen und füllt sie mit Werten <font name=Courier>k</font>, für die gilt: <font name=Courier>i &lt;= k &lt; j</font>. Man kann auch eine optionale Schrittweite angeben. Die eingebaute Funktion <font name=Courier>xrange()</font><onDraw name=myIndex label="eingebaute Funktionen::xrange()"><onDraw name=myIndex label="xrange() (Funktion)"><onDraw name=myIndex label="Funktionen::xrange()"> erfüllt einen ähnlichen Zweck, gibt aber eine unveränderliche Sequenz vom Typ <font name=Courier>XRangeType</font><onDraw name=myIndex label="XRangeType"> zurück. Anstatt alle Werte in der Liste abzuspeichern, berechnet diese Liste ihre Werte, wann immer sie angefordert werden. Das ist sehr viel speicherschonender, wenn mit sehr langen Listen von Ganzzahlen gearbeitet wird. <font name=Courier>XRangeType</font> kennt eine einzige Methode, <font name=Courier>s.tolist()</font><onDraw name=myIndex label="XRangeType::tolist() (Methode)"><onDraw name=myIndex label="s.tolist() (Methode)"><onDraw name=myIndex label="Methoden::s.tolist()">, die seine Werte in eine Liste umwandelt.'''
+		text='''Die eingebaute Funktion <font name=Courier>range(i, j [, stride])</font><onDraw name=myIndex label="eingebaute Funktionen::range()"><onDraw name=myIndex label="range() (Funktion)"><onDraw name=myIndex label="Funktionen::range()"> erzeugt eine Liste von Ganzzahlen und f\374llt sie mit Werten <font name=Courier>k</font>, f\374r die gilt: <font name=Courier>i &lt;= k &lt; j</font>. Man kann auch eine optionale Schrittweite angeben. Die eingebaute Funktion <font name=Courier>xrange()</font><onDraw name=myIndex label="eingebaute Funktionen::xrange()"><onDraw name=myIndex label="xrange() (Funktion)"><onDraw name=myIndex label="Funktionen::xrange()"> erf\374llt einen \344hnlichen Zweck, gibt aber eine unver\344nderliche Sequenz vom Typ <font name=Courier>XRangeType</font><onDraw name=myIndex label="XRangeType"> zur\374ck. Anstatt alle Werte in der Liste abzuspeichern, berechnet diese Liste ihre Werte, wann immer sie angefordert werden. Das ist sehr viel speicherschonender, wenn mit sehr langen Listen von Ganzzahlen gearbeitet wird. <font name=Courier>XRangeType</font> kennt eine einzige Methode, <font name=Courier>s.tolist()</font><onDraw name=myIndex label="XRangeType::tolist() (Methode)"><onDraw name=myIndex label="s.tolist() (Methode)"><onDraw name=myIndex label="Methoden::s.tolist()">, die seine Werte in eine Liste umwandelt.'''
 		aW = 420
 		aH = 64.4
 		P=Paragraph(text, B)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/reportlab/test/test_pdfbase_pdfmetrics.py	Tue Mar 06 17:38:15 2001 +0000
@@ -0,0 +1,134 @@
+#test_pdfbase_pdfmetrics_widths
+"""
+Various tests for PDF metrics.
+
+The main test prints out a PDF documents enabling checking of widths of every
+glyph in every standard font.  Long!
+"""
+from reportlab.test import unittest
+
+from reportlab.pdfbase import pdfmetrics
+from reportlab.pdfgen.canvas import Canvas
+from reportlab.lib import colors
+
+verbose = 0
+fontNamesToTest = pdfmetrics.standardEnglishFonts #[0:12]  #leaves out Symbol and Dingbats for now
+
+def decoratePage(c, header):
+    c.setFont('Helvetica-Oblique',10)
+    c.drawString(72, 800, header)
+    c.drawCentredString(297, 54, 'Page %d' % c.getPageNumber())
+
+def makeWidthTestForAllGlyphs(canv, fontName):
+    """New page, then runs down doing all the glyphs in one encoding"""
+    canv.setFont('Helvetica-Bold', 20)
+    title = 'Glyph Width Test for font %s' % fontName
+    canv.drawString(80, 750,  title)
+    canv.setFont('Helvetica-Oblique',10)
+    canv.drawCentredString(297, 54, 'Page %d' % canv.getPageNumber())
+
+    # put it in the outline
+    canv.bookmarkPage('GlyphWidths:' + fontName)
+    canv.addOutlineEntry(fontName,'GlyphWidths:' + fontName, level=1)
+
+    y = 720
+    thisFontWidths = pdfmetrics.widthsByName[fontName]
+    # ZapfDingbats and Symbol don't have names (at least, they are not
+    # useful) so we just print them.
+    if fontName in ['Symbol','ZapfDingbats']:
+        for i in range(32, 256):
+            if y < 72:
+                canv.showPage()
+                decoratePage(canv, title)
+                y = 750
+            canv.setFont('Helvetica', 10)
+            canv.drawString(80, y, '%03d      ' % i)
+            canv.setFont(fontName, 10)
+            canv.drawString(200, y, chr(i) * 30)
+            # now work out width and put a red marker next to the end.
+            try:
+                w = canv.stringWidth(chr(i) * 30, fontName, 10)
+            except KeyError:
+                w = 0
+            canv.setFillColor(colors.red)
+            canv.rect(200 + w, y-1, 5, 10, stroke=0, fill=1)
+            canv.setFillColor(colors.black)
+            y = y - 12
+
+    else:            
+        # ordinary font with standard character names    
+        glyphNames = pdfmetrics.encodings['WinAnsiEncoding']
+        for i in range(256):
+            if y < 72:
+                canv.showPage()
+                decoratePage(canv, title)
+                y = 750
+            glyphName = glyphNames[i]
+            if glyphName is not None:
+                canv.setFont('Helvetica', 10)
+                canv.drawString(80, y, '%03d   %s ' % (i, glyphName))
+                try:
+                    glyphWidth = thisFontWidths[glyphName]
+                    canv.setFont(fontName, 10)
+                    canv.drawString(200, y, chr(i) * 30)
+
+                    # now work out width and put a red marker next to the end.
+                    w = canv.stringWidth(chr(i) * 30, fontName, 10)
+                    canv.setFillColor(colors.red)
+                    canv.rect(200 + w, y-1, 5, 10, stroke=0, fill=1)
+                    canv.setFillColor(colors.black)
+                except KeyError:
+                    canv.drawString(200, y, 'Could not find glyph named "%s"' % glyphName)
+                y = y - 12
+                
+
+
+def makeTestDoc(fontNames):
+    filename = 'test_pdfbase_pdfmetrics.pdf'
+    c = Canvas(filename)
+    c.bookmarkPage('Glyph Width Tests')
+    c.showOutline()
+    c.addOutlineEntry('Glyph Width Tests', 'Glyph Width Tests', level=0)
+    if verbose:
+        print   # get it on a different line to the unittest log output.
+    for fontName in fontNames:
+        if verbose:
+            print 'width test for', fontName
+    
+        makeWidthTestForAllGlyphs(c, fontName)
+        c.showPage()
+    c.save()
+    if verbose:
+        if verbose:
+            print 'saved',filename
+
+class PDFMetricsTestCase(unittest.TestCase):
+    "Test various encodings used in PDF files."
+    def testGlyphWidthsAreCorrect(self):
+        "Visual test for glyph widths"
+        makeTestDoc(fontNamesToTest)        
+
+def makeSuite():
+    return unittest.makeSuite(PDFMetricsTestCase,'test')
+    
+
+if __name__=='__main__':
+    usage = """Usage:
+    (1) test_pdfbase_pdfmetrics.py     -  makes doc for all standard fonts
+    (2) test_pdfbase_pdfmetrics.py fontname - " " for just one font."""
+    import sys
+    verbose = 1
+    global fontNamesToTest
+    # accept font names as arguments; otherwise it does the lot
+    if len(sys.argv) > 1:
+        for arg in sys.argv[1:]:
+            if not arg in fontNamesToTest:
+                print 'unknown font %s' % arg
+                print usage
+                sys.exit(0)
+                
+        fontNamesToTest = sys.argv[1:]
+
+    runner = unittest.TextTestRunner()
+    runner.run(makeSuite())
+    
\ No newline at end of file