Revision: 3677
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3677&view=rev
Author:   mdboom
Date:     2007-08-06 13:53:11 -0700 (Mon, 06 Aug 2007)

Log Message:
-----------
Expose Unicode font functionality for mathtext through rcParams

Modified Paths:
--------------
    trunk/matplotlib/lib/matplotlib/_mathtext_data.py
    trunk/matplotlib/lib/matplotlib/mathtext.py
    trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc
    trunk/matplotlib/lib/matplotlib/rcsetup.py
    trunk/matplotlib/matplotlibrc.template

Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/_mathtext_data.py   2007-08-06 18:52:07 UTC 
(rev 3676)
+++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py   2007-08-06 20:53:11 UTC 
(rev 3677)
@@ -2211,7 +2211,7 @@
 '$': 36,
 '{': 123,
 '}': 125,
-'imath': 0xfd,          
+'imath': 0x131,          
 'circumflexaccent'         : 770,
 'combiningbreve'           : 774,
 'combiningoverline'        : 772,

Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-08-06 18:52:07 UTC (rev 
3676)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-08-06 20:53:11 UTC (rev 
3677)
@@ -133,7 +133,7 @@
 from cStringIO import StringIO
 from math import floor, ceil
 from sets import Set
-from unicodedata import category
+import unicodedata
 from warnings import warn
 
 from numpy import inf, isinf
@@ -462,7 +462,7 @@
 
         cached_font = self.fonts.get(basename)
         if cached_font is None:
-            font = FT2Font(os.path.join(self.basepath, basename + ".ttf"))
+            font = FT2Font(basename)
             cached_font = self.CachedFont(font)
             self.fonts[basename] = cached_font
             self.fonts[font.postscript_name] = cached_font
@@ -545,15 +545,24 @@
     """
     Use the Bakoma true type fonts for rendering
     """
-    fontmap = { 'cal' : 'cmsy10',
-                'rm'  : 'cmr10',
-                'tt'  : 'cmtt10',
-                'it'  : 'cmmi10',
-                'bf'  : 'cmb10',
-                'sf'  : 'cmss10',
-                'ex'  : 'cmex10'
-                }
-        
+    _fontmap = { 'cal' : 'cmsy10',
+                 'rm'  : 'cmr10',
+                 'tt'  : 'cmtt10',
+                 'it'  : 'cmmi10',
+                 'bf'  : 'cmb10',
+                 'sf'  : 'cmss10',
+                 'ex'  : 'cmex10'
+                 }
+    fontmap = {}
+    
+    def __init__(self, *args, **kwargs):
+        TruetypeFonts.__init__(self, *args, **kwargs)
+        if not len(self.fontmap):
+            for key, val in self._fontmap.items():
+                fullpath = os.path.join(self.basepath, val + ".ttf")
+                self.fontmap[key] = fullpath
+                self.fontmap[val] = fullpath
+    
     def _get_offset(self, cached_font, glyph, fontsize, dpi):
         if cached_font.font.postscript_name == 'Cmex10':
             return glyph.height/64.0/2.0 + 256.0/64.0 * dpi/72.0
@@ -564,7 +573,7 @@
     def _get_glyph(self, fontname, sym, fontsize):
         if fontname in self.fontmap and latex_to_bakoma.has_key(sym):
             basename, num = latex_to_bakoma[sym]
-            slanted = basename == "cmmi10" or sym in self._slanted_symbols
+            slanted = (basename == "cmmi10") or sym in self._slanted_symbols
             cached_font = self._get_font(basename)
             symbol_name = cached_font.font.get_glyph_name(num)
             num = cached_font.glyphmap[num]
@@ -638,15 +647,24 @@
 class UnicodeFonts(TruetypeFonts):
     """An abstract base class for handling Unicode fonts.
     """
-    fontmap = { 'cal' : 'cmsy10',
-                'rm'  : 'DejaVuSerif',
-                'tt'  : 'DejaVuSansMono',
-                'it'  : 'DejaVuSerif-Italic',
-                'bf'  : 'DejaVuSerif-Bold',
-                'sf'  : 'DejaVuSans',
-                None  : 'DejaVuSerif-Italic'
-                }
 
+    fontmap = {}
+    
+    def __init__(self, *args, **kwargs):
+        # This must come first so the backend's owner is set correctly
+        if rcParams['mathtext.fallback_to_cm']:
+            self.cm_fallback = BakomaFonts(*args, **kwargs)
+        else:
+            self.cm_fallback = None
+        TruetypeFonts.__init__(self, *args, **kwargs)
+        if not len(self.fontmap):
+            for texfont in "cal rm tt it bf sf".split():
+                setting = rcParams['mathtext.' + texfont]
+                family, weight, style = setting
+                prop = FontProperties(family=family, weight=weight, 
style=style)
+                font = fontManager.findfont(prop)
+                self.fontmap[texfont] = font
+    
     def _get_offset(self, cached_font, glyph, fontsize, dpi):
         return 0.
 
