Revision: 3758
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3758&view=rev
Author:   mdboom
Date:     2007-08-30 08:12:27 -0700 (Thu, 30 Aug 2007)

Log Message:
-----------
Deal with Unicode and non-ASCII characters correctly when outputting
Postscript with ps.useafm == True.

Modified Paths:
--------------
    trunk/matplotlib/lib/matplotlib/afm.py
    trunk/matplotlib/lib/matplotlib/backends/backend_ps.py

Modified: trunk/matplotlib/lib/matplotlib/afm.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/afm.py      2007-08-30 15:11:23 UTC (rev 
3757)
+++ trunk/matplotlib/lib/matplotlib/afm.py      2007-08-30 15:12:27 UTC (rev 
3758)
@@ -34,8 +34,8 @@
   John D. Hunter <[EMAIL PROTECTED]>
 """
 
-
 import sys, os
+from _mathtext_data import uni2type1
 
 #Convert string the a python type
 _to_int = int
@@ -152,12 +152,13 @@
     all the sample afm files I have
     """
 
-    d = {}
+    ascii_d = {}
+    name_d  = {}
     while 1:
         line = fh.readline()
         if not line: break
         line = line.rstrip()
-        if line.startswith('EndCharMetrics'): return d
+        if line.startswith('EndCharMetrics'): return ascii_d, name_d
         vals = line.split(';')[:4]
         if len(vals) !=4 : raise RuntimeError('Bad char metrics line: %s' % 
line)
         num = _to_int(vals[0].split()[1])
@@ -169,7 +170,8 @@
         if name == 'Euro':
             num = 128
         if num != -1:
-            d[num] = (wx, name, bbox)
+            ascii_d[num] = (wx, name, bbox)
+        name_d[name] = (wx, bbox)
     raise RuntimeError('Bad parse')
 
 def _parse_kern_pairs(fh):
@@ -277,9 +279,9 @@
     """
     _sanity_check(fh)
     dhead =  _parse_header(fh)
-    dcmetrics =  _parse_char_metrics(fh)
+    dcmetrics_ascii, dcmetrics_name = _parse_char_metrics(fh)
     doptional = _parse_optional(fh)
-    return dhead, dcmetrics, doptional[0], doptional[1]
+    return dhead, dcmetrics_ascii, dcmetrics_name, doptional[0], doptional[1]
 
 
 class AFM:
@@ -288,10 +290,12 @@
         """
         Parse the AFM file in file object fh
         """
-        (dhead, dcmetrics, dkernpairs, dcomposite) = parse_afm(fh)
+        (dhead, dcmetrics_ascii, dcmetrics_name, dkernpairs, dcomposite) = \
+            parse_afm(fh)
         self._header = dhead
         self._kern = dkernpairs
-        self._metrics = dcmetrics
+        self._metrics = dcmetrics_ascii
+        self._metrics_by_name = dcmetrics_name
         self._composite = dcomposite
 
 
@@ -340,9 +344,16 @@
         miny = 1e9
         maxy = 0
         left = 0
+        if not isinstance(s, unicode):
+            s = s.decode()
         for c in s:
             if c == '\n': continue
-            wx, name, bbox = self._metrics[ord(c)]
+            name = uni2type1.get(ord(c), 'question')
+            try:
+                wx, bbox = self._metrics_by_name[name]
+            except KeyError:
+                name = 'question'
+                wx, bbox = self._metrics_by_name[name]
             l,b,w,h = bbox
             if l<left: left = l
             # find the width with kerning
@@ -377,6 +388,13 @@
         wx, name, bbox = self._metrics[c]
         return wx
 
+    def get_width_from_char_name(self, name):
+        """
+        Get the width of the character from a type1 character name
+        """
+        wx, bbox = self._metrics_by_name[name]
+        return wx
+        
     def get_height_char(self, c, isord=False):
         """
         Get the height of character c from the bounding box.  This is
@@ -392,9 +410,16 @@
         c2
         """
         name1, name2 = self.get_name_char(c1), self.get_name_char(c2)
+        return self.get_kern_dist_from_name(name1, name2)
+
+    def get_kern_dist_from_name(self, name1, name2):
+        """
+        Return the kerning pair distance (possibly 0) for chars c1 and
+        c2
+        """
         try: return self._kern[ (name1, name2) ]
         except: return 0
-
+        
     def get_fontname(self):
         "Return the font name, eg, Times-Roman"
         return self._header['FontName']

Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py      2007-08-30 
15:11:23 UTC (rev 3757)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py      2007-08-30 
15:12:27 UTC (rev 3758)
@@ -22,6 +22,7 @@
 from matplotlib.ft2font import FT2Font, KERNING_DEFAULT, LOAD_NO_HINTING
 from matplotlib.ttconv import convert_ttf_to_ps
 from matplotlib.mathtext import MathTextParser
+from matplotlib._mathtext_data import uni2type1
 from matplotlib.text import Text
 
 from matplotlib.transforms import get_vec6_scales
@@ -700,8 +701,10 @@
         elif ismath:
             return self.draw_mathtext(gc, x, y, s, prop, angle)
 
+        elif isinstance(s, unicode):
+            return self.draw_unicode(gc, x, y, s, prop, angle)
+        
         elif rcParams['ps.useafm']:
-            if ismath: s = s[1:-1]
             font = self._get_font_afm(prop)
 
             l,b,w,h = font.get_str_bbox(s)
@@ -735,8 +738,6 @@
     """ % locals()
             self._draw_ps(ps, gc, None)
 
