Revision: 3742
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3742&view=rev
Author:   mdboom
Date:     2007-08-27 12:34:23 -0700 (Mon, 27 Aug 2007)

Log Message:
-----------
Better fontconfig pattern standards compliance.  Added experimental
(may be removed) fontconfig support.

Modified Paths:
--------------
    trunk/matplotlib/lib/matplotlib/font_manager.py
    trunk/matplotlib/lib/matplotlib/fontconfig_pattern.py

Modified: trunk/matplotlib/lib/matplotlib/font_manager.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/font_manager.py     2007-08-27 19:33:45 UTC 
(rev 3741)
+++ trunk/matplotlib/lib/matplotlib/font_manager.py     2007-08-27 19:34:23 UTC 
(rev 3742)
@@ -48,6 +48,8 @@
 except ImportError:
     import pickle
 
+USE_FONTCONFIG = False
+    
 verbose = matplotlib.verbose
 
 font_scalings = {'xx-small': 0.579, 'x-small': 0.694, 'small': 0.833,
@@ -84,13 +86,14 @@
     "/System/Library/Fonts/"
 ]
 
-home = os.environ.get('HOME')
-if home is not None:
-    # user fonts on OSX
-    path = os.path.join(home, 'Library', 'Fonts')
-    OSXFontDirectories.append(path)
-    path = os.path.join(home, '.fonts')
-    X11FontDirectories.append(path)
+if not USE_FONTCONFIG:
+    home = os.environ.get('HOME')
+    if home is not None:
+        # user fonts on OSX
+        path = os.path.join(home, 'Library', 'Fonts')
+        OSXFontDirectories.append(path)
+        path = os.path.join(home, '.fonts')
+        X11FontDirectories.append(path)
 
 def win32FontDirectory():
     """Return the user-specified font directory for Win32."""
@@ -609,10 +612,10 @@
         family = rcParams['font.' + rcParams['font.family']]
         if is_string_like(family):
             family = [family]
-        slant = rcParams['font.style']
-        variant = rcParams['font.variant']
-        weight = rcParams['font.weight']
-        stretch = rcParams['font.stretch']
+        slant = [rcParams['font.style']]
+        variant = [rcParams['font.variant']]
+        weight = [rcParams['font.weight']]
+        stretch = [rcParams['font.stretch']]
         size = [rcParams['font.size']]
         file = None
         
@@ -675,32 +678,35 @@
 
     def get_style(self):
         """Return the font style.  Values are: normal, italic or oblique."""
-        return self.__props.slant
+        return self.__props.slant[0]
 
     def get_variant(self):
         """Return the font variant.  Values are: normal or small-caps."""
-        return self.__props.variant
+        return self.__props.variant[0]
 
     def get_weight(self):
         """
         Return the font weight.  See the FontProperties class for a
         a list of possible values.
         """
-        return self.__props.weight
+        return self.__props.weight[0]
 
     def get_stretch(self):
         """
         Return the font stretch or width.  Options are: normal,
         narrow, condensed, or wide.
         """
-        return self.__props.stretch
+        return self.__props.stretch[0]
 
     def get_size(self):
         """Return the font size."""
         return float(self.__props.size[0])
 
     def get_file(self):
-        return self.__props.file
+        if self.__props.file is not None:
+            return self.__props.file[0]
+        else:
+            return None
 
     def get_fontconfig_pattern(self):
         return generate_fontconfig_pattern(self.__props.__dict__)
@@ -723,7 +729,7 @@
         else:
             if style not in ('normal', 'italic', 'oblique'):
                 raise ValueError("style must be normal, italic or oblique")
-            self.__props.slant = style
+            self.__props.slant = [style]
 
     def set_variant(self, variant):
         """Set the font variant.  Values are: normal or small-caps."""
@@ -732,7 +738,7 @@
         else:
             if variant not in ('normal', 'small-caps'):
                 raise ValueError("variant must be normal or small-caps")
-            self.__props.variant = variant
+            self.__props.variant = [variant]
 
     def set_weight(self, weight):
         """
@@ -745,7 +751,7 @@
             if (weight not in weight_dict and
                 weight not in weight_dict.keys()):
                 raise ValueError("weight is invalid")
-            self.__props.weight = weight
+            self.__props.weight = [weight]
 
     def set_stretch(self, stretch):
         """
@@ -755,7 +761,7 @@
         if stretch is None:
             self.__props.__dict__.pop('stretch', None)
         else:
-            self.__props.stretch = stretch
+            self.__props.stretch = [stretch]
 
     def set_size(self, size):
         """Set the font size."""
@@ -774,13 +780,19 @@
             self.__props.size = size
 
     def set_file(self, file):
-        self.__props.file = file
+        if file is None:
+            self.__props.__dict__.pop('file', None)
+        else:
+            self.__props.file = [file]
 
     get_size_in_points = get_size
 
     def set_fontconfig_pattern(self, pattern):
         self.__props.__dict__ = self._parse_fontconfig_pattern(pattern)