@@ -662,34 +680,66 @@
                 uniindex = get_unicode_index(sym[4:])
                 fontsize *= GROW_FACTOR
             else:
-                warn("No TeX to unicode mapping for '%s'" % sym,
+                uniindex = ord('?')
+                warn("No TeX to unicode mapping for '%s'" % 
sym.encode('ascii', 'replace'),
                      MathTextWarning)
 
         # Only characters in the "Letter" class should be italicized in 'it'
-        # mode.  This class includes greek letters, of course.
-        if (fontname == 'it'
-            and not category(unichr(uniindex)).startswith("L")):
-            fontname = 'rm'
+        # mode.  Greek capital letters should be Roman.
+        if found_symbol:
+            new_fontname = fontname
 
-        slanted = (fontname == 'it')
-            
-        cached_font = self._get_font(fontname)
-        if found_symbol:
+            if fontname == 'it':
+                unistring = unichr(uniindex)
+                if (not unicodedata.category(unistring).startswith("L")
+                    or unicodedata.name(unistring).startswith("GREEK 
CAPITAL")):
+                    new_fontname = 'rm'
+
+            slanted = (new_fontname == 'it')
+            cached_font = self._get_font(new_fontname)
             try:
                 glyphindex = cached_font.charmap[uniindex]
             except KeyError:
                 warn("Font '%s' does not have a glyph for '%s'" %
-                     (cached_font.font.postscript_name, sym),
+                     (cached_font.font.postscript_name, sym.encode('ascii', 
'replace')),
                      MathTextWarning)
                 found_symbol = False
 
         if not found_symbol:
-            uniindex = 0xA4 # currency character, for lack of anything better
-            glyphindex = cached_font.charmap[uniindex]
+            if self.cm_fallback:
+                warn("Substituting with a symbol from the Computer Modern 
family.",
+                     MathTextWarning)
+                return self.cm_fallback._get_glyph(fontname, sym, fontsize)
+            else:
+                new_fontname = fontname
+                cached_font = self._get_font(fontname)
+                uniindex = 0xA4 # currency character, for lack of anything 
better
+                glyphindex = cached_font.charmap[uniindex]
+                slanted = False
             
         symbol_name = cached_font.font.get_glyph_name(glyphindex)
         return cached_font, uniindex, symbol_name, fontsize, slanted
+
+    def set_canvas_size(self, w, h):
+        'Dimension the drawing canvas; may be a noop'
+        TruetypeFonts.set_canvas_size(self, w, h)
+        if self.cm_fallback:
+            self.cm_fallback.set_canvas_size(w, h)
     
+    def get_used_characters(self):
+        used_characters = dict(self.used_characters)
+        if self.cm_fallback:
+            fallback_characters = self.cm_fallback.get_used_characters()
+            for key, val in fallback_characters:
+                used_characters.setdefault(key, Set()).update(val)
+        return used_characters
+
+    def get_fonts(self):
+        fonts = [x.font for x in self.fonts.values()]
+        if self.cm_fallback:
+            fonts.extend(self.cm_fallback.get_fonts())
+        return list(set(fonts))
+    
 class StandardPsFonts(Fonts):
     """
     Use the standard postscript fonts for rendering to backend_ps
@@ -750,7 +800,7 @@
         # This class includes greek letters, so we're ok
         if (fontname == 'it' and
             (len(sym) > 1 or
-             not category(unicode(sym)).startswith("L"))):
+             not unicodedata.category(unicode(sym)).startswith("L"))):
             fontname = 'rm'
 
         found_symbol = False
@@ -2302,10 +2352,10 @@
             font_output = StandardPsFonts(prop)
         else:
             backend = self._backend_mapping[self.output]()
-            font_output = BakomaFonts(prop, backend)
-            # When we have a decent Unicode font, we should test and
-            # then make this available as an option
-            #~ font_output = UnicodeFonts(prop, backend)
+            if rcParams['mathtext.use_cm']:
+                font_output = BakomaFonts(prop, backend)
+            else:
+                font_output = UnicodeFonts(prop, backend)
 
         fontsize = prop.get_size_in_points()
         if self._parser is None:

Modified: trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc
===================================================================
--- trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc       2007-08-06 
18:52:07 UTC (rev 3676)
+++ trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc       2007-08-06 
20:53:11 UTC (rev 3677)
@@ -159,6 +159,22 @@
                                # In that case, all text will be sent to TeX 
for 
                                # processing.
 
+# The following settings allow you to select the fonts in math mode.
+# They map from a TeX font name to a 3-tuple of the form:
+#    (family, weight, style)
+# These settings are only used if mathtext.use_cm is False, otherwise, the
+# Bakoma TeX Computer Modern fonts are used.
+#mathtext.cal : (['cursive'], 'normal', 'normal')
+#mathtext.rm  : (['serif'], 'normal', 'normal')
+#mathtext.tt  : (['monospace'], 'normal', 'normal')
+#mathtext.it  : (['serif'], 'normal', 'oblique')
+#mathtext.bf  : (['serif'], 'bold', 'normal')
+#mathtext.sf  : (['sans-serif'], 'normal', 'normal')
+#mathtext.use_cm : True
+#mathtext.fallback_to_cm : True  # When True, use symbols from the Computer 
Modern
+                                # fonts when a symbol can not be found in one 
of 
+                                # the user-specified math fonts.
+
 ### AXES
 # default face and edge color, default tick sizes,
 # default fontsizes for ticklabels, and so on.  See

Modified: trunk/matplotlib/lib/matplotlib/rcsetup.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/rcsetup.py  2007-08-06 18:52:07 UTC (rev 
3676)
+++ trunk/matplotlib/lib/matplotlib/rcsetup.py  2007-08-06 20:53:11 UTC (rev 
3677)
@@ -198,6 +198,12 @@
     except ValueError:
         raise ValueError('not a valid font size')
 
+def validate_mathtext_font(s):
+    s = eval(s)
+    if type(s) in (list, tuple) and len(s) == 3:
+        return s
+    raise ValueError('Mathtext font specifier must be a 3-tuple of (family, 
weight, style)')
+    
 validate_markup = ValidateInStrings(
     'markup', 
     ['plain', 'tex'],
@@ -357,6 +363,15 @@
     'text.fontsize'       : ['medium', validate_fontsize],
     'text.markup'         : ['plain', validate_markup],
 
+    'mathtext.cal'        : [(['cursive'], 'normal', 'normal'), 
validate_mathtext_font],
+    'mathtext.rm'         : [(['serif'], 'normal', 'normal'), 
validate_mathtext_font],
+    'mathtext.tt'         : [(['monospace'], 'normal', 'normal'), 
validate_mathtext_font],
+    'mathtext.it'         : [(['serif'], 'normal', 'oblique'), 
validate_mathtext_font],
+    'mathtext.bf'         : [(['serif'], 'bold', 'normal'), 
validate_mathtext_font],
+    'mathtext.sf'         : [(['sans-serif'], 'normal', 'normal'), 
validate_mathtext_font],
+    'mathtext.use_cm'     : [True, validate_bool],
+    'mathtext.fallback_to_cm' : [True, validate_bool],
+    
     'image.aspect'        : ['equal', validate_aspect],  # equal, auto, a 
number
     'image.interpolation' : ['bilinear', str],
     'image.cmap'          : ['jet', str],        # one of gray, jet, etc

Modified: trunk/matplotlib/matplotlibrc.template
===================================================================
--- trunk/matplotlib/matplotlibrc.template      2007-08-06 18:52:07 UTC (rev 
3676)
+++ trunk/matplotlib/matplotlibrc.template      2007-08-06 20:53:11 UTC (rev 
3677)
@@ -159,6 +159,22 @@
                                # In that case, all text will be sent to TeX 
for 
                                # processing.
 
+# The following settings allow you to select the fonts in math mode.
+# They map from a TeX font name to a 3-tuple of the form:
+#    (family, weight, style)
+# These settings are only used if mathtext.use_cm is False, otherwise, the
+# Bakoma TeX Computer Modern fonts are used.
+#mathtext.cal : (['cursive'], 'normal', 'normal')
+#mathtext.rm  : (['serif'], 'normal', 'normal')
+#mathtext.tt  : (['monospace'], 'normal', 'normal')
+#mathtext.it  : (['serif'], 'normal', 'oblique')
+#mathtext.bf  : (['serif'], 'bold', 'normal')
+#mathtext.sf  : (['sans-serif'], 'normal', 'normal')
+#mathtext.use_cm : True
+#mathtext.fallback_to_cm : True  # When True, use symbols from the Computer 
Modern
+                                # fonts when a symbol can not be found in one 
of 
+                                # the user-specified math fonts.
+
 ### AXES
 # default face and edge color, default tick sizes,
 # default fontsizes for ticklabels, and so on.  See


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
Matplotlib-checkins@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to