-        elif isinstance(s, unicode):
-            return self.draw_unicode(gc, x, y, s, prop, angle)
         else:
             font = self._get_font_ttf(prop)
             font.set_text(s, 0, flags=LOAD_NO_HINTING)
@@ -762,50 +763,92 @@
         """draw a unicode string.  ps doesn't have unicode support, so
         we have to do this the hard way
         """
+        if rcParams['ps.useafm']:
+            self.set_color(*gc.get_rgb())
 
-        font = self._get_font_ttf(prop)
+            font = self._get_font_afm(prop)
+            fontname = font.get_fontname()
+            fontsize = prop.get_size_in_points()
+            scale = 0.001*fontsize
 
-        self.set_color(*gc.get_rgb())
-        self.set_font(font.get_sfnt()[(1,0,0,6)], prop.get_size_in_points())
-        self.track_characters(font, s)
+            thisx, thisy = 0, 0
+            last_name = None
+            lines = []
+            for c in s:
+                name = uni2type1.get(ord(c), 'question')
+                try:
+                    width = font.get_width_from_char_name(name)
+                except KeyError:
+                    name = 'question'
+                    width = font.get_width_char('?')
+                if last_name is not None:
+                    kern = font.get_kern_dist_from_name(last_name, name)
+                else:
+                    kern = 0
+                last_name = name
+                thisx += kern * scale
+                
+                lines.append('%f %f m /%s glyphshow'%(thisx, thisy, name))
 
-        cmap = font.get_charmap()
-        lastgind = None
-        #print 'text', s
-        lines = []
-        thisx, thisy = 0,0
-        for c in s:
-            ccode = ord(c)
-            gind = cmap.get(ccode)
-            if gind is None:
-                ccode = ord('?')
-                name = '.notdef'
-                gind = 0
-            else:
-                name = font.get_glyph_name(gind)
-            glyph = font.load_char(ccode, flags=LOAD_NO_HINTING)
+                thisx += width * scale
 
-            if lastgind is not None:
-                kern = font.get_kerning(lastgind, gind, KERNING_DEFAULT)
-            else:
-                kern = 0
-            lastgind = gind
-            thisx += kern/64.0
-
-            lines.append('%f %f m /%s glyphshow'%(thisx, thisy, name))
-            thisx += glyph.linearHoriAdvance/65536.0
-
-
-        thetext = '\n'.join(lines)
-        ps = """gsave
+            thetext = "\n".join(lines)
+            ps = """\
+gsave
+/%(fontname)s findfont
+%(fontsize)s scalefont
+setfont
 %(x)f %(y)f translate
 %(angle)f rotate
 %(thetext)s
 grestore
-""" % locals()
-        self._pswriter.write(ps)
+    """ % locals()
+            self._pswriter.write(ps)
+            
+        else:
+            font = self._get_font_ttf(prop)
 
+            self.set_color(*gc.get_rgb())
+            self.set_font(font.get_sfnt()[(1,0,0,6)], 
prop.get_size_in_points())
+            self.track_characters(font, s)
 
+            cmap = font.get_charmap()
+            lastgind = None
+            #print 'text', s
+            lines = []
+            thisx, thisy = 0,0
+            for c in s:
+                ccode = ord(c)
+                gind = cmap.get(ccode)
+                if gind is None:
+                    ccode = ord('?')
+                    name = '.notdef'
+                    gind = 0
+                else:
+                    name = font.get_glyph_name(gind)
+                glyph = font.load_char(ccode, flags=LOAD_NO_HINTING)
+
+                if lastgind is not None:
+                    kern = font.get_kerning(lastgind, gind, KERNING_DEFAULT)
+                else:
+                    kern = 0
+                lastgind = gind
+                thisx += kern/64.0
+
+                lines.append('%f %f m /%s glyphshow'%(thisx, thisy, name))
+                thisx += glyph.linearHoriAdvance/65536.0
+
+
+            thetext = '\n'.join(lines)
+            ps = """gsave
+    %(x)f %(y)f translate
+    %(angle)f rotate
+    %(thetext)s
+    grestore
+    """ % locals()
+            self._pswriter.write(ps)
+
+
     def draw_mathtext(self, gc,
         x, y, s, prop, angle):
         """


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to