-    
+
+    def add_property_pair(self, key, val):
+        self.__props.setdefault(key, []).append(val)
+        
     def copy(self):
         """Return a deep copy of self"""
         return FontProperties(_init = self.__props.__dict__)
@@ -1026,29 +1038,60 @@
             return self.defaultFont
         return fname
 
+if USE_FONTCONFIG and sys.platform != 'win32':
+    import re
 
-_fmcache = os.path.join(get_configdir(), 'fontManager.cache')
+    def fc_match(pattern, fontext):
+        import commands
+        ext = "." + fontext
+        status, output = commands.getstatusoutput('fc-match -sv "%s"' % 
pattern)
+        if status == 0:
+            for match in _fc_match_regex.finditer(output):
+                file = match.group(1)
+                if os.path.splitext(file)[1] == ext:
+                    return file
+        return None
 
-fontManager = None
+    _fc_match_regex = re.compile(r'\sfile:\s+"(.*)"')
+    _fc_match_cache = {}
+    
+    def findfont(prop, fontext='ttf'):
+        if not is_string_like(prop):
+            prop = prop.get_fontconfig_pattern()
+        cached = _fc_match_cache.get(prop)
+        if cached is not None:
+            return cached
 
-def _rebuild():
-    global fontManager
-    fontManager = FontManager()
-    pickle_dump(fontManager, _fmcache)
-    verbose.report("generated new fontManager")
+        result = fc_match(prop, fontext)
+        if result is None:
+            result = fc_match(':', fontext)
 
-try:
-    fontManager = pickle_load(_fmcache)
-    verbose.report("Using fontManager instance from %s" % _fmcache)
-except:
-    _rebuild()
+        _fc_match_cache[prop] = result
+        return result
 
-def findfont(prop, **kw):
-    global fontManager
-    font = fontManager.findfont(prop, **kw)
-    if not os.path.exists(font):
-        verbose.report("%s returned by pickled fontManager does not exist" % 
font)
+else:
+    _fmcache = os.path.join(get_configdir(), 'fontManager.cache')
+
+    fontManager = None
+
+    def _rebuild():
+        global fontManager
+        fontManager = FontManager()
+        pickle_dump(fontManager, _fmcache)
+        verbose.report("generated new fontManager")
+
+    try:
+        fontManager = pickle_load(_fmcache)
+        verbose.report("Using fontManager instance from %s" % _fmcache)
+    except:
         _rebuild()
-        font =  fontManager.findfont(prop, **kw)
-    return font
 
+    def findfont(prop, **kw):
+        global fontManager
+        font = fontManager.findfont(prop, **kw)
+        if not os.path.exists(font):
+            verbose.report("%s returned by pickled fontManager does not exist" 
% font)
+            _rebuild()
+            font =  fontManager.findfont(prop, **kw)
+        return font
+

Modified: trunk/matplotlib/lib/matplotlib/fontconfig_pattern.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/fontconfig_pattern.py       2007-08-27 
19:33:45 UTC (rev 3741)
+++ trunk/matplotlib/lib/matplotlib/fontconfig_pattern.py       2007-08-27 
19:34:23 UTC (rev 3742)
@@ -19,7 +19,7 @@
 """
 import re
 from matplotlib.pyparsing import Literal, OneOrMore, ZeroOrMore, \
-    Optional, Regex, StringEnd, ParseException
+    Optional, Regex, StringEnd, ParseException, Suppress
 
 family_punc = r'\\\-:,'
 family_unescape = re.compile(r'\\([%s])' % family_punc).sub
@@ -89,8 +89,12 @@
                     ).setParseAction(self._point_sizes)
 
         property    =( (name
-                      + Literal('=')
-                      + value)
+                      + Suppress(Literal('='))
+                      + value
+                      + ZeroOrMore(
+                          Suppress(Literal(','))
+                        + value)
+                      )
                      |  name
                     ).setParseAction(self._property)
 
@@ -142,9 +146,11 @@
         if len(tokens) == 1:
             if tokens[0] in self._constants:
                 key, val = self._constants[tokens[0]]
-        elif len(tokens) == 3:
-            key, op, val = tokens
-        self._properties[key] = val
+                self._properties.setdefault(key, []).append(val)
+        else:
+            key = tokens[0]
+            val = tokens[1:]
+            self._properties.setdefault(key, []).extend(val)
         return []
 
 parse_fontconfig_pattern = FontconfigPatternParser().parse
@@ -156,14 +162,9 @@
     families = ''
     size = ''
     for key, val in d.items():
-        if key == 'family':
-            families = [family_escape(r'\\\1', name) for name in val]
-            families = ','.join(families)
-        elif key == 'size':
-            size = '-' + ','.join([str(x) for x in val])
-        elif val is not None:
-            val = value_escape(r'\\\1', str(val))
-            props.append(":%s=%s" % (key, val))
-    props = ''.join(props)
-
-    return ''.join([families, size, props])
+        if val is not None and val != []:
+            val = [value_escape(r'\\\1', str(x)) for x in val if x is not None]
+            if val != []:
+                val = ','.join(val)
+                props.append(":%s=%s" % (key, val))
+    return ''.join(props)


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