|
From: <md...@us...> - 2007-08-27 19:34:32
|
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.
|