SourceForge logo
SourceForge logo
Menu

matplotlib-checkins — Commit notification. DO NOT POST to this list, just subscribe to it.

You can subscribe to this list here.

2007 Jan
Feb
Mar
Apr
May
Jun
Jul
(115)
Aug
(120)
Sep
(137)
Oct
(170)
Nov
(461)
Dec
(263)
2008 Jan
(120)
Feb
(74)
Mar
(35)
Apr
(74)
May
(245)
Jun
(356)
Jul
(240)
Aug
(115)
Sep
(78)
Oct
(225)
Nov
(98)
Dec
(271)
2009 Jan
(132)
Feb
(84)
Mar
(74)
Apr
(56)
May
(90)
Jun
(79)
Jul
(83)
Aug
(296)
Sep
(214)
Oct
(76)
Nov
(82)
Dec
(66)
2010 Jan
(46)
Feb
(58)
Mar
(51)
Apr
(77)
May
(58)
Jun
(126)
Jul
(128)
Aug
(64)
Sep
(50)
Oct
(44)
Nov
(48)
Dec
(54)
2011 Jan
(68)
Feb
(52)
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
(1)
2018 Jan
Feb
Mar
Apr
May
(1)
Jun
Jul
Aug
Sep
Oct
Nov
Dec

Showing results of 5455

<< < 1 .. 213 214 215 216 217 .. 219 > >> (Page 215 of 219)
Revision: 3636
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3636&view=rev
Author: mdboom
Date: 2007年07月30日 12:46:53 -0700 (2007年7月30日)
Log Message:
-----------
Fix numpification typo affecting mathtext output with Cairo backend.
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py	2007年07月30日 18:57:09 UTC (rev 3635)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py	2007年07月30日 19:46:53 UTC (rev 3636)
@@ -335,7 +335,7 @@
 Xall[:,i] = npy.fromstring(s, npy.uint8)
 
 # get the max alpha at each pixel
- Xs = npy.mlab.max (Xall,1)
+ Xs = npy.max (Xall,1)
 
 # convert it to it's proper shape
 Xs.shape = imh, imw
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年07月30日 18:57:15
Revision: 3635
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3635&view=rev
Author: mdboom
Date: 2007年07月30日 11:57:09 -0700 (2007年7月30日)
Log Message:
-----------
Improving spacing operators.
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/mathtext.py
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py	2007年07月30日 18:44:36 UTC (rev 3634)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py	2007年07月30日 18:57:09 UTC (rev 3635)
@@ -1698,13 +1698,17 @@
 space =(FollowedBy(bslash)
 + (Literal(r'\ ')
 | Literal(r'\/')
- | Group(Literal(r'\hspace{') + number + Literal('}'))
- )
+ | Literal(r',円')
+ | Literal(r'\;')
+ | Literal(r'\quad')
+ | Literal(r'\qquad')
+ | Literal(r'\!')
+ )
 ).setParseAction(self.space).setName('space')
 
 symbol = Regex("(" + ")|(".join(
 [
- r"\\(?!left[^a-z])(?!right[^a-z])[a-zA-Z0-9]+(?!{)",
+ r"\\(?!quad)(?!qquad)(?!left[^a-z])(?!right[^a-z])[a-zA-Z0-9]+(?!{)",
 r"[a-zA-Z0-9 ]",
 r"[+\-*/]",
 r"[<>=]",
@@ -1794,7 +1798,7 @@
 
 ambiDelim = oneOf(r"""| \| / \backslash \uparrow \downarrow
 \updownarrow \Uparrow \Downarrow
- \Updownarrow""")
+ \Updownarrow .""")
 leftDelim = oneOf(r"( [ { \lfloor \langle \lceil")
 rightDelim = oneOf(r") ] } \rfloor \rangle \rceil")
 autoDelim <<(Suppress(Literal(r"\left"))
@@ -1886,16 +1890,19 @@
 state = self.get_state()
 metrics = state.font_output.get_metrics(
 state.font, 'm', state.fontsize, state.dpi)
- em = metrics.width
- return Hbox(em * percentage)
- 
+ em = metrics.advance
+ return Kern(em * percentage)
+
+ _space_widths = { r'\ ' : 0.3,
+ r',円' : 0.4,
+ r'\;' : 0.8,
+ r'\quad' : 1.6,
+ r'\qquad' : 3.2,
+ r'\!' : -0.4,
+ r'\/' : 0.4 }
 def space(self, s, loc, toks):
 assert(len(toks)==1)
- if toks[0]==r'\ ': num = 0.30 # 30% of fontsize
- elif toks[0]==r'\/': num = 0.1 # 10% of fontsize
- else: # hspace
- num = float(toks[0][1]) # get the num out of \hspace{num}
-
+ num = self._space_widths[toks[0]]
 box = self._make_space(num)
 return [box]
 
@@ -2179,10 +2186,13 @@
 state = self.get_state()
 height = max([x.height for x in middle])
 depth = max([x.depth for x in middle])
- hlist = Hlist(
- [AutoSizedDelim(front, height, depth, state)] +
- middle.asList() +
- [AutoSizedDelim(back, height, depth, state)])
+ parts = []
+ if front != '.':
+ parts.append(AutoSizedDelim(front, height, depth, state))
+ parts.extend(middle.asList())
+ if back != '.':
+ parts.append(AutoSizedDelim(back, height, depth, state))
+ hlist = Hlist(parts)
 return hlist
 
 ####
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <ds...@us...> - 2007年07月30日 18:45:42
Revision: 3634
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3634&view=rev
Author: dsdale
Date: 2007年07月30日 11:44:36 -0700 (2007年7月30日)
Log Message:
-----------
minor changes to traited configs
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/__init__.py
 trunk/matplotlib/lib/matplotlib/config/__init__.py
 trunk/matplotlib/lib/matplotlib/config/mplconfig.py
 trunk/matplotlib/lib/matplotlib/config/mpltraits.py
 trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc
Modified: trunk/matplotlib/lib/matplotlib/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/__init__.py	2007年07月30日 18:05:14 UTC (rev 3633)
+++ trunk/matplotlib/lib/matplotlib/__init__.py	2007年07月30日 18:44:36 UTC (rev 3634)
@@ -708,7 +708,7 @@
 rcParams.update(rcParamsDefault)
 
 if NEWCONFIG:
- print "importing from reorganized config system!"
+ #print "importing from reorganized config system!"
 from config import rcParams, rcdefaults
 try:
 from config import mplConfig, save_config
Modified: trunk/matplotlib/lib/matplotlib/config/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/__init__.py	2007年07月30日 18:05:14 UTC (rev 3633)
+++ trunk/matplotlib/lib/matplotlib/config/__init__.py	2007年07月30日 18:44:36 UTC (rev 3634)
@@ -1,12 +1,12 @@
 # Please keep this file empty
 
-USE_TRAITED_CONFIG = False
+USE_TRAITED_CONFIG = True
 
 from rcparams import rc
 from cutils import get_config_file
 
 if USE_TRAITED_CONFIG:
- print 'Using new config system!'
+ #print 'Using new config system!'
 from mplconfig import rcParams, mplConfig, save_config, rcdefaults
 else:
 from rcparams import rcParams, rcdefaults
Modified: trunk/matplotlib/lib/matplotlib/config/mplconfig.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/mplconfig.py	2007年07月30日 18:05:14 UTC (rev 3633)
+++ trunk/matplotlib/lib/matplotlib/config/mplconfig.py	2007年07月30日 18:44:36 UTC (rev 3634)
@@ -88,7 +88,7 @@
 fonttype = T.Trait(3, 42)
 
 class distiller(TConfig):
- use = T.Trait(None, None, 'ghostscript', 'xpdf')
+ use = T.Trait(None, None, 'ghostscript', 'xpdf', False)
 resolution = T.Float(6000)
 
 class pdf(TConfig):
@@ -267,7 +267,7 @@
 dpi = T.Float(100)
 facecolor = T.Trait('white', mplT.ColorHandler())
 edgecolor = T.Trait('white', mplT.ColorHandler())
- orientation = T.Trait('portrait', 'portrait', 'landscape')
+ orientation = T.Trait('portrait', 'portrait', 'landscape')
 
 class verbose(TConfig):
 level = T.Trait('silent', 'silent', 'helpful', 'debug', 'debug-annoying')
@@ -457,13 +457,19 @@
 return self.tconfig_map.has_key(val)
 
 
-config_file = cutils.get_config_file(tconfig=True)
 old_config_file = cutils.get_config_file(tconfig=False)
+old_config_path = os.path.split(old_config_file)[0]
+config_file = os.path.join(old_config_path, 'matplotlib.conf')
+
 if os.path.exists(old_config_file) and not os.path.exists(config_file):
+ print 'convert!'
 CONVERT = True
-else: CONVERT = False
+else:
+ config_file = cutils.get_config_file(tconfig=True)
+ CONVERT = False
+
 configManager = TConfigManager(MPLConfig,
- cutils.get_config_file(tconfig=True),
+ config_file,
 filePriority=True)
 mplConfig = configManager.tconf
 mplConfigDefault = MPLConfig()
Modified: trunk/matplotlib/lib/matplotlib/config/mpltraits.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/mpltraits.py	2007年07月30日 18:05:14 UTC (rev 3633)
+++ trunk/matplotlib/lib/matplotlib/config/mpltraits.py	2007年07月30日 18:44:36 UTC (rev 3634)
@@ -32,7 +32,7 @@
 'ps': 'PS',
 'pdf': 'PDF',
 'svg': 'SVG',
- 'template': 'Templates' }
+ 'template': 'Template' }
 
 def validate(self, object, name, value):
 try:
@@ -143,4 +143,4 @@
 'gist_yarg', 'gist_yarg_r', 'gray', 'gray_r', 'hot', 'hot_r', 
 'hsv', 'hsv_r', 'jet', 'jet_r', 'pink', 'pink_r', 
 'prism', 'prism_r', 'spectral', 'spectral_r', 'spring', 
- 'spring_r', 'summer', 'summer_r', 'winter', 'winter_r']
\ No newline at end of file
+ 'spring_r', 'summer', 'summer_r', 'winter', 'winter_r']
Modified: trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc
===================================================================
--- trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc	2007年07月30日 18:05:14 UTC (rev 3633)
+++ trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc	2007年07月30日 18:44:36 UTC (rev 3634)
@@ -243,6 +243,7 @@
 #savefig.dpi : 100 # figure dots per inch
 #savefig.facecolor : white # figure facecolor when saving
 #savefig.edgecolor : white # figure edgecolor when saving
+#savefig.orientation : portrait # portrait or landscape
 
 #cairo.format : png # png, ps, pdf, svg
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年07月30日 18:05:23
Revision: 3633
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3633&view=rev
Author: mdboom
Date: 2007年07月30日 11:05:14 -0700 (2007年7月30日)
Log Message:
-----------
Various minor bugfixes.
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/_mathtext_data.py
 trunk/matplotlib/lib/matplotlib/mathtext.py
Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/_mathtext_data.py	2007年07月30日 17:41:14 UTC (rev 3632)
+++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py	2007年07月30日 18:05:14 UTC (rev 3633)
@@ -2214,7 +2214,7 @@
 'combiningbreve' : 774,
 'combiningoverline' : 772,
 'combininggraveaccent' : 768,
-'combiningacuteaccent' : 764,
+'combiningacuteaccent' : 714,
 'combiningdiaeresis' : 776,
 'combiningtilde' : 771,
 'combiningrightarrowabove' : 8407,
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py	2007年07月30日 17:41:14 UTC (rev 3632)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py	2007年07月30日 18:05:14 UTC (rev 3633)
@@ -617,7 +617,7 @@
 return alternatives
 return [(fontname, sym)]
 
-class UnicodeFonts(BakomaFonts):
+class UnicodeFonts(TruetypeFonts):
 """An abstract base class for handling Unicode fonts.
 """
 fontmap = { 'cal' : 'cmsy10',
@@ -628,7 +628,7 @@
 'sf' : 'DejaVuSans',
 None : 'DejaVuSerif-Italic'
 }
- 
+
 def _get_offset(self, cached_font, glyph, fontsize, dpi):
 return 0.
 
@@ -637,6 +637,7 @@
 
 try:
 uniindex = get_unicode_index(sym)
+ found_symbol = True
 except ValueError:
 # This is a total hack, but it works for now
 if sym.startswith('\\big'):
@@ -658,7 +659,7 @@
 glyphindex = cached_font.charmap[uniindex]
 except KeyError:
 warn("Font '%s' does not have a glyph for '%s'" %
- (cached_font.postscript_name, sym),
+ (cached_font.font.postscript_name, sym),
 MathTextWarning)
 found_symbol = False
 
@@ -2228,7 +2229,7 @@
 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)
+ #~ font_output = UnicodeFonts(prop, backend)
 
 fontsize = prop.get_size_in_points()
 if self._parser is None:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <ds...@us...> - 2007年07月30日 17:41:37
Revision: 3632
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3632&view=rev
Author: dsdale
Date: 2007年07月30日 10:41:14 -0700 (2007年7月30日)
Log Message:
-----------
Ability to use new, traited configuration system in mpl
Modified Paths:
--------------
 trunk/matplotlib/CHANGELOG
 trunk/matplotlib/lib/matplotlib/__init__.py
 trunk/matplotlib/lib/matplotlib/config/__init__.py
 trunk/matplotlib/lib/matplotlib/config/cutils.py
 trunk/matplotlib/lib/matplotlib/config/mplconfig.py
 trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc
 trunk/matplotlib/setup.py
Removed Paths:
-------------
 trunk/matplotlib/lib/matplotlib/config/api.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG	2007年07月30日 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/CHANGELOG	2007年07月30日 17:41:14 UTC (rev 3632)
@@ -1,3 +1,12 @@
+2007年07月30日 Reorganized configuration code to work with traited config
+ objects. The new config system is located in the 
+ matplotlib.config package, but it is disabled by default.
+ To enable it, set NEWCONFIG=True in matplotlib.__init__.py.
+ The new configuration system will still use the old 
+ matplotlibrc files by default. To switch to the experimental,
+ traited configuration, set USE_TRAITED_CONFIG=True in 
+ config.__init__.py.
+
 2007年07月29日 Changed default pcolor shading to flat; added aliases
 to make collection kwargs agree with setter names, so
 updating works; related minor cleanups.
Modified: trunk/matplotlib/lib/matplotlib/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/__init__.py	2007年07月30日 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/lib/matplotlib/__init__.py	2007年07月30日 17:41:14 UTC (rev 3632)
@@ -55,6 +55,7 @@
 """
 from __future__ import generators
 
+NEWCONFIG = False
 
 __version__ = '0.90.1'
 __revision__ = '$Revision$'
@@ -706,6 +707,13 @@
 """
 rcParams.update(rcParamsDefault)
 
+if NEWCONFIG:
+ print "importing from reorganized config system!"
+ from config import rcParams, rcdefaults
+ try:
+ from config import mplConfig, save_config
+ except:
+ pass
 
 def use(arg):
 """
Modified: trunk/matplotlib/lib/matplotlib/config/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/__init__.py	2007年07月30日 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/lib/matplotlib/config/__init__.py	2007年07月30日 17:41:14 UTC (rev 3632)
@@ -1 +1,12 @@
-# Please keep this file empty
\ No newline at end of file
+# Please keep this file empty
+
+USE_TRAITED_CONFIG = False
+
+from rcparams import rc
+from cutils import get_config_file
+
+if USE_TRAITED_CONFIG:
+ print 'Using new config system!'
+ from mplconfig import rcParams, mplConfig, save_config, rcdefaults
+else:
+ from rcparams import rcParams, rcdefaults
Deleted: trunk/matplotlib/lib/matplotlib/config/api.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/api.py	2007年07月30日 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/lib/matplotlib/config/api.py	2007年07月30日 17:41:14 UTC (rev 3632)
@@ -1,12 +0,0 @@
-"""
-"""
-
-USE_NEW_CONFIG = True
-
-from rcparams import rc
-from cutils import get_config_file
-
-if USE_NEW_CONFIG:
- from mplconfig import rcParams, mplConfig, save_config
-else:
- from rcparams import rcParams
Modified: trunk/matplotlib/lib/matplotlib/config/cutils.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/cutils.py	2007年07月30日 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/lib/matplotlib/config/cutils.py	2007年07月30日 17:41:14 UTC (rev 3632)
@@ -179,4 +179,4 @@
 fname = os.path.join(path, filename)
 if not os.path.exists(fname):
 warnings.warn('Could not find %s; using defaults'%filename)
- return fname
\ No newline at end of file
+ return fname
Modified: trunk/matplotlib/lib/matplotlib/config/mplconfig.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/mplconfig.py	2007年07月30日 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/lib/matplotlib/config/mplconfig.py	2007年07月30日 17:41:14 UTC (rev 3632)
@@ -10,6 +10,7 @@
 # internal imports
 import mpltraits as mplT
 import cutils
+import checkdep
 from tconfig import TConfig, TConfigManager
 import pytz
 
@@ -266,210 +267,220 @@
 dpi = T.Float(100)
 facecolor = T.Trait('white', mplT.ColorHandler())
 edgecolor = T.Trait('white', mplT.ColorHandler())
-	orientation = T.Trait('portrait', 'portrait', 'landscape')
+ orientation = T.Trait('portrait', 'portrait', 'landscape')
 
 class verbose(TConfig):
 level = T.Trait('silent', 'silent', 'helpful', 'debug', 'debug-annoying')
 fileo = T.Trait('sys.stdout', 'sys.stdout', T.File)
 
 
-config_file = cutils.get_config_file(tconfig=True)
-old_config_file = cutils.get_config_file(tconfig=False)
-print 
-if os.path.exists(old_config_file) and not os.path.exists(config_file):
- CONVERT = True
-else: CONVERT = False
-configManager = TConfigManager(MPLConfig,
- cutils.get_config_file(tconfig=True),
- filePriority=True)
-mplConfig = configManager.tconf
-
-
-def save_config():
- """Save mplConfig customizations to current matplotlib.conf
- """
- configManager.write()
-
-
 class RcParamsWrapper(dict):
 
 """A backwards-compatible interface to a traited config object
 """
 
- tconf = {
- 'backend' : (mplConfig.backend, 'use'),
- 'numerix' : (mplConfig, 'numerix'),
- 'maskedarray' : (mplConfig, 'maskedarray'),
- 'toolbar' : (mplConfig, 'toolbar'),
- 'datapath' : (mplConfig, 'datapath'),
- 'units' : (mplConfig, 'units'),
- 'interactive' : (mplConfig, 'interactive'),
- 'timezone' : (mplConfig, 'timezone'),
+ def __init__(self, tconfig):
+ self.tconfig = tconfig
+ 
+ self.tconfig_map = {
+ 'backend' : (self.tconfig.backend, 'use'),
+ 'numerix' : (self.tconfig, 'numerix'),
+ 'maskedarray' : (self.tconfig, 'maskedarray'),
+ 'toolbar' : (self.tconfig, 'toolbar'),
+ 'datapath' : (self.tconfig, 'datapath'),
+ 'units' : (self.tconfig, 'units'),
+ 'interactive' : (self.tconfig, 'interactive'),
+ 'timezone' : (self.tconfig, 'timezone'),
 
- # the verbosity setting
- 'verbose.level' : (mplConfig.verbose, 'level'),
- 'verbose.fileo' : (mplConfig.verbose, 'fileo'),
+ # the verbosity setting
+ 'verbose.level' : (self.tconfig.verbose, 'level'),
+ 'verbose.fileo' : (self.tconfig.verbose, 'fileo'),
 
- # line props
- 'lines.linewidth' : (mplConfig.lines, 'linewidth'),
- 'lines.linestyle' : (mplConfig.lines, 'linestyle'),
- 'lines.color' : (mplConfig.lines, 'color'),
- 'lines.marker' : (mplConfig.lines, 'marker'),
- 'lines.markeredgewidth' : (mplConfig.lines, 'markeredgewidth'),
- 'lines.markersize' : (mplConfig.lines, 'markersize'),
- 'lines.antialiased' : (mplConfig.lines, 'antialiased'),
- 'lines.dash_joinstyle' : (mplConfig.lines, 'dash_joinstyle'),
- 'lines.solid_joinstyle' : (mplConfig.lines, 'solid_joinstyle'),
- 'lines.dash_capstyle' : (mplConfig.lines, 'dash_capstyle'),
- 'lines.solid_capstyle' : (mplConfig.lines, 'solid_capstyle'),
+ # line props
+ 'lines.linewidth' : (self.tconfig.lines, 'linewidth'),
+ 'lines.linestyle' : (self.tconfig.lines, 'linestyle'),
+ 'lines.color' : (self.tconfig.lines, 'color'),
+ 'lines.marker' : (self.tconfig.lines, 'marker'),
+ 'lines.markeredgewidth' : (self.tconfig.lines, 'markeredgewidth'),
+ 'lines.markersize' : (self.tconfig.lines, 'markersize'),
+ 'lines.antialiased' : (self.tconfig.lines, 'antialiased'),
+ 'lines.dash_joinstyle' : (self.tconfig.lines, 'dash_joinstyle'),
+ 'lines.solid_joinstyle' : (self.tconfig.lines, 'solid_joinstyle'),
+ 'lines.dash_capstyle' : (self.tconfig.lines, 'dash_capstyle'),
+ 'lines.solid_capstyle' : (self.tconfig.lines, 'solid_capstyle'),
 
- # patch props
- 'patch.linewidth' : (mplConfig.patch, 'linewidth'),
- 'patch.edgecolor' : (mplConfig.patch, 'edgecolor'),
- 'patch.facecolor' : (mplConfig.patch, 'facecolor'),
- 'patch.antialiased' : (mplConfig.patch, 'antialiased'),
+ # patch props
+ 'patch.linewidth' : (self.tconfig.patch, 'linewidth'),
+ 'patch.edgecolor' : (self.tconfig.patch, 'edgecolor'),
+ 'patch.facecolor' : (self.tconfig.patch, 'facecolor'),
+ 'patch.antialiased' : (self.tconfig.patch, 'antialiased'),
 
 
- # font props
- 'font.family' : (mplConfig.font, 'family'),
- 'font.style' : (mplConfig.font, 'style'),
- 'font.variant' : (mplConfig.font, 'variant'),
- 'font.stretch' : (mplConfig.lines, 'color'),
- 'font.weight' : (mplConfig.font, 'weight'),
- 'font.size' : (mplConfig.font, 'size'),
- 'font.serif' : (mplConfig.font, 'serif'),
- 'font.sans-serif' : (mplConfig.font, 'sans_serif'),
- 'font.cursive' : (mplConfig.font, 'cursive'),
- 'font.fantasy' : (mplConfig.font, 'fantasy'),
- 'font.monospace' : (mplConfig.font, 'monospace'),
+ # font props
+ 'font.family' : (self.tconfig.font, 'family'),
+ 'font.style' : (self.tconfig.font, 'style'),
+ 'font.variant' : (self.tconfig.font, 'variant'),
+ 'font.stretch' : (self.tconfig.lines, 'color'),
+ 'font.weight' : (self.tconfig.font, 'weight'),
+ 'font.size' : (self.tconfig.font, 'size'),
+ 'font.serif' : (self.tconfig.font, 'serif'),
+ 'font.sans-serif' : (self.tconfig.font, 'sans_serif'),
+ 'font.cursive' : (self.tconfig.font, 'cursive'),
+ 'font.fantasy' : (self.tconfig.font, 'fantasy'),
+ 'font.monospace' : (self.tconfig.font, 'monospace'),
 
- # text props
- 'text.color' : (mplConfig.text, 'color'),
- 'text.usetex' : (mplConfig.text, 'usetex'),
- 'text.latex.unicode' : (mplConfig.text.latex, 'unicode'),
- 'text.latex.preamble' : (mplConfig.text.latex, 'preamble'),
- 'text.dvipnghack' : (mplConfig.text.latex, 'dvipnghack'),
+ # text props
+ 'text.color' : (self.tconfig.text, 'color'),
+ 'text.usetex' : (self.tconfig.text, 'usetex'),
+ 'text.latex.unicode' : (self.tconfig.text.latex, 'unicode'),
+ 'text.latex.preamble' : (self.tconfig.text.latex, 'preamble'),
+ 'text.dvipnghack' : (self.tconfig.text.latex, 'dvipnghack'),
 
- 'image.aspect' : (mplConfig.image, 'aspect'),
- 'image.interpolation' : (mplConfig.image, 'interpolation'),
- 'image.cmap' : (mplConfig.image, 'cmap'),
- 'image.lut' : (mplConfig.image, 'lut'),
- 'image.origin' : (mplConfig.image, 'origin'),
+ 'image.aspect' : (self.tconfig.image, 'aspect'),
+ 'image.interpolation' : (self.tconfig.image, 'interpolation'),
+ 'image.cmap' : (self.tconfig.image, 'cmap'),
+ 'image.lut' : (self.tconfig.image, 'lut'),
+ 'image.origin' : (self.tconfig.image, 'origin'),
 
- 'contour.negative_linestyle' : (mplConfig.contour, 'negative_linestyle'),
+ 'contour.negative_linestyle' : (self.tconfig.contour, 'negative_linestyle'),
 
- # axes props
- 'axes.axisbelow' : (mplConfig.axes, 'axisbelow'),
- 'axes.hold' : (mplConfig.axes, 'hold'),
- 'axes.facecolor' : (mplConfig.axes, 'facecolor'),
- 'axes.edgecolor' : (mplConfig.axes, 'edgecolor'),
- 'axes.linewidth' : (mplConfig.axes, 'linewidth'),
- 'axes.titlesize' : (mplConfig.axes, 'titlesize'),
- 'axes.grid' : (mplConfig.axes, 'grid'),
- 'axes.labelsize' : (mplConfig.axes, 'labelsize'),
- 'axes.labelcolor' : (mplConfig.axes, 'labelcolor'),
- 'axes.formatter.limits' : (mplConfig.axes.formatter, 'limits'),
+ # axes props
+ 'axes.axisbelow' : (self.tconfig.axes, 'axisbelow'),
+ 'axes.hold' : (self.tconfig.axes, 'hold'),
+ 'axes.facecolor' : (self.tconfig.axes, 'facecolor'),
+ 'axes.edgecolor' : (self.tconfig.axes, 'edgecolor'),
+ 'axes.linewidth' : (self.tconfig.axes, 'linewidth'),
+ 'axes.titlesize' : (self.tconfig.axes, 'titlesize'),
+ 'axes.grid' : (self.tconfig.axes, 'grid'),
+ 'axes.labelsize' : (self.tconfig.axes, 'labelsize'),
+ 'axes.labelcolor' : (self.tconfig.axes, 'labelcolor'),
+ 'axes.formatter.limits' : (self.tconfig.axes.formatter, 'limits'),
 
- 'polaraxes.grid' : (mplConfig.axes, 'polargrid'),
+ 'polaraxes.grid' : (self.tconfig.axes, 'polargrid'),
 
- #legend properties
- 'legend.loc' : (mplConfig.legend, 'loc'),
- 'legend.isaxes' : (mplConfig.legend, 'isaxes'),
- 'legend.numpoints' : (mplConfig.legend, 'numpoints'),
- 'legend.fontsize' : (mplConfig.legend, 'fontsize'),
- 'legend.pad' : (mplConfig.legend, 'pad'),
- 'legend.markerscale' : (mplConfig.legend, 'markerscale'),
- 'legend.labelsep' : (mplConfig.legend, 'labelsep'),
- 'legend.handlelen' : (mplConfig.legend, 'handlelen'),
- 'legend.handletextsep' : (mplConfig.legend, 'handletextsep'),
- 'legend.axespad' : (mplConfig.legend, 'axespad'),
- 'legend.shadow' : (mplConfig.legend, 'shadow'),
+ #legend properties
+ 'legend.loc' : (self.tconfig.legend, 'loc'),
+ 'legend.isaxes' : (self.tconfig.legend, 'isaxes'),
+ 'legend.numpoints' : (self.tconfig.legend, 'numpoints'),
+ 'legend.fontsize' : (self.tconfig.legend, 'fontsize'),
+ 'legend.pad' : (self.tconfig.legend, 'pad'),
+ 'legend.markerscale' : (self.tconfig.legend, 'markerscale'),
+ 'legend.labelsep' : (self.tconfig.legend, 'labelsep'),
+ 'legend.handlelen' : (self.tconfig.legend, 'handlelen'),
+ 'legend.handletextsep' : (self.tconfig.legend, 'handletextsep'),
+ 'legend.axespad' : (self.tconfig.legend, 'axespad'),
+ 'legend.shadow' : (self.tconfig.legend, 'shadow'),
 
- # tick properties
- 'xtick.major.size' : (mplConfig.xticks.major, 'size'),
- 'xtick.minor.size' : (mplConfig.xticks.minor, 'size'),
- 'xtick.major.pad' : (mplConfig.xticks.major, 'pad'),
- 'xtick.minor.pad' : (mplConfig.xticks.minor, 'pad'),
- 'xtick.color' : (mplConfig.xticks, 'color'),
- 'xtick.labelsize' : (mplConfig.xticks, 'labelsize'),
- 'xtick.direction' : (mplConfig.xticks, 'direction'),
+ # tick properties
+ 'xtick.major.size' : (self.tconfig.xticks.major, 'size'),
+ 'xtick.minor.size' : (self.tconfig.xticks.minor, 'size'),
+ 'xtick.major.pad' : (self.tconfig.xticks.major, 'pad'),
+ 'xtick.minor.pad' : (self.tconfig.xticks.minor, 'pad'),
+ 'xtick.color' : (self.tconfig.xticks, 'color'),
+ 'xtick.labelsize' : (self.tconfig.xticks, 'labelsize'),
+ 'xtick.direction' : (self.tconfig.xticks, 'direction'),
 
- 'ytick.major.size' : (mplConfig.yticks.major, 'size'),
- 'ytick.minor.size' : (mplConfig.yticks.minor, 'size'),
- 'ytick.major.pad' : (mplConfig.yticks.major, 'pad'),
- 'ytick.minor.pad' : (mplConfig.yticks.minor, 'pad'),
- 'ytick.color' : (mplConfig.yticks, 'color'),
- 'ytick.labelsize' : (mplConfig.yticks, 'labelsize'),
- 'ytick.direction' : (mplConfig.yticks, 'direction'),
+ 'ytick.major.size' : (self.tconfig.yticks.major, 'size'),
+ 'ytick.minor.size' : (self.tconfig.yticks.minor, 'size'),
+ 'ytick.major.pad' : (self.tconfig.yticks.major, 'pad'),
+ 'ytick.minor.pad' : (self.tconfig.yticks.minor, 'pad'),
+ 'ytick.color' : (self.tconfig.yticks, 'color'),
+ 'ytick.labelsize' : (self.tconfig.yticks, 'labelsize'),
+ 'ytick.direction' : (self.tconfig.yticks, 'direction'),
 
- 'grid.color' : (mplConfig.grid, 'color'),
- 'grid.linestyle' : (mplConfig.grid, 'linestyle'),
- 'grid.linewidth' : (mplConfig.grid, 'linewidth'),
+ 'grid.color' : (self.tconfig.grid, 'color'),
+ 'grid.linestyle' : (self.tconfig.grid, 'linestyle'),
+ 'grid.linewidth' : (self.tconfig.grid, 'linewidth'),
 
 
- # figure props
- 'figure.figsize' : (mplConfig.figure, 'figsize'),
- 'figure.dpi' : (mplConfig.figure, 'dpi'),
- 'figure.facecolor' : (mplConfig.figure, 'facecolor'),
- 'figure.edgecolor' : (mplConfig.figure, 'edgecolor'),
+ # figure props
+ 'figure.figsize' : (self.tconfig.figure, 'figsize'),
+ 'figure.dpi' : (self.tconfig.figure, 'dpi'),
+ 'figure.facecolor' : (self.tconfig.figure, 'facecolor'),
+ 'figure.edgecolor' : (self.tconfig.figure, 'edgecolor'),
 
- 'figure.subplot.left' : (mplConfig.figure.subplot, 'left'),
- 'figure.subplot.right' : (mplConfig.figure.subplot, 'right'),
- 'figure.subplot.bottom' : (mplConfig.figure.subplot, 'bottom'),
- 'figure.subplot.top' : (mplConfig.figure.subplot, 'top'),
- 'figure.subplot.wspace' : (mplConfig.figure.subplot, 'wspace'),
- 'figure.subplot.hspace' : (mplConfig.figure.subplot, 'hspace'),
+ 'figure.subplot.left' : (self.tconfig.figure.subplot, 'left'),
+ 'figure.subplot.right' : (self.tconfig.figure.subplot, 'right'),
+ 'figure.subplot.bottom' : (self.tconfig.figure.subplot, 'bottom'),
+ 'figure.subplot.top' : (self.tconfig.figure.subplot, 'top'),
+ 'figure.subplot.wspace' : (self.tconfig.figure.subplot, 'wspace'),
+ 'figure.subplot.hspace' : (self.tconfig.figure.subplot, 'hspace'),
 
 
- 'savefig.dpi' : (mplConfig.savefig, 'dpi'),
- 'savefig.facecolor' : (mplConfig.savefig, 'facecolor'),
- 'savefig.edgecolor' : (mplConfig.savefig, 'edgecolor'),
- 'savefig.orientation' : (mplConfig.savefig, 'orientation'),
+ 'savefig.dpi' : (self.tconfig.savefig, 'dpi'),
+ 'savefig.facecolor' : (self.tconfig.savefig, 'facecolor'),
+ 'savefig.edgecolor' : (self.tconfig.savefig, 'edgecolor'),
+ 'savefig.orientation' : (self.tconfig.savefig, 'orientation'),
 
- 'cairo.format' : (mplConfig.backend.cairo, 'format'),
- 'tk.window_focus' : (mplConfig.backend.tk, 'window_focus'),
- 'tk.pythoninspect' : (mplConfig.backend.tk, 'pythoninspect'),
- 'ps.papersize' : (mplConfig.backend.ps, 'papersize'),
- 'ps.useafm' : (mplConfig.backend.ps, 'useafm'),
- 'ps.usedistiller' : (mplConfig.backend.ps.distiller, 'use'),
- 'ps.distiller.res' : (mplConfig.backend.ps.distiller, 'resolution'),
- 'ps.fonttype' : (mplConfig.backend.ps, 'fonttype'),
- 'pdf.compression' : (mplConfig.backend.pdf, 'compression'),
- 'pdf.inheritcolor' : (mplConfig.backend.pdf, 'inheritcolor'),
- 'pdf.use14corefonts' : (mplConfig.backend.pdf, 'use14corefonts'),
- 'pdf.fonttype' : (mplConfig.backend.pdf, 'fonttype'),
- 'svg.image_inline' : (mplConfig.backend.svg, 'image_inline'),
- 'svg.image_noscale' : (mplConfig.backend.svg, 'image_noscale'),
- 'svg.embed_char_paths' : (mplConfig.backend.svg, 'embed_chars'),
+ 'cairo.format' : (self.tconfig.backend.cairo, 'format'),
+ 'tk.window_focus' : (self.tconfig.backend.tk, 'window_focus'),
+ 'tk.pythoninspect' : (self.tconfig.backend.tk, 'pythoninspect'),
+ 'ps.papersize' : (self.tconfig.backend.ps, 'papersize'),
+ 'ps.useafm' : (self.tconfig.backend.ps, 'useafm'),
+ 'ps.usedistiller' : (self.tconfig.backend.ps.distiller, 'use'),
+ 'ps.distiller.res' : (self.tconfig.backend.ps.distiller, 'resolution'),
+ 'ps.fonttype' : (self.tconfig.backend.ps, 'fonttype'),
+ 'pdf.compression' : (self.tconfig.backend.pdf, 'compression'),
+ 'pdf.inheritcolor' : (self.tconfig.backend.pdf, 'inheritcolor'),
+ 'pdf.use14corefonts' : (self.tconfig.backend.pdf, 'use14corefonts'),
+ 'pdf.fonttype' : (self.tconfig.backend.pdf, 'fonttype'),
+ 'svg.image_inline' : (self.tconfig.backend.svg, 'image_inline'),
+ 'svg.image_noscale' : (self.tconfig.backend.svg, 'image_noscale'),
+ 'svg.embed_char_paths' : (self.tconfig.backend.svg, 'embed_chars'),
 
- # mathtext settings
- 'mathtext.mathtext2' : (mplConfig.text.math, 'mathtext2'),
- 'mathtext.rm' : (mplConfig.text.math, 'rm'),
- 'mathtext.it' : (mplConfig.text.math, 'it'),
- 'mathtext.tt' : (mplConfig.text.math, 'tt'),
- 'mathtext.mit' : (mplConfig.text.math, 'mit'),
- 'mathtext.cal' : (mplConfig.text.math, 'cal'),
- 'mathtext.nonascii' : (mplConfig.text.math, 'nonascii'),
- }
+ # mathtext settings
+ 'mathtext.mathtext2' : (self.tconfig.text.math, 'mathtext2'),
+ 'mathtext.rm' : (self.tconfig.text.math, 'rm'),
+ 'mathtext.it' : (self.tconfig.text.math, 'it'),
+ 'mathtext.tt' : (self.tconfig.text.math, 'tt'),
+ 'mathtext.mit' : (self.tconfig.text.math, 'mit'),
+ 'mathtext.cal' : (self.tconfig.text.math, 'cal'),
+ 'mathtext.nonascii' : (self.tconfig.text.math, 'nonascii'),
+ }
 
 def __setitem__(self, key, val):
 try:
- obj, attr = self.tconf[key]
+ obj, attr = self.tconfig_map[key]
 setattr(obj, attr, val)
 except KeyError:
 raise KeyError('%s is not a valid rc parameter.\
 See rcParams.keys() for a list of valid parameters.'%key)
 
 def __getitem__(self, key):
- obj, attr = self.tconf[key]
+ obj, attr = self.tconfig_map[key]
 return getattr(obj, attr)
 
- def keys():
- return self.tconf.keys()
+ def keys(self):
+ return self.tconfig_map.keys()
+ 
+ def has_key(self, val):
+ return self.tconfig_map.has_key(val)
 
 
-rcParams = RcParamsWrapper()
+config_file = cutils.get_config_file(tconfig=True)
+old_config_file = cutils.get_config_file(tconfig=False)
+if os.path.exists(old_config_file) and not os.path.exists(config_file):
+ CONVERT = True
+else: CONVERT = False
+configManager = TConfigManager(MPLConfig,
+ cutils.get_config_file(tconfig=True),
+ filePriority=True)
+mplConfig = configManager.tconf
+mplConfigDefault = MPLConfig()
 
+# TODO: move into traits validation
+mplConfig.backend.ps.distiller.use = \
+ checkdep.ps_distiller(mplConfig.backend.ps.distiller.use)
+mplConfig.text.usetex = checkdep.usetex(mplConfig.text.usetex)
+
+def save_config():
+ """Save mplConfig customizations to current matplotlib.conf
+ """
+ configManager.write()
+
+rcParams = RcParamsWrapper(mplConfig)
+rcParamsDefault = RcParamsWrapper(mplConfigDefault)
+
 # convert old matplotlibrc to new matplotlib.conf
 if CONVERT:
 from rcparams import rcParams as old_rcParams
@@ -479,6 +490,10 @@
 print '%s converted to %s'%(cutils.get_config_file(tconfig=False),
 config_file)
 
+def rcdefaults():
+ mplConfig = MPLConfig()
+ rcParams = RcParamsWrapper(mplConfig)
+
 ##############################################################################
 # Simple testing
 ##############################################################################
Modified: trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc
===================================================================
--- trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc	2007年07月30日 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc	2007年07月30日 17:41:14 UTC (rev 3632)
@@ -34,7 +34,6 @@
 #interactive : False # see http://matplotlib.sourceforge.net/interactive.html
 #toolbar : toolbar2 # None | classic | toolbar2
 #timezone : UTC # a pytz timezone string, eg US/Central or Europe/Paris
-#units : False
 
 # Where your matplotlib data lives if you installed to a non-default
 # location. This is where the matplotlib fonts, bitmaps, etc reside
@@ -197,7 +196,6 @@
 #grid.linewidth : 0.5 # in points
 
 ### Legend
-#legend.loc : upper right
 #legend.isaxes : True
 #legend.numpoints : 2 # the number of points in the legend line
 #legend.fontsize : 14
@@ -245,7 +243,6 @@
 #savefig.dpi : 100 # figure dots per inch
 #savefig.facecolor : white # figure facecolor when saving
 #savefig.edgecolor : white # figure edgecolor when saving
-#savefig.orientation: portrait
 
 #cairo.format : png # png, ps, pdf, svg
 
@@ -267,8 +264,6 @@
 #pdf.compression : 6 # integer from 0 to 9
 # 0 disables compression (good for debugging)
 #pdf.fonttype : 3 # Output Type 3 (Type3) or Type 42 (TrueType)
-#pdf.inheritcolor : False
-#pdf.use14corefonts : False
 
 # svg backend params
 #svg.image_inline : True # write raster image data directly into the svg file
Modified: trunk/matplotlib/setup.py
===================================================================
--- trunk/matplotlib/setup.py	2007年07月30日 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/setup.py	2007年07月30日 17:41:14 UTC (rev 3632)
@@ -130,7 +130,7 @@
 'matplotlib.numerix.linear_algebra',
 'matplotlib.numerix.random_array',
 'matplotlib.numerix.fft',
-
+ 'matplotlib.config'
 ]
 
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年07月30日 16:41:56
Revision: 3631
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3631&view=rev
Author: mdboom
Date: 2007年07月30日 09:41:53 -0700 (2007年7月30日)
Log Message:
-----------
Major refactor to separate out backend-specific stuff from
fontset-specific stuff. What used to be the Fonts class heirarchy is
now both a Fonts heirarchy and MathtextBackend heirarchy. This should
be further improved in the future when the backends themselves are
refactored to be more consistent.
Now uses the multi-sized delimiters in the BaKoMa fonts. This
prevents the square root symbol from getting overly wide as it gets
tall. (As auto-sized parens, brackets and braces etc.)
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/_mathtext_data.py
 trunk/matplotlib/lib/matplotlib/mathtext.py
Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/_mathtext_data.py	2007年07月30日 07:03:47 UTC (rev 3630)
+++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py	2007年07月30日 16:41:53 UTC (rev 3631)
@@ -14,8 +14,9 @@
 print charcode, glyphind
 """
 
-latex_to_bakoma = {
+from sets import Set
 
+latex_to_bakoma = {
 r'\oint' : ('cmex10', 45),
 r'\bigodot' : ('cmex10', 50),
 r'\bigoplus' : ('cmex10', 55),
@@ -29,13 +30,7 @@
 r'\bigwedge' : ('cmex10', 4),
 r'\bigvee' : ('cmex10', 37),
 r'\coprod' : ('cmex10', 42),
- r'\Leftbracket' : ('cmex10', 29),
- r'\Rightbracket' : ('cmex10', 61),
- r'\Leftbrace' : ('cmex10', 43),
- r'\Rightbrace' : ('cmex10', 16),
 r'\sqrt' : ('cmex10', 48),
- r'\Sqrt' : ('cmex10', 21),
- r'\SQRT' : ('cmex10', 53),
 r'\leftbrace' : ('cmex10', 92),
 r'{' : ('cmex10', 92),
 r'\{' : ('cmex10', 92),
@@ -44,16 +39,6 @@
 r'\}' : ('cmex10', 130),
 r'\leftangle' : ('cmex10', 97),
 r'\rightangle' : ('cmex10', 64),
- r'\Leftparen' : ('cmex10', 112),
- r'\Rightparen' : ('cmex10', 81),
- r'\LEFTparen' : ('cmex10', 119),
- r'\RIGHTparen' : ('cmex10', 87),
- r'\LEFTbracket' : ('cmex10', 125),
- r'\RIGHTbracket' : ('cmex10', 93),
- r'\LEFTbrace' : ('cmex10', 70),
- r'\RIGHTbrace' : ('cmex10', 107),
- r'\LEFTangle' : ('cmex10', 76),
- r'\RIGHTangle' : ('cmex10', 113),
 
 r'\omega' : ('cmmi10', 29),
 r'\varepsilon' : ('cmmi10', 20),
@@ -144,15 +129,15 @@
 
 # these are mathml names, I think. I'm just using them for the
 # tex methods noted
- r'\circumflexaccent' : ('cmr10', 124), # for \hat
- r'\combiningbreve' : ('cmr10', 81), # for \breve
- r'\combiningoverline' : ('cmr10', 131), # for \bar
- r'\combininggraveaccent' : ('cmr10', 114), # for \grave
- r'\combiningacuteaccent' : ('cmr10', 63), # for \accute
- r'\combiningdiaeresis' : ('cmr10', 91), # for \ddot
- r'\combiningtilde' : ('cmr10', 75), # for \tilde
+ r'\circumflexaccent' : ('cmr10', 124), # for \hat
+ r'\combiningbreve' : ('cmr10', 81), # for \breve
+ r'\combiningoverline' : ('cmr10', 131), # for \bar
+ r'\combininggraveaccent' : ('cmr10', 114), # for \grave
+ r'\combiningacuteaccent' : ('cmr10', 63), # for \accute
+ r'\combiningdiaeresis' : ('cmr10', 91), # for \ddot
+ r'\combiningtilde' : ('cmr10', 75), # for \tilde
 r'\combiningrightarrowabove' : ('cmmi10', 110), # for \vec
- r'\combiningdotabove' : ('cmr10', 26), # for \dot
+ r'\combiningdotabove' : ('cmr10', 26), # for \dot
 
 r'\leftarrow' : ('cmsy10', 10),
 r'\uparrow' : ('cmsy10', 25),
@@ -199,8 +184,6 @@
 r'\rceil' : ('cmsy10', 81),
 r'\lbrace' : ('cmsy10', 92),
 r'\rbrace' : ('cmsy10', 105),
- r'\langle' : ('cmsy10', 3),
- r'\rangle' : ('cmsy10', 88),
 r'\mid' : ('cmsy10', 47),
 r'\vert' : ('cmsy10', 47),
 r'\Vert' : ('cmsy10', 44),
@@ -258,417 +241,6 @@
 r'\spadesuit' : ('cmsy10', 7),
 }
 
-# the kerning dictionary in design space units
-cmkern = {
- 'cmr10' :
- {
- ('A', 't') : -0.027779,
- ('A', 'C') : -0.027779,
- ('A', 'O') : -0.027779,
- ('A', 'G') : -0.027779,
- ('A', 'U') : -0.027779,
- ('A', 'Q') : -0.027779,
- ('A', 'T') : -0.083334,
- ('A', 'Y') : -0.083334,
- ('A', 'V') : -0.111112,
- ('A', 'W') : -0.111112,
- ('D', 'X') : -0.027779,
- ('D', 'W') : -0.027779,
- ('D', 'A') : -0.027779,
- ('D', 'V') : -0.027779,
- ('D', 'Y') : -0.027779,
- ('F', 'o') : -0.083334,
- ('F', 'e') : -0.083334,
- ('F', 'u') : -0.083334,
- ('F', 'r') : -0.083334,
- ('F', 'a') : -0.083334,
- ('F', 'A') : -0.111112,
- ('F', 'O') : -0.027779,
- ('F', 'C') : -0.027779,
- ('F', 'G') : -0.027779,
- ('F', 'Q') : -0.027779,
- ('I', 'I') : 0.027779,
- ('K', 'O') : -0.027779,
- ('K', 'C') : -0.027779,
- ('K', 'G') : -0.027779,
- ('K', 'Q') : -0.027779,
- ('L', 'T') : -0.083334,
- ('L', 'Y') : -0.083334,
- ('L', 'V') : -0.111112,
- ('L', 'W') : -0.111112,
- ('O', 'X') : -0.027779,
- ('O', 'W') : -0.027779,
- ('O', 'A') : -0.027779,
- ('O', 'V') : -0.027779,
- ('O', 'Y') : -0.027779,
- ('P', 'A') : -0.083334,
- ('P', 'o') : -0.027779,
- ('P', 'e') : -0.027779,
- ('P', 'a') : -0.027779,
- ('R', 't') : -0.027779,
- ('R', 'C') : -0.027779,
- ('R', 'O') : -0.027779,
- ('R', 'G') : -0.027779,
- ('R', 'U') : -0.027779,
- ('R', 'Q') : -0.027779,
- ('R', 'T') : -0.083334,
- ('R', 'Y') : -0.083334,
- ('R', 'V') : -0.111112,
- ('R', 'W') : -0.111112,
- ('T', 'y') : -0.027779,
- ('T', 'e') : -0.083334,
- ('T', 'o') : -0.083334,
- ('T', 'r') : -0.083334,
- ('T', 'a') : -0.083334,
- ('T', 'A') : -0.083334,
- ('T', 'u') : -0.083334,
- ('V', 'o') : -0.083334,
- ('V', 'e') : -0.083334,
- ('V', 'u') : -0.083334,
- ('V', 'r') : -0.083334,
- ('V', 'a') : -0.083334,
- ('V', 'A') : -0.111112,
- ('V', 'O') : -0.027779,
- ('V', 'C') : -0.027779,
- ('V', 'G') : -0.027779,
- ('V', 'Q') : -0.027779,
- ('W', 'o') : -0.083334,
- ('W', 'e') : -0.083334,
- ('W', 'u') : -0.083334,
- ('W', 'r') : -0.083334,
- ('W', 'a') : -0.083334,
- ('W', 'A') : -0.111112,
- ('W', 'O') : -0.027779,
- ('W', 'C') : -0.027779,
- ('W', 'G') : -0.027779,
- ('W', 'Q') : -0.027779,
- ('X', 'O') : -0.027779,
- ('X', 'C') : -0.027779,
- ('X', 'G') : -0.027779,
- ('X', 'Q') : -0.027779,
- ('Y', 'e') : -0.083334,
- ('Y', 'o') : -0.083334,
- ('Y', 'r') : -0.083334,
- ('Y', 'a') : -0.083334,
- ('Y', 'A') : -0.083334,
- ('Y', 'u') : -0.083334,
- ('a', 'v') : -0.027779,
- ('a', 'j') : 0.055555,
- ('a', 'y') : -0.027779,
- ('a', 'w') : -0.027779,
- ('b', 'e') : 0.027779,
- ('b', 'o') : 0.027779,
- ('b', 'x') : -0.027779,
- ('b', 'd') : 0.027779,
- ('b', 'c') : 0.027779,
- ('b', 'q') : 0.027779,
- ('b', 'v') : -0.027779,
- ('b', 'j') : 0.055555,
- ('b', 'y') : -0.027779,
- ('b', 'w') : -0.027779,
- ('c', 'h') : -0.027779,
- ('c', 'k') : -0.027779,
- ('g', 'j') : 0.027779,
- ('h', 't') : -0.027779,
- ('h', 'u') : -0.027779,
- ('h', 'b') : -0.027779,
- ('h', 'y') : -0.027779,
- ('h', 'v') : -0.027779,
- ('h', 'w') : -0.027779,
- ('k', 'a') : -0.055555,
- ('k', 'e') : -0.027779,
- ('k', 'a') : -0.027779,
- ('k', 'o') : -0.027779,
- ('k', 'c') : -0.027779,
- ('m', 't') : -0.027779,
- ('m', 'u') : -0.027779,
- ('m', 'b') : -0.027779,
- ('m', 'y') : -0.027779,
- ('m', 'v') : -0.027779,
- ('m', 'w') : -0.027779,
- ('n', 't') : -0.027779,
- ('n', 'u') : -0.027779,
- ('n', 'b') : -0.027779,
- ('n', 'y') : -0.027779,
- ('n', 'v') : -0.027779,
- ('n', 'w') : -0.027779,
- ('o', 'e') : 0.027779,
- ('o', 'o') : 0.027779,
- ('o', 'x') : -0.027779,
- ('o', 'd') : 0.027779,
- ('o', 'c') : 0.027779,
- ('o', 'q') : 0.027779,
- ('o', 'v') : -0.027779,
- ('o', 'j') : 0.055555,
- ('o', 'y') : -0.027779,
- ('o', 'w') : -0.027779,
- ('p', 'e') : 0.027779,
- ('p', 'o') : 0.027779,
- ('p', 'x') : -0.027779,
- ('p', 'd') : 0.027779,
- ('p', 'c') : 0.027779,
- ('p', 'q') : 0.027779,
- ('p', 'v') : -0.027779,
- ('p', 'j') : 0.055555,
- ('p', 'y') : -0.027779,
- ('p', 'w') : -0.027779,
- ('t', 'y') : -0.027779,
- ('t', 'w') : -0.027779,
- ('u', 'w') : -0.027779,
- ('v', 'a') : -0.055555,
- ('v', 'e') : -0.027779,
- ('v', 'a') : -0.027779,
- ('v', 'o') : -0.027779,
- ('v', 'c') : -0.027779,
- ('w', 'e') : -0.027779,
- ('w', 'a') : -0.027779,
- ('w', 'o') : -0.027779,
- ('w', 'c') : -0.027779,
- ('y', 'o') : -0.027779,
- ('y', 'e') : -0.027779,
- ('y', 'a') : -0.027779,
- },
- 'cmex10' : {},
- 'cmtt10' : {},
- 'cmsy10' : {},
- 'cmmi10' :
- {
- ('9', 'A') : -0.055555,
- ('9', 'M') : -0.055555,
- ('9', 'N') : -0.055555,
- ('9', 'Y') : 0.055555,
- ('9', 'Z') : -0.055555,
- ('d', 'Y') : 0.055555,
- ('d', 'Z') : -0.055555,
- ('d', 'j') : -0.111112,
- ('d', 'f') : -0.166667,
- },
- }
-ams_type1 = {
- r'\Leftbracket' : ( 'cmex10', '02'),
- r'\Rightbracket' : ( 'cmex10', '03'),
- r'\Leftbrace' : ( 'cmex10', '08'),
- r'\leftbrace' : ( 'cmex10', '08'),
- '{' : ( 'cmex10', '08'),
- r'\Rightbrace' : ( 'cmex10', '09'),
- r'\rightbrace' : ( 'cmex10', '09'),
- '}' : ( 'cmex10', '09'),
- r'\Leftparen' : ( 'cmex10', '10'),
- r'\Rightparen' : ( 'cmex10', '11'),
- r'\LEFTparen' : ( 'cmex10', '20'),
- r'\RIGHTparen' : ( 'cmex10', '21'),
- r'\LEFTbracket' : ( 'cmex10', '22'),
- r'\RIGHTbracket' : ( 'cmex10', '23'),
- '6' : ( 'cmex10', '26'),
- '(' : ( 'cmex10', '28'),
- r'\LEFTbrace' : ( 'cmex10', '28'),
- r'\leftparen' : ( 'cmex10', '28'),
- ')' : ( 'cmex10', '29'),
- r'\RIGHTbrace' : ( 'cmex10', '29'),
- r'\rightparen' : ( 'cmex10', '29'),
- r'\LEFTangle' : ( 'cmex10', '2A'),
- '+' : ( 'cmex10', '2B'),
- '0' : ( 'cmex10', '30'),
- '1' : ( 'cmex10', '31'),
- '2' : ( 'cmex10', '32'),
- '3' : ( 'cmex10', '33'),
- '4' : ( 'cmex10', '34'),
- '5' : ( 'cmex10', '35'),
- '7' : ( 'cmex10', '37'),
- '8' : ( 'cmex10', '38'),
- '9' : ( 'cmex10', '39'),
- ':' : ( 'cmex10', '3A'),
- ';' : ( 'cmex10', '3B'),
- '=' : ( 'cmex10', '3D'),
- r'\leftangle' : ( 'cmex10', '44'),
- r'\rightangle' : ( 'cmex10', '45'),
- r'\oint' : ( 'cmex10', '49'),
- r'\bigodot' : ( 'cmex10', '4B'),
- r'\bigoplus' : ( 'cmex10', '4D'),
- r'\bigotimes' : ( 'cmex10', '4F'),
- r'\sum' : ( 'cmex10', '58'),
- r'\prod' : ( 'cmex10', '59'),
- r'\int' : ( 'cmex10', '5A'),
- '[' : ( 'cmex10', '5B'),
- r'\bigcup' : ( 'cmex10', '5B'),
- r'\leftbracket' : ( 'cmex10', '5B'),
- r'\bigcap' : ( 'cmex10', '5C'),
- r'\biguplus' : ( 'cmex10', '5D'),
- r'\rightbracket' : ( 'cmex10', '5D'),
- ']' : ( 'cmex10', '5D'),
- r'\bigwedge' : ( 'cmex10', '5E'),
- r'\bigvee' : ( 'cmex10', '5F'),
- r'\coprod' : ( 'cmex10', '61'),
- r'\Sqrt' : ( 'cmex10', '70'),
- r'\sqrt' : ( 'cmex10', '70'),
- r'\SQRT' : ( 'cmex10', '72'),
- r'\Sigma' : ( 'cmmi10', '06'),
- r'\Upsilon' : ( 'cmmi10', '07'),
- r'\Phi' : ( 'cmmi10', '08'),
- r'\Psi' : ( 'cmmi10', '09'),
- r'\alpha' : ( 'cmmi10', '0B'),
- r'\beta' : ( 'cmmi10', '0C'),
- r'\gamma' : ( 'cmmi10', '0D'),
- r'\delta' : ( 'cmmi10', '0E'),
- r'\epsilon' : ( 'cmmi10', '0F'),
- r'\zeta' : ( 'cmmi10', '10'),
- r'\eta' : ( 'cmmi10', '11'),
- r'\theta' : ( 'cmmi10', '12'),
- r'\iota' : ( 'cmmi10', '13'),
- r'\lambda' : ( 'cmmi10', '15'),
- r'\mu' : ( 'cmmi10', '16'),
- r'\nu' : ( 'cmmi10', '17'),
- r'\xi' : ( 'cmmi10', '18'),
- r'\pi' : ( 'cmmi10', '19'),
- r'\kappa' : ( 'cmmi10', '19'),
- r'\rho' : ( 'cmmi10', '1A'),
- r'\sigma' : ( 'cmmi10', '1B'),
- r'\tau' : ( 'cmmi10', '1C'),
- r'\upsilon' : ( 'cmmi10', '1D'),
- r'\phi' : ( 'cmmi10', '1E'),
- r'\chi' : ( 'cmmi10', '1F'),
- r'\psi' : ( 'cmmi10', '20'),
- r'\omega' : ( 'cmmi10', '21'),
- r'\varepsilon' : ( 'cmmi10', '22'),
- r'\vartheta' : ( 'cmmi10', '23'),
- r'\varrho' : ( 'cmmi10', '25'),
- r'\varsigma' : ( 'cmmi10', '26'),
- r'\varphi' : ( 'cmmi10', '27'),
- r'\leftharpoonup' : ( 'cmmi10', '28'),
- r'\leftharpoondown' : ( 'cmmi10', '29'),
- r'\rightharpoonup' : ( 'cmmi10', '2A'),
- r'\rightharpoondown' : ( 'cmmi10', '2B'),
- r'\triangleright' : ( 'cmmi10', '2E'),
- r'\triangleleft' : ( 'cmmi10', '2F'),
- '.' : ( 'cmmi10', '3A'),
- ',' : ( 'cmmi10', '3B'),
- '<' : ( 'cmmi10', '3C'),
- '/' : ( 'cmmi10', '3D'),
- '>' : ( 'cmmi10', '3E'),
- r'\flat' : ( 'cmmi10', '5B'),
- r'\natural' : ( 'cmmi10', '5C'),
- r'\sharp' : ( 'cmmi10', '5D'),
- r'\smile' : ( 'cmmi10', '5E'),
- r'\frown' : ( 'cmmi10', '5F'),
- r'\ell' : ( 'cmmi10', '60'),
- r'\imath' : ( 'cmmi10', '7B'),
- r'\jmath' : ( 'cmmi10', '7C'),
- r'\wp' : ( 'cmmi10', '7D'),
- r'\Gamma' : ( 'cmr10', '00'),
- r'\Delta' : ( 'cmr10', '01'),
- r'\Theta' : ( 'cmr10', '02'),
- r'\Lambda' : ( 'cmr10', '03'),
- r'\Xi' : ( 'cmr10', '04'),
- r'\Pi' : ( 'cmr10', '05'),
- r'\Omega' : ( 'cmr10', '0A'),
- '-' : ( 'cmsy10', '00'),
- r'\cdot' : ( 'cmsy10', '01'),
- r'\times' : ( 'cmsy10', '02'),
- '*' : ( 'cmsy10', '03'),
- r'\ast' : ( 'cmsy10', '03'),
- r'\div' : ( 'cmsy10', '04'),
- r'\diamond' : ( 'cmsy10', '05'),
- r'\pm' : ( 'cmsy10', '06'),
- r'\mp' : ( 'cmsy10', '07'),
- r'\oplus' : ( 'cmsy10', '08'),
- r'\ominus' : ( 'cmsy10', '09'),
- r'\otimes' : ( 'cmsy10', '0A'),
- r'\oslash' : ( 'cmsy10', '0B'),
- r'\odot' : ( 'cmsy10', '0C'),
- r'\bigcirc' : ( 'cmsy10', '0D'),
- r'\circ' : ( 'cmsy10', '0E'),
- r'\bullet' : ( 'cmsy10', '0F'),
- r'\simeq' : ( 'cmsy10', '10'),
- r'\asymp' : ( 'cmsy10', '11'),
- r'\subseteq' : ( 'cmsy10', '12'),
- r'\supseteq' : ( 'cmsy10', '13'),
- r'\leq' : ( 'cmsy10', '14'),
- r'\geq' : ( 'cmsy10', '15'),
- r'\preceq' : ( 'cmsy10', '16'),
- r'\succeq' : ( 'cmsy10', '17'),
- r'\sim' : ( 'cmsy10', '18'),
- r'\approx' : ( 'cmsy10', '19'),
- r'\subset' : ( 'cmsy10', '1A'),
- r'\supset' : ( 'cmsy10', '1B'),
- r'\ll' : ( 'cmsy10', '1C'),
- r'\gg' : ( 'cmsy10', '1D'),
- r'\prec' : ( 'cmsy10', '1E'),
- r'\succ' : ( 'cmsy10', '1F'),
- r'\rightarrow' : ( 'cmsy10', '20'),
- r'\leftarrow' : ( 'cmsy10', '21'),
- r'\uparrow' : ( 'cmsy10', '22'),
- r'\downarrow' : ( 'cmsy10', '23'),
- r'\leftrightarrow' : ( 'cmsy10', '24'),
- r'\nearrow' : ( 'cmsy10', '25'),
- r'\searrow' : ( 'cmsy10', '26'),
- r'\Leftarrow' : ( 'cmsy10', '28'),
- r'\Rightarrow' : ( 'cmsy10', '29'),
- r'\Uparrow' : ( 'cmsy10', '2A'),
- r'\Downarrow' : ( 'cmsy10', '2B'),
- r'\Leftrightarrow' : ( 'cmsy10', '2C'),
- r'\nwarrow' : ( 'cmsy10', '2D'),
- r'\swarrow' : ( 'cmsy10', '2E'),
- r'\propto' : ( 'cmsy10', '2F'),
- r'\prime' : ( 'cmsy10', '30'),
- r'\infty' : ( 'cmsy10', '31'),
- r'\in' : ( 'cmsy10', '32'),
- r'\ni' : ( 'cmsy10', '33'),
- r'\bigtriangleup' : ( 'cmsy10', '34'),
- r'\bigtriangledown' : ( 'cmsy10', '35'),
- r'\slash' : ( 'cmsy10', '36'),
- r'\forall' : ( 'cmsy10', '38'),
- r'\exists' : ( 'cmsy10', '39'),
- r'\neg' : ( 'cmsy10', '3A'),
- r'\emptyset' : ( 'cmsy10', '3B'),
- r'\Re' : ( 'cmsy10', '3C'),
- r'\Im' : ( 'cmsy10', '3D'),
- r'\top' : ( 'cmsy10', '3E'),
- r'\bot' : ( 'cmsy10', '3F'),
- r'\aleph' : ( 'cmsy10', '40'),
- r'\cup' : ( 'cmsy10', '5B'),
- r'\cap' : ( 'cmsy10', '5C'),
- r'\uplus' : ( 'cmsy10', '5D'),
- r'\wedge' : ( 'cmsy10', '5E'),
- r'\vee' : ( 'cmsy10', '5F'),
- r'\vdash' : ( 'cmsy10', '60'),
- r'\dashv' : ( 'cmsy10', '61'),
- r'\lfloor' : ( 'cmsy10', '62'),
- r'\rfloor' : ( 'cmsy10', '63'),
- r'\lceil' : ( 'cmsy10', '64'),
- r'\rceil' : ( 'cmsy10', '65'),
- r'\lbrace' : ( 'cmsy10', '66'),
- r'\rbrace' : ( 'cmsy10', '67'),
- r'\langle' : ( 'cmsy10', '68'),
- r'\rangle' : ( 'cmsy10', '69'),
- r'\mid' : ( 'cmsy10', '6A'),
- r'\vert' : ( 'cmsy10', '6A'),
- r'\Vert' : ( 'cmsy10', '6B'),
- r'\updownarrow' : ( 'cmsy10', '6C'),
- r'\Updownarrow' : ( 'cmsy10', '6D'),
- r'\backslash' : ( 'cmsy10', '6E'),
- r'\wr' : ( 'cmsy10', '6F'),
- r'\nabla' : ( 'cmsy10', '72'),
- r'\sqcup' : ( 'cmsy10', '74'),
- r'\sqcap' : ( 'cmsy10', '75'),
- r'\sqsubseteq' : ( 'cmsy10', '76'),
- r'\sqsupseteq' : ( 'cmsy10', '77'),
- r'\S' : ( 'cmsy10', '78'),
- r'\dag' : ( 'cmsy10', '79'),
- r'\ddag' : ( 'cmsy10', '7A'),
- r'\P' : ( 'cmsy10', '7B'),
- r'\clubsuit' : ( 'cmsy10', '7C'),
- r'\diamondsuit' : ( 'cmsy10', '7D'),
- r'\heartsuit' : ( 'cmsy10', '7E'),
- r'\spadesuit' : ( 'cmsy10', '7F'),
-}
-
-"""
-no mlname for \RIGHTangle
-no type1 key \equiv # could not find in ASM
-no type1 key \kappa # could not find kappa
-no type1 key \RIGHTangle # could not find
-"""
-
 latex_to_standard = {
 r'\cong' : ('psyr', 64),
 r'\Delta' : ('psyr', 68),
@@ -757,17 +329,60 @@
 r'\langle' : ('psyr', 225),
 r'\Sigma' : ('psyr', 229),
 r'\sum' : ('psyr', 229),
- # these are mathml names, I think. I'm just using them for the
- # tex methods noted
- r'\circumflexaccent' : ('pncri8a', 124), # for \hat
- r'\combiningbreve' : ('pncri8a', 81), # for \breve
- r'\combininggraveaccent' : ('pncri8a', 114), # for \grave
- r'\combiningacuteaccent' : ('pncri8a', 63), # for \accute
- r'\combiningdiaeresis' : ('pncri8a', 91), # for \ddot
- r'\combiningtilde' : ('pncri8a', 75), # for \tilde
+ r'\forall' : ('psyr', 34),
+ r'\exists' : ('psyr', 36),
+ r'\lceil' : ('psyr', 233),
+ r'\lbrace' : ('psyr', 123),
+ r'\Psi' : ('psyr', 89),
+ r'\bot' : ('psyr', 0136),
+ r'\Omega' : ('psyr', 0127),
+ r'\leftbracket' : ('psyr', 0133),
+ r'\rightbracket' : ('psyr', 0135),
+ r'\leftbrace' : ('psyr', 123),
+ r'\leftparen' : ('psyr', 050),
+ r'\prime' : ('psyr', 0242),
+ r'\sharp' : ('psyr', 043),
+ r'\slash' : ('psyr', 057),
+ r'\Lamda' : ('psyr', 0114),
+ r'\neg' : ('psyr', 0330),
+ r'\Upsilon' : ('psyr', 0241),
+ r'\rightbrace' : ('psyr', 0175),
+ r'\rfloor' : ('psyr', 0373),
+ r'\lambda' : ('psyr', 0154),
+ r'\to' : ('psyr', 0256),
+ r'\Xi' : ('psyr', 0130),
+ r'\emptyset' : ('psyr', 0306),
+ r'\lfloor' : ('psyr', 0353),
+ r'\rightparen' : ('psyr', 051),
+ r'\rceil' : ('psyr', 0371),
+ r'\ni' : ('psyr', 047),
+ r'\epsilon' : ('psyr', 0145),
+ r'\Theta' : ('psyr', 0121),
+ r'\langle' : ('psyr', 0341),
+ r'\leftangle' : ('psyr', 0341),
+ r'\rangle' : ('psyr', 0361),
+ r'\rightangle' : ('psyr', 0361),
+ r'\rbrace' : ('psyr', 0175),
+ r'\circ' : ('psyr', 0260),
+ r'\diamond' : ('psyr', 0340),
+ r'\mu' : ('psyr', 0155),
+ r'\mid' : ('psyr', 0352),
+ r'\imath' : ('pncri8a', 105),
+ r'\%' : ('pncr8a', 37),
+ r'\$' : ('pncr8a', 36),
+ r'\{' : ('pncr8a', 123),
+ r'\}' : ('pncr8a', 125),
+ r'\backslash' : ('pncr8a', 92),
+ r'\ast' : ('pncr8a', 42),
+ 
+ r'\circumflexaccent' : ('pncri8a', 124), # for \hat
+ r'\combiningbreve' : ('pncri8a', 81), # for \breve
+ r'\combininggraveaccent' : ('pncri8a', 114), # for \grave
+ r'\combiningacuteaccent' : ('pncri8a', 63), # for \accute
+ r'\combiningdiaeresis' : ('pncri8a', 91), # for \ddot
+ r'\combiningtilde' : ('pncri8a', 75), # for \tilde
 r'\combiningrightarrowabove' : ('pncri8a', 110), # for \vec
- r'\combiningdotabove' : ('pncri8a', 26), # for \dot
- r'\imath' : ('pncri8a', 105)
+ r'\combiningdotabove' : ('pncri8a', 26), # for \dot
 }
 
 # Automatically generated.
@@ -2214,7 +1829,7 @@
 'updownarrows': 8645,
 'heartsuit': 9825,
 'trianglelefteq': 8884,
-'ddagger': 8225,
+'ddag': 8225,
 'sqsubseteq': 8849,
 'mapsfrom': 8612,
 'boxbar': 9707,
@@ -2516,7 +2131,7 @@
 'succcurlyeq': 8829,
 'gamma': 947,
 'scrR': 8475,
-'dagger': 8224,
+'dag': 8224,
 'thickspace': 8197,
 'frakZ': 8488,
 'lessdot': 8918,
@@ -2589,7 +2204,39 @@
 'divideontimes': 8903,
 'lbrack': 91,
 'textquotedblright': 8221,
-'Colon': 8759}
+'Colon': 8759,
+'%': 37,
+'$': 36,
+'{': 123,
+'}': 125,
+'imath': 0xfd, 
+'circumflexaccent' : 770,
+'combiningbreve' : 774,
+'combiningoverline' : 772,
+'combininggraveaccent' : 768,
+'combiningacuteaccent' : 764,
+'combiningdiaeresis' : 776,
+'combiningtilde' : 771,
+'combiningrightarrowabove' : 8407,
+'combiningdotabove' : 775,
+'to': 8594,
+'succeq': 8829,
+'emptyset': 8709,
+'leftparen': 40,
+'rightparen': 41,
+'bigoplus': 10753,
+'leftangle': 10216,
+'rightangle': 10217,
+'leftbrace': 124,
+'rightbrace': 125,
+'jmath': 567,
+'bigodot': 10752,
+'preceq': 8828,
+'biguplus': 10756,
+'epsilon': 949,
+'vartheta': 977,
+'bigotimes': 10754 
+}
 
 uni2tex = dict([(v,k) for k,v in tex2uni.items()])
 
@@ -2692,7 +2339,7 @@
 'updownarrows': 'uni21C5',
 'heartsuit': 'uni2661',
 'trianglelefteq': 'uni22B4',
-'ddagger': 'daggerdbl',
+'ddag': 'daggerdbl',
 'sqsubseteq': 'uni2291',
 'mapsfrom': 'uni21A4',
 'boxbar': 'uni25EB',
@@ -2994,7 +2641,7 @@
 'succcurlyeq': 'uni227D',
 'gamma': 'uni03B3',
 'scrR': 'uni211B',
-'dagger': 'dagger',
+'dag': 'dagger',
 'thickspace': 'uni2005',
 'frakZ': 'uni2128',
 'lessdot': 'uni22D6',
@@ -3070,4 +2717,3 @@
 'Colon': 'uni2237'}
 
 type12tex = dict([(v,k) for k,v in tex2type1.items()])
-
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py	2007年07月30日 07:03:47 UTC (rev 3630)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py	2007年07月30日 16:41:53 UTC (rev 3631)
@@ -131,7 +131,9 @@
 from __future__ import division
 import os, sys
 from cStringIO import StringIO
+from math import floor, ceil
 from sets import Set
+from unicodedata import category
 from warnings import warn
 
 from matplotlib import verbose
@@ -146,7 +148,7 @@
 is_string_like
 from matplotlib.ft2font import FT2Font, KERNING_UNFITTED
 from matplotlib.font_manager import fontManager, FontProperties
-from matplotlib._mathtext_data import latex_to_bakoma, cmkern, \
+from matplotlib._mathtext_data import latex_to_bakoma, \
 latex_to_standard, tex2uni, type12uni, tex2type1, uni2type1
 from matplotlib import get_data_path, rcParams
 
@@ -164,14 +166,6 @@
 ##############################################################################
 # FONTS
 
-def font_open(filename):
- ext = filename.rsplit('.',1)[1]
- if ext == 'afm':
- return AFM(str(filename))
- else:
- return FT2Font(str(filename))
-
-
 def get_unicode_index(symbol):
 """get_unicode_index(symbol) -> integer
 
@@ -187,10 +181,6 @@
 try:# Is symbol a TeX symbol (i.e. \alpha)
 return tex2uni[symbol.strip("\\")]
 except KeyError:
- pass
- try:# Is symbol a Type1 name (i.e. degree)? If not raise error
- return type12uni[symbol]
- except KeyError:
 message = """'%(symbol)s' is not a valid Unicode character or
 TeX/Type1 symbol"""%locals()
 raise ValueError, message
@@ -219,574 +209,473 @@
 # The user did not suply a valid symbol, show usage
 raise ValueError, get_type1_name.__doc__
 
+class MathtextBackend(object):
+ def __init__(self):
+ fonts_object = None
 
-class Fonts:
- """
- An abstract base class for fonts that want to render mathtext
+ def set_canvas_size(self, w, h):
+ 'Dimension the drawing canvas; may be a noop'
+ self.width = w
+ self.height = h
 
- The class must be able to take symbol keys and font file names and
- return the character metrics as well as do the drawing
- """
- 
- def get_kern(self, facename, symleft, symright, fontsize, dpi):
- """
- Get the kerning distance for font between symleft and symright.
+ def render_glyph(self, ox, oy, info):
+ raise NotImplementedError()
 
- facename is one of tt, it, rm, cal or None
+ def render_filled_rect(self, x1, y1, x2, y2):
+ raise NotImplementedError()
 
- sym is a single symbol(alphanum, punct) or a special symbol
- like \sigma.
-
- """
- return 0
-
- def get_metrics(self, facename, sym, fontsize, dpi):
- """
- facename is one of tt, it, rm, cal or None
-
- sym is a single symbol(alphanum, punct) or a special symbol
- like \sigma.
-
- fontsize is in points
-
- Return object has attributes - see
- http://www.freetype.org/freetype2/docs/tutorial/step2.html for
- a pictoral representation of these attributes
-
- advance
- height
- width
- xmin, xmax, ymin, ymax - the ink rectangle of the glyph
- """
- raise NotImplementedError('Derived must override')
-
+ def get_results(self):
+ """Return a backend specific tuple of things to return to the
+ backend after all processing is done."""
+ raise NotImplementedError()
+ 
+class MathtextBackendAgg(MathtextBackend):
 def set_canvas_size(self, w, h):
- 'Dimension the drawing canvas; may be a noop'
- self.width, self.height = w, h
+ MathtextBackend.set_canvas_size(self, w, h)
+ for font in self.fonts_object.get_fonts():
+ font.set_bitmap_size(int(w), int(h))
 
- def render(self, ox, oy, facename, sym, fontsize, dpi):
- pass
+ def render_glyph(self, ox, oy, info):
+ info.font.draw_glyph_to_bitmap(
+ int(ox), int(oy - info.metrics.ymax), info.glyph)
 
 def render_rect_filled(self, x1, y1, x2, y2):
- pass
+ font = self.fonts_object.get_fonts()[0]
+ font.draw_rect_filled(
+ floor(max(0, x1 - 1)),
+ floor(y1),
+ ceil(max(x2 - 1, x1)),
+ ceil(max(y2 - 1, y1)))
+
+ def get_results(self):
+ return (self.width,
+ self.height,
+ self.fonts_object.get_fonts(),
+ self.fonts_object.get_used_characters())
 
- def get_used_characters(self):
- return {}
+class MathtextBackendPs(MathtextBackend):
+ def __init__(self):
+ self.pswriter = StringIO()
 
- 
-class DummyFonts(Fonts):
- 'dummy class for debugging parser'
- def get_metrics(self, font, sym, fontsize, dpi):
-
- metrics = Bunch(
- advance = 0,
- height = 0,
- width = 0,
- xmin = 0,
- xmax = 0,
- ymin = 0,
- ymax = 0,
- )
- return metrics
-
-
-class UnicodeFonts(Fonts):
- """An abstract base class for handling Unicode fonts.
-
-Specific terminology:
- * fontface: an FT2Font object, corresponding to a facename
- * facename: a string that defines the (type)face's name - 'rm', 'it' etc.
- * filename: a string that is used for generating a fontface object
- * symbol*: a single Unicode character or a TeX command,
- or to be precise, a TeX symbol command like \alpha (but not \frac) or
- even a Type1/PS name
- * filenamesd: a dict that maps the face's name to the filename:
- filenamesd = { 'cal' : 'fontnamecal.ext',
- 'rm' : 'fontnamerm.ext',
- 'tt' : 'fontnamett.ext',
- 'it' : 'fontnameit.ext',
- None : 'fontnamesmth.ext'}
- filenamesd should be declared as a class atribute
- * glyphdict: a dict used for caching of glyph specific data
- * fonts: a dict of facename -> fontface pairs
- * charmaps: a dict of facename -> charmap pairs. Charmap maps character
- codes to glyph indices
- * glyphmaps: a dict of facename -> glyphmap pairs. A glyphmap is an
- inverted charmap
- * output: a string in ['Agg','SVG','PS'], coresponding to the backends
- * index: Fontfile specific index of a glyph.
-
-"""
-
- # The path to the dir with the fontfiles
- def __init__(self, output='Agg'):
- self.facenames = self.filenamesd.keys()
- # Set the filenames to full path
- for facename in self.filenamesd:
- self.filenamesd[facename] = self.filenamesd[facename]
- if output:
- self.output = output
- # self.glyphdict[key] = facename, metrics, glyph, offset
- self.glyphdict = {}
-
- self.fonts = dict(
- [ (facename, font_open(self.filenamesd[facename])) for
- facename in self.facenames])
- # a dict of charcode -> glyphindex pairs
- self.charmaps = dict(
- [ (facename, self.fonts[facename].get_charmap())
- for facename in self.facenames])
- # a dict of glyphindex -> charcode pairs
- self.glyphmaps = {}
- for facename in self.facenames:
- charmap = self.charmaps[facename]
- self.glyphmaps[facename] = dict([(glyphind, charcode)
- for charcode, glyphind in charmap.items()])
- for fontface in self.fonts.values():
- fontface.clear()
- if self.output == 'SVG':
- # a list of "glyphs" we need to render this thing in SVG
- self.svg_glyphs=[]
-
- def set_canvas_size(self, w, h, pswriter=None):
- 'Dimension the drawing canvas; may be a noop'
- # self.width = int(w)
- # self.height = int(h)
- # I don't know why this was different than the PS version
- self.width = w
- self.height = h
- if pswriter:
- self.pswriter = pswriter
- else:
- for fontface in self.fonts.values():
- fontface.set_bitmap_size(int(w), int(h))
-
- def render(self, ox, oy, facename, symbol, fontsize, dpi):
- filename = self.filenamesd[facename]
- uniindex, metrics, glyph, offset = self._get_info(facename,
- symbol, fontsize, dpi)
- if self.output == 'SVG':
- oy += offset - 512/2048.*10.
- # TO-DO - make a method for it
- # This gets the name of the font.
- familyname = self.fonts[facename].get_sfnt()[(1,0,0,1)]
- thetext = unichr(uniindex)
- thetext.encode('utf-8')
- self.svg_glyphs.append((familyname, fontsize, thetext, ox, oy,
- metrics))
- elif self.output == 'PS':
- # This should be changed to check for math mode or smth.
- #if filename == 'cmex10.ttf':
- # oy += offset - 512/2048.*10.
-
- # Get the PS name of a glyph (his unicode integer code)
- # from the font object
- symbolname = self._get_glyph_name(uniindex, facename)
- psfontname = self.fonts[facename].postscript_name
- ps = """/%(psfontname)s findfont
+ def render_glyph(self, ox, oy, info):
+ oy = self.height - oy + info.offset
+ postscript_name = info.postscript_name
+ fontsize = info.fontsize
+ symbol_name = info.symbol_name
+ 
+ ps = """/%(postscript_name)s findfont
 %(fontsize)s scalefont
 setfont
 %(ox)f %(oy)f moveto
-/%(symbolname)s glyphshow
+/%(symbol_name)s glyphshow
 """ % locals()
- self.pswriter.write(ps)
- else: # Agg
- fontface = self.fonts[facename]
- fontface.draw_glyph_to_bitmap(
- int(ox), int(self.height - oy - metrics.ymax), glyph)
+ self.pswriter.write(ps)
 
- def get_metrics(self, facename, symbol, fontsize, dpi):
- uniindex, metrics, glyph, offset = \
- self._get_info(facename, symbol, fontsize, dpi)
- return metrics
+ def render_rect_filled(self, x1, y1, x2, y2):
+ ps = "%f %f %f %f rectfill" % (x1, self.height - y2, x2 - x1, y2 - y1)
+ self.pswriter.write(ps)
 
- # Methods that must be overridden for fonts that are not unicode aware
+ def get_results(self):
+ return (self.width,
+ self.height,
+ self.pswriter,
+ self.fonts_object.get_used_characters())
+ 
+class MathtextBackendPdf(MathtextBackend):
+ def __init__(self):
+ self.pswriter = []
+ 
+ def render_glyph(self, ox, oy, info):
+ filename = info.font.fname
+ oy = self.height - oy + info.offset
 
- def _get_unicode_index(self, symbol):
- return get_unicode_index(symbol)
+ self.pswriter.append(('glyph', ox, oy, filename, info.fontsize, info.num))
 
- def _get_glyph_name(self, uniindex, facename):
- """get_glyph_name(self, uniindex, facename) -> string
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.pswriter.append(('rect', x1, self.height - y2, x2 - x1, y2 - y1))
 
-Returns the name of the glyph directly from the font object.
+ def get_results(self):
+ return (self.width,
+ self.height,
+ self.pswriter,
+ self.fonts_object.get_used_characters())
 
-"""
- font = self.fonts[facename]
- glyphindex = self.glyphmaps[facename][uniindex]
- return font.get_glyph_name(glyphindex)
-
- def _get_info(self, facename, symbol, fontsize, dpi):
- 'load the facename, metrics and glyph'
- #print hex(index), symbol, filename, facename
- key = facename, symbol, fontsize, dpi
- tup = self.glyphdict.get(key)
- if tup is not None:
- return tup
- filename = self.filenamesd[facename]
- fontface = self.fonts[facename]
- fontface.set_size(fontsize, dpi)
- head = fontface.get_sfnt_table('head')
- uniindex = self._get_unicode_index(symbol)
- glyphindex = self.glyphmaps[facename][uniindex]
- glyph = fontface.load_char(uniindex)
- xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- # This is black magic to me (Edin)
- if filename == 'cmex10.ttf':
- if self.output == 'PS':
- offset = -(head['yMin']+512)/head['unitsPerEm']*10.
- else:
- offset = glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
- else:
- offset = 0.
- metrics = Bunch(
- advance = glyph.linearHoriAdvance/65536.0,
- height = glyph.height/64.0,
- width = glyph.width/64.0,
- xmin = xmin,
- xmax = xmax,
- ymin = ymin+offset,
- ymax = ymax+offset,
- )
- self.glyphdict[key] = uniindex, metrics, glyph, offset
- return self.glyphdict[key]
-
-
-class MyUnicodeFonts(UnicodeFonts):
- _initialized = False
+class MathtextBackendSvg(MathtextBackend):
 def __init__(self):
- if not MyUnicodeFonts._initialized:
- prop = FontProperties()
- prop.set_family('serif')
- self.rmfile = fontManager.findfont(prop)
+ self.svg_glyphs = []
+ self.svg_rects = []
+ 
+ def render_glyph(self, ox, oy, info):
+ oy = self.height - oy + info.offset
+ thetext = unichr(info.num)
+ self.svg_glyphs.append(
+ (info.font, info.fontsize, thetext, ox, oy, info.metrics))
 
- prop.set_family('fantasy')
- self.calfile = fontManager.findfont(prop)
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.svg_rects.append(
+ (x1, self.height - y1, x2 - x1, y2 - y1))
 
- prop.set_family('monospace')
- self.ttfile = fontManager.findfont(prop)
+ def get_results(self):
+ svg_elements = Bunch(svg_glyphs = self.svg_glyphs,
+ svg_rects = self.svg_rects)
+ return (self.width,
+ self.height,
+ svg_elements,
+ self.fonts_object.get_used_characters())
+ 
+class Fonts(object):
+ """
+ An abstract base class for fonts that want to render mathtext
 
- prop.set_family('serif')
- prop.set_style('italic')
- self.itfile = fontManager.findfont(prop)
- self.filenamesd = { 'rm' : self.rmfile,
- 'it' : self.itfile,
- 'cal' : self.calfile,
- 'tt' : self.ttfile,
- }
- MyUnicodeFonts._initialized = True
+ The class must be able to take symbol keys and font file names and
+ return the character metrics. It also delegates to a backend class
+ to do the actual drawing.
+ """
 
+ def __init__(self, default_font_prop, mathtext_backend):
+ """default_font_prop: A FontProperties object to use for the
+ default non-math font, or the base font for Unicode font
+ rendering.
+ mathtext_backend: A subclass of MathTextBackend used to
+ delegate the actual rendering."""
+ self.default_font_prop = default_font_prop
+ self.mathtext_backend = mathtext_backend
+ # Make these classes doubly-linked
+ self.mathtext_backend.fonts_object = self
+ self.used_characters = {}
+ 
+ def get_kern(self, font1, sym1, fontsize1,
+ font2, sym2, fontsize2, dpi):
+ """
+ Get the kerning distance for font between sym1 and sym2.
 
-# TO-DO: pretty much everything
-class BakomaUnicodeFonts(UnicodeFonts):
- """A class that simulates Unicode support in the BaKoMa fonts"""
+ fontX: one of the TeX font names, tt, it, rm, cal, sf, bf or
+ default (non-math)
+ symX: a symbol in raw TeX form. e.g. '1', 'x' or '\sigma'
+ fontsizeX: the fontsize in points
+ dpi: the current dots-per-inch
+ 
+ sym is a single symbol(alphanum, punct) or a special symbol
+ like \sigma.
 
- filenamesd = { 'cal' : 'cmsy10.ttf',
- 'rm' : 'cmr10.ttf',
- 'tt' : 'cmtt10.ttf',
- 'it' : 'cmmi10.ttf',
- 'bf' : 'cmb10.ttf',
- 'sf' : 'cmss10.ttf',
- None : 'cmmi10.ttf',
- }
+ """
+ return 0.
 
- # We override the UnicodeFonts methods, that depend on Unicode support
- def _get_unicode_index(self, symbol):
- uniindex = get_unicode_index(symbol)
+ def get_metrics(self, font, sym, fontsize, dpi):
+ """
+ font: one of the TeX font names, tt, it, rm, cal, sf, bf or
+ default (non-math)
+ sym: a symbol in raw TeX form. e.g. '1', 'x' or '\sigma'
+ fontsize: font size in points
+ dpi: current dots-per-inch
 
- # Should be deleted
- def _get_glyph_name(self, uniindex, facename):
- """get_glyph_name(self, uniindex, facename) -> string
+ advance
+ height
+ width
+ xmin, xmax, ymin, ymax - the ink rectangle of the glyph
+ iceberg - the distance from the baseline to the top of the glyph.
+ horiBearingY in Truetype parlance, height in TeX parlance
+ """
+ info = self._get_info(font, sym, fontsize, dpi)
+ return info.metrics
 
-Returns the name of the glyph directly from the font object.
-Because BaKoma fonts don't support Unicode, 'uniindex' is misleading
+ def set_canvas_size(self, w, h):
+ 'Dimension the drawing canvas; may be a noop'
+ self.width, self.height = ceil(w), ceil(h)
+ self.mathtext_backend.set_canvas_size(self.width, self.height)
 
-"""
- font = self.fonts[facename]
- glyphindex = self.glyphmaps[facename][uniindex]
- return font.get_glyph_name(glyphindex)
+ def render_glyph(self, ox, oy, facename, sym, fontsize, dpi):
+ info = self._get_info(facename, sym, fontsize, dpi)
+ realpath, stat_key = get_realpath_and_stat(info.font.fname)
+ used_characters = self.used_characters.setdefault(
+ stat_key, (realpath, Set()))
+ used_characters[1].update(unichr(info.num))
+ self.mathtext_backend.render_glyph(ox, oy, info)
 
- def _get_info(self, facename, symbol, fontsize, dpi):
- 'load the facename, metrics and glyph'
- #print hex(index), symbol, filename, facename
- key = facename, symbol, fontsize, dpi
- tup = self.glyphdict.get(key)
- if tup is not None:
- return tup
- filename = self.filenamesd[facename]
- fontface = self.fonts[facename]
- fontface.set_size(fontsize, dpi)
- head = fontface.get_sfnt_table('head')
- uniindex = self._get_unicode_index(symbol)
- glyphindex = self.glyphmaps[facename][uniindex]
- glyph = fontface.load_char(uniindex)
- xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- # This is black magic to me (Edin)
- if filename == 'cmex10.ttf':
- if self.output == 'PS':
- offset = -(head['yMin']+512)/head['unitsPerEm']*10.
- else:
- offset = glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
- else:
- offset = 0.
- metrics = Bunch(
- advance = glyph.linearHoriAdvance/65536.0,
- height = glyph.height/64.0,
- width = glyph.width/64.0,
- xmin = xmin,
- xmax = xmax,
- ymin = ymin+offset,
- ymax = ymax+offset,
- )
- self.glyphdict[key] = uniindex, metrics, glyph, offset
- return self.glyphdict[key]
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.mathtext_backend.render_rect_filled(x1, y1, x2, y2)
 
+ def get_xheight(self, font, fontsize, dpi):
+ raise NotImplementedError()
 
-# TO-DO: Implement all methods
-class CMUUnicodeFonts(UnicodeFonts):
- """A class representing Computer Modern Unicode Fonts, made by
-Andrey V. Panov
-panov /at/ canopus. iacp. dvo. ru
-They are distributed under the X11 License.
+ def get_underline_thickness(self, font, fontsize, dpi):
+ raise NotImplementedError()
+ 
+ def get_used_characters(self):
+ return self.used_characters
 
-"""
+ def get_results(self):
+ return self.mathtext_backend.get_results()
 
-
-# Old classes
-
-class BakomaFonts(Fonts):
+ def get_sized_alternatives_for_symbol(self, fontname, sym):
+ """Override if your font provides multiple sizes of the same
+ symbol."""
+ return [(fontname, sym)]
+ 
+class TruetypeFonts(Fonts):
 """
+ A generic base class for all font setups that use Truetype fonts
+ (through ft2font)
+ """
+ """
 Use the Bakoma true type fonts for rendering
 """
 # allocate a new set of fonts
 basepath = os.path.join( get_data_path(), 'fonts', 'ttf' )
 
- fontmap = { 'cal' : 'Cmsy10',
- 'rm' : 'Cmr10',
- 'tt' : 'Cmtt10',
- 'it' : 'Cmmi10',
- 'bf' : 'Cmb10',
- 'sf' : 'Cmss10',
- None : 'Cmmi10',
- 'ex' : 'Cmex10'
- }
-
 class CachedFont:
 def __init__(self, font):
 self.font = font
 self.charmap = font.get_charmap()
 self.glyphmap = dict(
 [(glyphind, ccode) for ccode, glyphind in self.charmap.items()])
- 
- def __init__(self):
- self.glyphd = {}
- self.fonts = {}
- self.used_characters = {}
 
+ def __repr__(self):
+ return repr(self.font)
+ 
+ def __init__(self, default_font_prop, mathtext_backend):
+ Fonts.__init__(self, default_font_prop, mathtext_backend)
+ self.glyphd = {}
+ self.fonts = {}
+
+ filename = fontManager.findfont(default_font_prop)
+ default_font = self.CachedFont(FT2Font(str(filename)))
+ 
+ self.fonts['default'] = default_font
+ 
 def _get_font(self, font):
 """Looks up a CachedFont with its charmap and inverse charmap.
- font may be a TeX font name (cal, rm, it etc.), a Computer Modern
- font name (cmtt10, cmr10, etc.) or an FT2Font object."""
- if isinstance(font, str):
- if font not in self.fontmap.values():
- basename = self.fontmap[font]
- else:
- basename = font
+ font may be a TeX font name (cal, rm, it etc.), or postscript name."""
+ if font in self.fontmap:
+ basename = self.fontmap[font]
 else:
- basename = font.postscript_name
+ basename = font
 
 cached_font = self.fonts.get(basename)
 if cached_font is None:
- if isinstance(font, str):
- font = FT2Font(os.path.join(self.basepath, basename.lower() + ".ttf"))
- basename = font.postscript_name
+ font = FT2Font(os.path.join(self.basepath, basename + ".ttf"))
 cached_font = self.CachedFont(font)
 self.fonts[basename] = cached_font
- return basename, cached_font
+ self.fonts[font.postscript_name] = cached_font
+ self.fonts[font.postscript_name.lower()] = cached_font
+ return cached_font
 
- def get_font(self, font):
- return self._get_font(font)[1].font
- 
 def get_fonts(self):
- return [x.font for x in self.fonts.values()]
- 
- def get_metrics(self, font, sym, fontsize, dpi):
- basename, font, metrics, symbol_name, num, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
- return metrics
+ return list(set([x.font for x in self.fonts.values()]))
 
- def _get_offset(self, basename, cached_font, glyph, fontsize, dpi):
- if basename.lower() == 'cmex10':
- return glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
+ def _get_offset(self, cached_font, glyph, fontsize, dpi):
 return 0.
- 
- def _get_info (self, font, sym, fontsize, dpi):
+ 
+ def _get_info (self, fontname, sym, fontsize, dpi, mark_as_used=True):
 'load the cmfont, metrics and glyph with caching'
- if hasattr(font, 'postscript_name'):
- fontname = font.postscript_name
- else:
- fontname = font
- 
 key = fontname, sym, fontsize, dpi
- tup = self.glyphd.get(key)
+ bunch = self.glyphd.get(key)
+ if bunch is not None:
+ return bunch
 
- if tup is not None: return tup
- 
- if font in self.fontmap and latex_to_bakoma.has_key(sym):
- basename, num = latex_to_bakoma[sym]
- basename, cached_font = self._get_font(basename.capitalize())
- symbol_name = cached_font.font.get_glyph_name(num)
- num = cached_font.glyphmap[num]
- elif len(sym) == 1:
- basename, cached_font = self._get_font(font)
- num = ord(sym)
- symbol_name = cached_font.font.get_glyph_name(cached_font.charmap[num])
- else:
- num = 0
- raise ValueError('unrecognized symbol "%s"' % sym)
+ cached_font, num, symbol_name, fontsize = \
+ self._get_glyph(fontname, sym, fontsize)
 
 font = cached_font.font
 font.set_size(fontsize, dpi)
 glyph = font.load_char(num)
 
- realpath, stat_key = get_realpath_and_stat(font.fname)
- used_characters = self.used_characters.setdefault(
- stat_key, (realpath, Set()))
- used_characters[1].update(unichr(num))
- 
 xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- offset = self._get_offset(basename, cached_font, glyph, fontsize, dpi)
+ offset = self._get_offset(cached_font, glyph, fontsize, dpi)
 metrics = Bunch(
- advance = glyph.linearHoriAdvance/65536.0,
- height = glyph.height/64.0,
- width = glyph.width/64.0,
- xmin = xmin,
- xmax = xmax,
- ymin = ymin+offset,
- ymax = ymax+offset,
+ advance = glyph.linearHoriAdvance/65536.0,
+ height = glyph.height/64.0 + offset,
+ width = glyph.width/64.0,
+ xmin = xmin,
+ xmax = xmax,
+ ymin = ymin+offset,
+ ymax = ymax+offset,
 # iceberg is the equivalent of TeX's "height"
 iceberg = glyph.horiBearingY/64.0 + offset
 )
 
- self.glyphd[key] = basename, font, metrics, symbol_name, num, glyph, offset
+ self.glyphd[key] = Bunch(
+ font = font,
+ fontsize = fontsize,
+ postscript_name = font.postscript_name,
+ metrics = metrics,
+ symbol_name = symbol_name,
+ num = num,
+ glyph = glyph,
+ offset = offset
+ )
 return self.glyphd[key]
 
- def set_canvas_size(self, w, h):
- 'Dimension the drawing canvas; may be a noop'
- self.width = int(w)
- self.height = int(h)
- for cached_font in self.fonts.values():
- cached_font.font.set_bitmap_size(int(w), int(h))
-
- def render(self, ox, oy, font, sym, fontsize, dpi):
- basename, font, metrics, symbol_name, num, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
-
- font.draw_glyph_to_bitmap(
- int(ox), int(oy - metrics.ymax), glyph)
-
- def render_rect_filled(self, x1, y1, x2, y2):
- assert len(self.fonts)
- font = self.fonts.values()[0]
- font.font.draw_rect_filled(
- max(0, x1 - 1),
- y1,
- max(x2 - 1, x1),
- max(y2 - 1, y1))
- 
- def get_used_characters(self):
- return self.used_characters
-
 def get_xheight(self, font, fontsize, dpi):
- basename, cached_font = self._get_font(font)
+ cached_font = self._get_font(font)
 cached_font.font.set_size(fontsize, dpi)
 pclt = cached_font.font.get_sfnt_table('pclt')
+ if pclt is None:
+ # Some fonts don't store the xHeight, so we do a poor man's xHeight
+ metrics = self.get_metrics(font, 'x', fontsize, dpi)
+ return metrics.iceberg
 xHeight = pclt['xHeight'] / 64.0
 return xHeight
 
 def get_underline_thickness(self, font, fontsize, dpi):
- basename, cached_font = self._get_font(font)
+ cached_font = self._get_font(font)
 cached_font.font.set_size(fontsize, dpi)
 return max(1.0, cached_font.font.underline_thickness / 64.0)
 
- def get_kern(self, fontleft, symleft, fontsizeleft,
- fontright, symright, fontsizeright, dpi):
- if fontsizeleft == fontsizeright:
- basename, font1, metrics, symbol_name, num1, glyph1, offset = \
- self._get_info(fontleft, symleft, fontsizeleft, dpi)
- basename, font2, metrics, symbol_name, num2, glyph2, offset = \
- self._get_info(fontright, symright, fontsizeright, dpi)
- if font1 == font2:
- basename, font = self._get_font(font1)
- return font.font.get_kerning(num1, num2, KERNING_UNFITTED) / 64.0
+ def get_kern(self, font1, sym1, fontsize1,
+ font2, sym2, fontsize2, dpi):
+ if font1 == font2 and fontsize1 == fontsize2:
+ info1 = self._get_info(font1, sym1, fontsize1, dpi)
+ info2 = self._get_info(font2, sym2, fontsize2, dpi)
+ font = info1.font
+ return font.get_kerning(info1.num, info2.num, KERNING_UNFITTED) / 64.0
 return 0.0
 
-class BakomaPSFonts(BakomaFonts):
+class BakomaFonts(TruetypeFonts):
 """
- Use the Bakoma postscript fonts for rendering to backend_ps
+ Use the Bakoma true type fonts for rendering
 """
-
- def set_canvas_size(self, w, h, pswriter):
- 'Dimension the drawing canvas; may be a noop'
- self.width = w
- self.height = h
- self.pswriter = pswriter
-
- def render(self, ox, oy, font, sym, fontsize, dpi):
- basename, font, metrics, symbol_name, num, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
- oy = self.height - oy + offset
- 
- ps = """/%(basename)s findfont
-%(fontsize)s scalefont
-setfont
-%(ox)f %(oy)f moveto
-/%(symbol_name)s glyphshow
-""" % locals()
- self.pswriter.write(ps)
-
- def render_rect_filled(self, x1, y1, x2, y2):
- ps = "%f %f %f %f rectfill" % (x1, self.height - y2, x2 - x1, y2 - y1)
- self.pswriter.write(ps)
+ fontmap = { 'cal' : 'cmsy10',
+ 'rm' : 'cmr10',
+ 'tt' : 'cmtt10',
+ 'it' : 'cmmi10',
+ 'bf' : 'cmb10',
+ 'sf' : 'cmss10',
+ 'ex' : 'cmex10'
+ }
 
-class BakomaPDFFonts(BakomaPSFonts):
- """Hack of BakomaPSFonts for PDF support."""
+ def _get_offset(self, cached_font, glyph, fontsize, dpi):
+ if cached_font.font.postscript_name == 'cmex10':
+ return glyph.height/64.0/2 + 256.0/64.0 * dpi/72.0
+ return 0.
 
- def render(self, ox, oy, font, sym, fontsize, dpi):
- basename, font, metrics, symbol_name, num, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
- filename = font.fname
- oy = self.height - oy + offset
+ 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]
+ cached_font = self._get_font(basename)
+ symbol_name = cached_font.font.get_glyph_name(num)
+ num = cached_font.glyphmap[num]
+ elif len(sym) == 1:
+ cached_font = self._get_font(fontname)
+ num = ord(sym)
+ symbol_name = cached_font.font.get_glyph_name(
+ cached_font.charmap[num])
+ else:
+ raise ValueError('unrecognized symbol "%s"' % sym)
 
- self.pswriter.append(('glyph', ox, oy, filename, fontsize, num))
+ return cached_font, num, symbol_name, fontsize
 
- def render_rect_filled(self, x1, y1, x2, y2):
- self.pswriter.append(('rect', x1, self.height - y2, x2 - x1, y2 - y1))
+ # The Bakoma fonts contain many pre-sized alternatives for the
+ # delimiters. The AutoSizedChar class will use these alternatives
+ # and select the best (closest sized) glyph.
+ _size_alternatives = {
+ '(' : [('rm', '('), ('ex', '\xa1'), ('ex', '\xb3'),
+ ('ex', '\xb5'), ('ex', '\xc3')],
+ ')' : [('rm', ')'), ('ex', '\xa2'), ('ex', '\xb4'),
+ ('ex', '\xb6'), ('ex', '\x21')],
+ '{' : [('cal', '{'), ('ex', '\xa9'), ('ex', '\x6e'),
+ ('ex', '\xbd'), ('ex', '\x28')],
+ '}' : [('cal', '}'), ('ex', '\xaa'), ('ex', '\x6f'),
+ ('ex', '\xbe'), ('ex', '\x29')],
+ # The fourth size of '[' is mysteriously missing from the BaKoMa font,
+ # so I've ommitted it for both
+ '[' : [('rm', '['), ('ex', '\xa3'), ('ex', '\x68'),
+ ('ex', '\x22')],
+ ']' : [('rm', ']'), ('ex', '\xa4'), ('ex', '\x69'),
+ ('ex', '\x23')],
+ r'\lfloor' : [('cal', '\x62'), ('ex', '\xa5'), ('ex', '\x6a'),
+ ('ex', '\xb9'), ('ex', '\x24')],
+ r'\rfloor' : [('cal', '\x63'), ('ex', '\xa6'), ('ex', '\x6b'),
+ ('ex', '\xba'), ('ex', '\x25')],
+ r'\lceil' : [('cal', '\x64'), ('ex', '\xa7'), ('ex', '\x6c'),
+ ('ex', '\xbb'), ('ex', '\x26')],
+ r'\rceil' : [('cal', '\x65'), ('ex', '\xa8'), ('ex', '\x6d'),
+ ('ex', '\xbc'), ('ex', '\x27')],
+ r'\langle' : [('cal', '\x68'), ('ex', '\xad'), ('ex', '\x44'),
+ ('ex', '\xbf'), ('ex', '\x2a')],
+ r'\rangle' : [('cal', '\x69'), ('ex', '\xae'), ('ex', '\x45'),
+ ...
 
[truncated message content]
From: <ef...@us...> - 2007年07月30日 07:03:49
Revision: 3630
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3630&view=rev
Author: efiring
Date: 2007年07月30日 00:03:47 -0700 (2007年7月30日)
Log Message:
-----------
Removed last vestiges of old pcolor, scatter, quiver versions.
Modified Paths:
--------------
 trunk/matplotlib/CHANGELOG
 trunk/matplotlib/boilerplate.py
 trunk/matplotlib/lib/matplotlib/axes.py
 trunk/matplotlib/lib/matplotlib/pylab.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG	2007年07月30日 06:04:41 UTC (rev 3629)
+++ trunk/matplotlib/CHANGELOG	2007年07月30日 07:03:47 UTC (rev 3630)
@@ -1,6 +1,7 @@
 2007年07月29日 Changed default pcolor shading to flat; added aliases
 to make collection kwargs agree with setter names, so
 updating works; related minor cleanups.
+ Removed quiver_classic, scatter_classic, pcolor_classic. - EF
 
 2007年07月26日 Major rewrite of mathtext.py, using the TeX box layout model.
 
Modified: trunk/matplotlib/boilerplate.py
===================================================================
--- trunk/matplotlib/boilerplate.py	2007年07月30日 06:04:41 UTC (rev 3629)
+++ trunk/matplotlib/boilerplate.py	2007年07月30日 07:03:47 UTC (rev 3630)
@@ -82,7 +82,6 @@
 'stem',
 'vlines',
 'quiver',
- 'quiver2',
 'quiverkey',
 'xcorr',
 )
Modified: trunk/matplotlib/lib/matplotlib/axes.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/axes.py	2007年07月30日 06:04:41 UTC (rev 3629)
+++ trunk/matplotlib/lib/matplotlib/axes.py	2007年07月30日 07:03:47 UTC (rev 3630)
@@ -4051,34 +4051,6 @@
 
 scatter.__doc__ = cbook.dedent(scatter.__doc__) % martist.kwdocd
 
- def scatter_classic(self, x, y, s=None, c='b'):
- """
- scatter_classic is no longer available; please use scatter.
- To help in porting, for comparison to the scatter docstring,
- here is the scatter_classic docstring:
-
- SCATTER_CLASSIC(x, y, s=None, c='b')
-
- Make a scatter plot of x versus y. s is a size (in data coords) and
- can be either a scalar or an array of the same length as x or y. c is
- a color and can be a single color format string or an length(x) array
- of intensities which will be mapped by the colormap jet.
-
- If size is None a default size will be used
- """
- raise NotImplementedError('scatter_classic has been removed;\n'
- + 'please use scatter instead')
-
- def pcolor_classic(self, *args):
- """
- pcolor_classic is no longer available; please use pcolor,
- which is a drop-in replacement.
- """
- raise NotImplementedError('pcolor_classic has been removed;\n'
- + 'please use pcolor instead')
-
-
-
 def arrow(self, x, y, dx, dy, **kwargs):
 """
 Draws arrow on specified axis from (x,y) to (x+dx,y+dy).
@@ -4097,164 +4069,14 @@
 return qk
 quiverkey.__doc__ = mquiver.QuiverKey.quiverkey_doc
 
- def quiver2(self, *args, **kw):
+ def quiver(self, *args, **kw):
 q = mquiver.Quiver(self, *args, **kw)
 self.add_collection(q)
 self.update_datalim_numerix(q.X, q.Y)
 self.autoscale_view()
 return q
- quiver2.__doc__ = mquiver.Quiver.quiver_doc
-
- def quiver(self, *args, **kw):
- if (len(args) == 3 or len(args) == 5) and not iterable(args[-1]):
- return self.quiver_classic(*args, **kw)
- c = kw.get('color', None)
- if c is not None:
- if not mcolors.is_color_like(c):
- assert npy.shape(npy.asarray(c)) == npy.shape(npy.asarray(args[-1]))
- return self.quiver_classic(*args, **kw)
- return self.quiver2(*args, **kw)
 quiver.__doc__ = mquiver.Quiver.quiver_doc
 
- def quiver_classic(self, U, V, *args, **kwargs ):
- """
- QUIVER( X, Y, U, V )
- QUIVER( U, V )
- QUIVER( X, Y, U, V, S)
- QUIVER( U, V, S )
- QUIVER( ..., color=None, width=1.0, cmap=None, norm=None )
-
- Make a vector plot (U, V) with arrows on a grid (X, Y)
-
- If X and Y are not specified, U and V must be 2D arrays.
- Equally spaced X and Y grids are then generated using the
- meshgrid command.
-
- color can be a color value or an array of colors, so that the
- arrows can be colored according to another dataset. If cmap
- is specified and color is 'length', the colormap is used to
- give a color according to the vector's length.
-
- If color is a scalar field, the colormap is used to map the
- scalar to a color If a colormap is specified and color is an
- array of color triplets, then the colormap is ignored
-
- width is a scalar that controls the width of the arrows
-
- if S is specified it is used to scale the vectors. Use S=0 to
- disable automatic scaling. If S!=0, vectors are scaled to fit
- within the grid and then are multiplied by S.
-
-
- """
- msg = '''This version of quiver is obsolete and will be
- phased out; please use the new quiver.
- '''
- warnings.warn(msg, DeprecationWarning)
- if not self._hold: self.cla()
- do_scale = True
- S = 1.0
- if len(args)==0:
- # ( U, V )
- U = npy.asarray(U)
- V = npy.asarray(V)
- X,Y = mlab.meshgrid( npy.arange(U.shape[1]), npy.arange(U.shape[0]) )
- elif len(args)==1:
- # ( U, V, S )
- U = npy.asarray(U)
- V = npy.asarray(V)
- X,Y = mlab.meshgrid( npy.arange(U.shape[1]), npy.arange(U.shape[0]) )
- S = float(args[0])
- do_scale = ( S != 0.0 )
- elif len(args)==2:
- # ( X, Y, U, V )
- X = npy.asarray(U)
- Y = npy.asarray(V)
- U = npy.asarray(args[0])
- V = npy.asarray(args[1])
- elif len(args)==3:
- # ( X, Y, U, V )
- X = npy.asarray(U)
- Y = npy.asarray(V)
- U = npy.asarray(args[0])
- V = npy.asarray(args[1])
- S = float(args[2])
- do_scale = ( S != 0.0 )
-
- assert U.shape == V.shape
- assert X.shape == Y.shape
- assert U.shape == X.shape
-
- U = U.ravel()
- V = V.ravel()
- X = X.ravel()
- Y = Y.ravel()
-
- arrows = []
- N = npy.sqrt( U**2+V**2 )
- if do_scale:
- Nmax = maximum.reduce(N) or 1 # account for div by zero
- U = U*(S/Nmax)
- V = V*(S/Nmax)
- N = N*Nmax
-
- alpha = kwargs.pop('alpha', 1.0)
- width = kwargs.pop('width', .5)
- norm = kwargs.pop('norm', None)
- cmap = kwargs.pop('cmap', None)
- vmin = kwargs.pop('vmin', None)
- vmax = kwargs.pop('vmax', None)
- color = kwargs.pop('color', None)
- shading = kwargs.pop('shading', 'faceted')
-
- if len(kwargs):
- raise TypeError(
- "quiver() got an unexpected keyword argument '%s'"%kwargs.keys()[0])
-
- C = None
- if color == 'length' or color is True:
- if color is True:
- warnings.warn('''Use "color='length'",
- not "color=True"''', DeprecationWarning)
- C = N
- elif color is None:
- color = (0,0,0,1)
- else:
- clr = npy.asarray(color).ravel()
- if clr.shape == U.shape:
- C = clr
-
- I = U.shape[0]
- arrows = [mpatches.FancyArrow(X[i],Y[i],U[i],V[i],0.1*S ).get_verts()
- for i in xrange(I)]
-
- collection = mcoll.PolyCollection(
- arrows,
- edgecolors = 'None',
- antialiaseds = (1,),
- linewidths = (width,),
- )
- if C is not None:
- collection.set_array( C.ravel() )
- collection.set_cmap(cmap)
- collection.set_norm(norm)
- if norm is not None:
- collection.set_clim( vmin, vmax )
- else:
- collection.set_facecolor(color)
- self.add_collection( collection )
-
- lims = npy.asarray(arrows)
- _max = maximum.reduce( maximum.reduce( lims ))
- _min = minimum.reduce( minimum.reduce( lims ))
- self.update_datalim( [ tuple(_min), tuple(_max) ] )
- self.autoscale_view()
- return collection
-
-
-
-
-
 def fill(self, *args, **kwargs):
 """
 FILL(*args, **kwargs)
Modified: trunk/matplotlib/lib/matplotlib/pylab.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/pylab.py	2007年07月30日 06:04:41 UTC (rev 3629)
+++ trunk/matplotlib/lib/matplotlib/pylab.py	2007年07月30日 07:03:47 UTC (rev 3630)
@@ -335,64 +335,6 @@
 colorbar.__doc__ = colorbar_doc
 
 
-def colorbar_classic(mappable = None,
- cax=None,
- orientation='vertical',
- tickfmt='%1.1f',
- cspacing='proportional',
- clabels=None,
- drawedges=False,
- edgewidth=0.5,
- edgecolor='k'):
- """
- Create a colorbar for mappable; if mappable is None,
- use current image.
-
- tickfmt is a format string to format the colorbar ticks
-
- cax is a colorbar axes instance in which the colorbar will be
- placed. If None, as default axesd will be created resizing the
- current aqxes to make room for it. If not None, the supplied axes
- will be used and the other axes positions will be unchanged.
-
- orientation is the colorbar orientation: one of 'vertical' | 'horizontal'
-
- cspacing controls how colors are distributed on the colorbar.
- if cspacing == 'linear', each color occupies an equal area
- on the colorbar, regardless of the contour spacing.
- if cspacing == 'proportional' (Default), the area each color
- occupies on the the colorbar is proportional to the contour interval.
- Only relevant for a Contour image.
-
- clabels can be a sequence containing the
- contour levels to be labelled on the colorbar, or None (Default).
- If clabels is None, labels for all contour intervals are
- displayed. Only relevant for a Contour image.
-
- if drawedges == True, lines are drawn at the edges between
- each color on the colorbar. Default False.
-
- edgecolor is the line color delimiting the edges of the colors
- on the colorbar (if drawedges == True). Default black ('k')
-
- edgewidth is the width of the lines delimiting the edges of
- the colors on the colorbar (if drawedges == True). Default 0.5
-
- return value is the colorbar axes instance
- """
- if mappable is None:
- mappable = gci()
- ret = gcf().colorbar_classic(mappable, cax = cax,
- orientation = orientation,
- tickfmt = tickfmt,
- cspacing=cspacing,
- clabels=clabels,
- drawedges=drawedges,
- edgewidth=edgewidth,
- edgecolor=edgecolor)
- draw_if_interactive()
- return ret
-
 def colors():
 """
 This is a do nothing function to provide you with help on how
@@ -1606,19 +1548,6 @@
 
 draw_if_interactive()
 
-### Deprecated functions:
-def scatter_classic(*args, **kwargs):
- return gca().scatter_classic(*args, **kwargs)
-if Axes.scatter_classic.__doc__ is not None:
- scatter_classic.__doc__ = dedent(Axes.scatter_classic.__doc__)
-
-def pcolor_classic(*args, **kwargs):
- return gca().pcolor_classic(*args, **kwargs)
-if Axes.pcolor_classic.__doc__ is not None:
- pcolor_classic.__doc__ = dedent(Axes.pcolor_classic.__doc__)
-
-
-
 ### Do not edit below this point
 # This function was autogenerated by boilerplate.py. Do not edit as
 # changes will be lost
@@ -2357,27 +2286,6 @@
 
 # This function was autogenerated by boilerplate.py. Do not edit as
 # changes will be lost
-def quiver2(*args, **kwargs):
- # allow callers to override the hold state by passing hold=True|False
- b = ishold()
- h = popd(kwargs, 'hold', None)
- if h is not None:
- hold(h)
- try:
- ret = gca().quiver2(*args, **kwargs)
- draw_if_interactive()
- except:
- hold(b)
- raise
- gci._current = ret
- hold(b)
- return ret
-if Axes.quiver2.__doc__ is not None:
- quiver2.__doc__ = dedent(Axes.quiver2.__doc__) + """
-Addition kwargs: hold = [True|False] overrides default hold state"""
-
-# This function was autogenerated by boilerplate.py. Do not edit as
-# changes will be lost
 def quiverkey(*args, **kwargs):
 # allow callers to override the hold state by passing hold=True|False
 b = ishold()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3629
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3629&view=rev
Author: fer_perez
Date: 2007年07月29日 23:04:41 -0700 (2007年7月29日)
Log Message:
-----------
cleaner fill implementation
Modified Paths:
--------------
 trunk/py4science/examples/schrodinger/schrod_fdtd.py
Modified: trunk/py4science/examples/schrodinger/schrod_fdtd.py
===================================================================
--- trunk/py4science/examples/schrodinger/schrod_fdtd.py	2007年07月30日 02:04:46 UTC (rev 3628)
+++ trunk/py4science/examples/schrodinger/schrod_fdtd.py	2007年07月30日 06:04:41 UTC (rev 3629)
@@ -80,6 +80,16 @@
 v[npts/2:npts/2+thickness] = v0
 return v
 
+def fillax(x,y,*args,**kw):
+ """Fill the space between an array of y values and the x axis.
+
+ All args/kwargs are passed to the pylab.fill function.
+ Returns the value of the pylab.fill() call.
+ """
+ xx = np.concatenate((x,np.array([x[-1],x[0]],x.dtype)))
+ yy = np.concatenate((y,np.zeros(2,y.dtype)))
+ return pylab.fill(xx, yy, *args,**kw)
+ 
 #=============================================================================
 #
 # Simulation Constants. Be sure to include decimal points on appropriate
@@ -213,14 +223,12 @@
 # in light red, as well as drawing a green line at the wavepacket's total
 # energy, in the same units the potential is being plotted.
 if Vmax !=0 :
+ # Scaling factor for energies, so they fit in the same plot as the
+ # wavefunctions
 Efac = ymax/2.0/Vmax
 V_plot = V*Efac
 pylab.plot(X,V_plot,':k',zorder=0) # Potential line.
- # reverse x and y2 so the polygon fills in order
- y1 = free(N) # lower boundary for polygon drawing
- x = np.concatenate( (X,X[::-1]) )
- y = np.concatenate( (y1,V_plot[::-1]) )
- pylab.fill(x, y, facecolor='y', alpha=0.2,zorder=0)
+ fillax(X,V_plot, facecolor='y', alpha=0.2,zorder=0)
 # Plot the wavefunction energy, in the same scale as the potential
 pylab.axhline(E*Efac,color='g',label='Energy',zorder=1)
 pylab.legend(loc='lower right')
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <ef...@us...> - 2007年07月30日 02:04:54
Revision: 3628
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3628&view=rev
Author: efiring
Date: 2007年07月29日 19:04:46 -0700 (2007年7月29日)
Log Message:
-----------
changed pcolor default to shading='flat'; related cleanups
Modified Paths:
--------------
 trunk/matplotlib/API_CHANGES
 trunk/matplotlib/CHANGELOG
 trunk/matplotlib/examples/pcolor_demo.py
 trunk/matplotlib/examples/pcolor_log.py
 trunk/matplotlib/examples/pcolor_small.py
 trunk/matplotlib/lib/matplotlib/artist.py
 trunk/matplotlib/lib/matplotlib/axes.py
 trunk/matplotlib/lib/matplotlib/collections.py
Modified: trunk/matplotlib/API_CHANGES
===================================================================
--- trunk/matplotlib/API_CHANGES	2007年07月29日 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/API_CHANGES	2007年07月30日 02:04:46 UTC (rev 3628)
@@ -1,3 +1,6 @@
+ Changed pcolor default to shading='flat'; but as noted now in the
+ docstring, it is preferable to simply use the edgecolor kwarg.
+
 The mathtext font commands (\cal, \rm, \it, \tt) now behave as TeX
 does: they are in effect until the next font change command or the
 end of the grouping. Therefore uses of $\cal{R}$ should be
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG	2007年07月29日 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/CHANGELOG	2007年07月30日 02:04:46 UTC (rev 3628)
@@ -1,54 +1,58 @@
+2007年07月29日 Changed default pcolor shading to flat; added aliases
+ to make collection kwargs agree with setter names, so
+ updating works; related minor cleanups.
+
 2007年07月26日 Major rewrite of mathtext.py, using the TeX box layout model.
 
-	 There is one (known) backward incompatible change. The
-	 font commands (\cal, \rm, \it, \tt) now behave as TeX does:
-	 they are in effect until the next font change command or
-	 the end of the grouping. Therefore uses of $\cal{R}$
-	 should be changed to ${\cal R}$. Alternatively, you may
-	 use the new LaTeX-style font commands (\mathcal, \mathrm,
-	 \mathit, \mathtt) which do affect the following group,
-	 eg. $\mathcal{R}$.
+ There is one (known) backward incompatible change. The
+ font commands (\cal, \rm, \it, \tt) now behave as TeX does:
+ they are in effect until the next font change command or
+ the end of the grouping. Therefore uses of $\cal{R}$
+ should be changed to ${\cal R}$. Alternatively, you may
+ use the new LaTeX-style font commands (\mathcal, \mathrm,
+ \mathit, \mathtt) which do affect the following group,
+ eg. $\mathcal{R}$.
 
-	 Other new features include:
+ Other new features include:
 
-	 - Math may be interspersed with non-math text. Any text
+ - Math may be interspersed with non-math text. Any text
 with an even number of $'s (non-escaped) will be sent to
-	 the mathtext parser for layout.
+ the mathtext parser for layout.
 
-	 - Sub/superscripts are less likely to accidentally overlap.
+ - Sub/superscripts are less likely to accidentally overlap.
 
-	 - Support for sub/superscripts in either order, eg. $x^i_j$
+ - Support for sub/superscripts in either order, eg. $x^i_j$
 and $x_j^i$ are equivalent.
 
-	 - Double sub/superscripts (eg. $x_i_j$) are considered
+ - Double sub/superscripts (eg. $x_i_j$) are considered
 ambiguous and raise an exception. Use braces to disambiguate.
 
-	 - $\frac{x}{y}$ can be used for displaying fractions.
+ - $\frac{x}{y}$ can be used for displaying fractions.
 
-	 - $\sqrt[3]{x}$ can be used to display the radical symbol
+ - $\sqrt[3]{x}$ can be used to display the radical symbol
 with a root number and body.
 
-	 - $\left(\frac{x}{y}\right)$ may be used to create
+ - $\left(\frac{x}{y}\right)$ may be used to create
 parentheses and other delimiters that automatically
 resize to the height of their contents.
 
-	 - Spacing around operators etc. is now generally more like
+ - Spacing around operators etc. is now generally more like
 TeX.
 
- 	 - Added support (and fonts) for boldface (\bf) and
+ - Added support (and fonts) for boldface (\bf) and
 sans-serif (\sf) symbols.
 
-	 - Log-like function name shortcuts are supported. For
+ - Log-like function name shortcuts are supported. For
 example, $\sin(x)$ may be used instead of ${\rm sin}(x)$
 
-	 - Limited use of kerning for the easy case (same font)
+ - Limited use of kerning for the easy case (same font)
 
-	 Behind the scenes, the pyparsing.py module used for doing
-	 the math parsing was updated to the latest stable version
-	 (1.4.6). A lot of duplicate code was refactored out of the
-	 Font classes.
+ Behind the scenes, the pyparsing.py module used for doing
+ the math parsing was updated to the latest stable version
+ (1.4.6). A lot of duplicate code was refactored out of the
+ Font classes.
 
-	 - MGD
+ - MGD
 
 2007年07月19日 completed numpification of most trivial cases - NN
 
@@ -56,11 +60,11 @@
 
 2007年07月19日 replaced the Python code in numerix/ by a minimal wrapper around
 numpy that explicitly mentions all symbols that need to be
-	 addressed for further numpification - NN
+ addressed for further numpification - NN
 
-2007年07月18日 make usetex respect changes to rcParams. texmanager used to 
- only configure itself when it was created, now it 
- reconfigures when rcParams are changed. Thank you Alexander 
+2007年07月18日 make usetex respect changes to rcParams. texmanager used to
+ only configure itself when it was created, now it
+ reconfigures when rcParams are changed. Thank you Alexander
 Schmolck for contributing a patch - DSD
 
 2007年07月17日 added validation to setting and changing rcParams - DSD
@@ -71,7 +75,7 @@
 2007年07月16日 clean up some code in ticker.ScalarFormatter, use unicode to
 render multiplication sign in offset ticklabel - DSD
 
-2007年07月16日 fixed a formatting bug in ticker.ScalarFormatter's scientific 
+2007年07月16日 fixed a formatting bug in ticker.ScalarFormatter's scientific
 notation (10^0 was being rendered as 10 in some cases) - DSD
 
 2007年07月13日 Add MPL_isfinite64() and MPL_isinf64() for testing
@@ -83,7 +87,7 @@
 
 2007年07月13日 Removed the rest of the numerix extension code detritus,
 numpified axes.py, and cleaned up the imports in axes.py
-	 - JDH
+ - JDH
 
 2007年07月13日 Added legend.loc as configurable option that could in
 future default to 'best'. - NN
@@ -552,35 +556,35 @@
 
 2006年10月10日 deactivated rcfile-configurability of markerfacecolor
 and markeredgecolor. Both are now hardcoded to the special value
-	 'auto' to follow the line color. Configurability at run-time
-	 (using function arguments) remains functional. - NN
+ 'auto' to follow the line color. Configurability at run-time
+ (using function arguments) remains functional. - NN
 
 2006年10月07日 introduced dummy argument magnification=1.0 to
 FigImage.make_image to satisfy unit test figimage_demo.py
 The argument is not yet handled correctly, which should only
-	 show up when using non-standard DPI settings in PS backend,
-	 introduced by patch #1562394. - NN
+ show up when using non-standard DPI settings in PS backend,
+ introduced by patch #1562394. - NN
 
 2006年10月06日 add backend-agnostic example: simple3d.py - NN
 
 2006年09月29日 fix line-breaking for SVG-inline images (purely cosmetic) - NN
 
 2006年09月29日 reworked set_linestyle and set_marker
-	 markeredgecolor and markerfacecolor now default to
-	 a special value "auto" that keeps the color in sync with
-	 the line color
-	 further, the intelligence of axes.plot is cleaned up,
-	 improved and simplified. Complete compatibility cannot be
-	 guaranteed, but the new behavior should be much more predictable
-	 (see patch #1104615 for details) - NN
+ markeredgecolor and markerfacecolor now default to
+ a special value "auto" that keeps the color in sync with
+ the line color
+ further, the intelligence of axes.plot is cleaned up,
+ improved and simplified. Complete compatibility cannot be
+ guaranteed, but the new behavior should be much more predictable
+ (see patch #1104615 for details) - NN
 
 2006年09月29日 changed implementation of clip-path in SVG to work around a
 limitation in inkscape - NN
 
 2006年09月29日 added two options to matplotlibrc:
-	 svg.image_inline
-	 svg.image_noscale
-	 see patch #1533010 for details - NN
+ svg.image_inline
+ svg.image_noscale
+ see patch #1533010 for details - NN
 
 2006年09月29日 axes.py: cleaned up kwargs checking - NN
 
@@ -611,8 +615,8 @@
 2006年09月05日 Released 0.87.5 at revision 2761
 
 2006年09月04日 Added nxutils for some numeric add-on extension code --
-		 specifically a better/more efficient inside polygon tester (see
-		 unit/inside_poly_*.py) - JDH
+ specifically a better/more efficient inside polygon tester (see
+ unit/inside_poly_*.py) - JDH
 
 2006年09月04日 Made bitstream fonts the rc default - JDH
 
@@ -957,7 +961,7 @@
 2006年03月20日 Added contour.negative_linestyle rcParam - ADS
 
 2006年03月20日 Added _isnan extension module to test for nan with Numeric
-	 - ADS
+ - ADS
 
 2006年03月17日 Added Paul and Alex's support for faceting with quadmesh
 in sf patch 1411223 - JDH
@@ -1304,7 +1308,7 @@
 
 
 2005年11月09日 added axisbelow attr for Axes to determine whether ticks and such
- 	 are above or below the actors
+ are above or below the actors
 
 2005年11月08日 Added Nicolas' irregularly spaced image patch
 
@@ -1461,7 +1465,7 @@
 
 2005年07月24日 backend_gtk.py: modify print_figure() use own pixmap, fixing
 problems where print_figure() overwrites the display pixmap.
-	 return False from all button/key etc events - to allow the event
+ return False from all button/key etc events - to allow the event
 to propagate further - SC
 
 2005年07月23日 backend_gtk.py: change expose_event from using set_back_pixmap();
@@ -1483,7 +1487,7 @@
 2005年07月14日 Fixed a Windows related bug (#1238412) in texmanager - DSD
 
 2005年07月11日 Fixed color kwarg bug, setting color=1 or 0 caused an
-		 exception - DSD
+ exception - DSD
 
 2005年07月07日 Added Eric's MA set_xdata Line2D fix - JDH
 
@@ -1585,10 +1589,10 @@
 2005年06月13日 Exposed cap and join style for lines with new rc params and
 line properties
 
-	lines.dash_joinstyle : miter # miter|round|bevel
-	lines.dash_capstyle : butt # butt|round|projecting
-	lines.solid_joinstyle : miter # miter|round|bevel
-	lines.solid_capstyle : projecting # butt|round|projecting
+ lines.dash_joinstyle : miter # miter|round|bevel
+ lines.dash_capstyle : butt # butt|round|projecting
+ lines.solid_joinstyle : miter # miter|round|bevel
+ lines.solid_capstyle : projecting # butt|round|projecting
 
 
 2005年06月13日 Added kwargs to Axes init
@@ -1702,9 +1706,9 @@
 for the interp kwarg are
 
 'nearest', 'bilinear', 'bicubic', 'spline16', 'spline36',
-	 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric',
-	 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc',
-	 'lanczos', 'blackman'
+ 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric',
+ 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc',
+ 'lanczos', 'blackman'
 
 See help(imshow) for details, particularly the
 interpolation, filternorm and filterrad kwargs
Modified: trunk/matplotlib/examples/pcolor_demo.py
===================================================================
--- trunk/matplotlib/examples/pcolor_demo.py	2007年07月29日 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/examples/pcolor_demo.py	2007年07月30日 02:04:46 UTC (rev 3628)
@@ -19,7 +19,7 @@
 X,Y = meshgrid(x, y)
 
 Z = func3(X, Y)
-pcolor(X, Y, Z, shading='flat')
+pcolor(X, Y, Z)
 colorbar()
 axis([-3,3,-3,3])
 savefig('pcolor_demo')
Modified: trunk/matplotlib/examples/pcolor_log.py
===================================================================
--- trunk/matplotlib/examples/pcolor_log.py	2007年07月29日 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/examples/pcolor_log.py	2007年07月30日 02:04:46 UTC (rev 3628)
@@ -15,11 +15,11 @@
 Z1 = bivariate_normal(X, Y, 0.1, 0.2, 1.0, 1.0) + 0.1*bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
 
 subplot(2,1,1)
-pcolor(X, Y, Z1, shading='flat', norm=LogNorm(vmin=Z1.min(), vmax=Z1.max()))
+pcolor(X, Y, Z1, norm=LogNorm(vmin=Z1.min(), vmax=Z1.max()))
 colorbar()
 
 subplot(2,1,2)
-pcolor(X, Y, Z1, shading='flat')
+pcolor(X, Y, Z1)
 colorbar()
 
 
Modified: trunk/matplotlib/examples/pcolor_small.py
===================================================================
--- trunk/matplotlib/examples/pcolor_small.py	2007年07月29日 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/examples/pcolor_small.py	2007年07月30日 02:04:46 UTC (rev 3628)
@@ -2,15 +2,14 @@
 
 from pylab import *
 
-#Z = arange(60)
-#Z.shape = 6,10
-#Z.shape = 10,6
-#print Z
-Z = rand(10,6)
+Z = rand(6,10)
 
-#c = pcolor(Z, shading='flat') # default 'faceted'
+subplot(2,1,1)
 c = pcolor(Z)
-c.set_linewidth(4)
+title('default: no edges')
 
-#savefig('pcolor_small')
+subplot(2,1,2)
+c = pcolor(Z, edgecolors='k', linewidths=4)
+title('thick edges')
+
 show()
Modified: trunk/matplotlib/lib/matplotlib/artist.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/artist.py	2007年07月29日 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/lib/matplotlib/artist.py	2007年07月30日 02:04:46 UTC (rev 3628)
@@ -55,7 +55,7 @@
 Remove the artist from the figure if possible. The effect will not
 be visible until the figure is redrawn, e.g., with ax.draw_idle().
 Call ax.relim() to update the axes limits if desired.
- 
+
 Note: relim() will not see collections even if the collection
 was added to axes with autolim=True.
 
@@ -63,10 +63,10 @@
 '''
 
 # There is no method to set the callback. Instead the parent should set
- # the _remove_method attribute directly. This would be a protected 
+ # the _remove_method attribute directly. This would be a protected
 # attribute if Python supported that sort of thing. The callback
 # has one parameter, which is the child to be removed.
- if self._remove_method != None: 
+ if self._remove_method != None:
 self._remove_method(self)
 else:
 raise NotImplementedError('cannot remove artist')
Modified: trunk/matplotlib/lib/matplotlib/axes.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/axes.py	2007年07月29日 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/lib/matplotlib/axes.py	2007年07月30日 02:04:46 UTC (rev 3628)
@@ -3853,7 +3853,7 @@
 will be plotted.
 
 Other keyword args; the color mapping and normalization arguments will
- on be used if c is an array of floats
+ be used only if c is an array of floats
 
 * cmap = cm.jet : a colors.Colormap instance from cm.
 defaults to rc image.cmap
@@ -3876,7 +3876,12 @@
 
 * faceted: if True, will use the default edgecolor for the
 markers. If False, will set the edgecolors to be the same
- as the facecolors
+ as the facecolors.
+ This kwarg is deprecated;
+ please use the edgecolors kwarg instead:
+ shading='flat' --> edgecolors='None'
+ shading='faceted --> edgecolors=None
+ edgecolors also can be any mpl color or sequence of colors.
 
 Optional kwargs control the PatchCollection properties:
 %(PatchCollection)s
@@ -4468,7 +4473,14 @@
 instance, vmin and vmax will be None
 
 * shading = 'flat' : or 'faceted'. If 'faceted', a black grid is
- drawn around each rectangle; if 'flat', edges are not drawn
+ drawn around each rectangle; if 'flat', edges are not drawn.
+ Default is 'flat', contrary to Matlab(TM).
+ This kwarg is deprecated;
+ please use the edgecolors kwarg instead:
+ shading='flat' --> edgecolors='None'
+ shading='faceted --> edgecolors='k'
+ edgecolors can also be None to specify the rcParams
+ default, or any mpl color or sequence of colors.
 
 * alpha=1.0 : the alpha blending value
 
@@ -4526,7 +4538,7 @@
 cmap = kwargs.pop('cmap', None)
 vmin = kwargs.pop('vmin', None)
 vmax = kwargs.pop('vmax', None)
- shading = kwargs.pop('shading', 'faceted')
+ shading = kwargs.pop('shading', 'flat')
 
 if len(args)==1:
 C = args[0]
@@ -4586,14 +4598,11 @@
 edgecolors = (0,0,0,1),
 else:
 edgecolors = 'None'
+ kwargs.setdefault('edgecolors', edgecolors)
+ kwargs.setdefault('antialiaseds', (0,))
+ kwargs.setdefault('linewidths', (0.25,))
 
- collection = mcoll.PolyCollection(
- verts,
- edgecolors = edgecolors,
- antialiaseds = (0,),
- linewidths = (0.25,),
- **kwargs
- )
+ collection = mcoll.PolyCollection(verts, **kwargs)
 
 collection.set_alpha(alpha)
 collection.set_array(C)
@@ -4652,8 +4661,14 @@
 min and max of the color array C is used.
 
 * shading = 'flat' : or 'faceted'. If 'faceted', a black grid is
- drawn around each rectangle; if 'flat', edge colors are same as
- face colors
+ drawn around each rectangle; if 'flat', edges are not drawn.
+ Default is 'flat', contrary to Matlab(TM).
+ This kwarg is deprecated;
+ please use the edgecolors kwarg instead:
+ shading='flat' --> edgecolors='None'
+ shading='faceted --> edgecolors='k'
+ More flexible specification of edgecolors, as in pcolor,
+ is not presently supported.
 
 * alpha=1.0 : the alpha blending value
 
@@ -4675,7 +4690,8 @@
 cmap = kwargs.pop('cmap', None)
 vmin = kwargs.pop('vmin', None)
 vmax = kwargs.pop('vmax', None)
- shading = kwargs.pop('shading', 'faceted')
+ shading = kwargs.pop('shading', 'flat')
+ edgecolors = kwargs.pop('edgecolors', 'None')
 
 if len(args)==1:
 C = args[0]
@@ -4703,13 +4719,13 @@
 coords[:, 0] = X
 coords[:, 1] = Y
 
- if shading == 'faceted':
+ if shading == 'faceted' or edgecolors != 'None':
 showedges = 1
 else:
 showedges = 0
 
 collection = mcoll.QuadMesh(
- Nx - 1, Ny - 1, coords, showedges, **kwargs)
+ Nx - 1, Ny - 1, coords, showedges) # kwargs are not used
 collection.set_alpha(alpha)
 collection.set_array(C)
 if norm is not None: assert(isinstance(norm, mcolors.Normalize))
Modified: trunk/matplotlib/lib/matplotlib/collections.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/collections.py	2007年07月29日 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/lib/matplotlib/collections.py	2007年07月30日 02:04:46 UTC (rev 3628)
@@ -21,16 +21,12 @@
 
 class Collection(artist.Artist):
 """
- All properties in a collection must be sequences. The
+ All properties in a collection must be sequences or scalars;
+ if scalars, they will be converted to sequences. The
 property of the ith element of the collection is the
 
 prop[i % len(props)].
 
- This implies that the properties cycle if the len of props is less
- than the number of elements of the collection. A length 1
- property is shared by all the elements of the collection
-
- All color args to a collection are sequences of rgba tuples
 """
 
 def __init__(self):
@@ -133,8 +129,8 @@
 linewidths = (0,)
 else:
 self._edgecolors = _colors.colorConverter.to_rgba_list(edgecolors)
- self._linewidths = linewidths
- self._antialiaseds = antialiaseds
+ self._linewidths = self._get_value(linewidths)
+ self._antialiaseds = self._get_value(antialiaseds)
 #self._offsets = offsets
 self._offsets = offsets
 self._transOffset = transOffset
@@ -221,6 +217,8 @@
 ACCEPTS: float or sequence of floats
 """
 self._linewidths = self._get_value(lw)
+ def set_linewidths(self, lw):
+ self.set_linewidth(lw)
 
 def set_color(self, c):
 """
@@ -242,16 +240,23 @@
 ACCEPTS: matplotlib color arg or sequence of rgba tuples
 """
 self._facecolors = _colors.colorConverter.to_rgba_list(c)
+ def set_facecolors(self, c):
+ self.set_facecolor(c)
 
 def set_edgecolor(self, c):
 """
- Set the facecolor(s) of the collection. c can be a matplotlib color
+ Set the edgecolor(s) of the collection. c can be a matplotlib color
 arg (all patches have same color), or a a sequence or rgba tuples; if
 it is a sequence the patches will cycle through the sequence
 
 ACCEPTS: matplotlib color arg or sequence of rgba tuples
 """
- self._edgecolors = _colors.colorConverter.to_rgba_list(c)
+ if c == 'None':
+ self._linewidths = (0.0,)
+ else:
+ self._edgecolors = _colors.colorConverter.to_rgba_list(c)
+ def set_edgecolors(self, c):
+ self.set_edgecolor(c)
 
 def set_alpha(self, alpha):
 """
@@ -568,7 +573,8 @@
 
 class LineCollection(Collection, cm.ScalarMappable):
 """
- All parameters must be sequences. The property of the ith line
+ All parameters must be sequences or scalars; if scalars, they will
+ be converted to sequences. The property of the ith line
 segment is the prop[i % len(props)], ie the properties cycle if
 the len of props is less than the number of sements
 """
@@ -637,8 +643,8 @@
 antialiaseds = (mpl.rcParams['lines.antialiased'], )
 
 self._colors = _colors.colorConverter.to_rgba_list(colors)
- self._aa = antialiaseds
- self._lw = linewidths
+ self._aa = self._get_value(antialiaseds)
+ self._lw = self._get_value(linewidths)
 self.set_linestyle(linestyle)
 self._uniform_offsets = None
 if offsets is not None:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3627
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3627&view=rev
Author: fer_perez
Date: 2007年07月29日 01:03:12 -0700 (2007年7月29日)
Log Message:
-----------
Small optimization.
Modified Paths:
--------------
 trunk/py4science/examples/schrodinger/schrod_fdtd.py
Modified: trunk/py4science/examples/schrodinger/schrod_fdtd.py
===================================================================
--- trunk/py4science/examples/schrodinger/schrod_fdtd.py	2007年07月29日 06:50:34 UTC (rev 3626)
+++ trunk/py4science/examples/schrodinger/schrod_fdtd.py	2007年07月29日 08:03:12 UTC (rev 3627)
@@ -237,22 +237,26 @@
 IDX2 = range(2,N) # psi [ k + 1 ]
 IDX3 = range(0,N-2) # psi [ k - 1 ]
 
-for t in range(0,T+1):
+for t in range(T+1):
+ # Precompute a couple of indexing constants, this speeds up the computation
+ psi_rPR = psi_r[PR]
+ psi_iPR = psi_i[PR]
+
 # Apply the update equations.
 psi_i[FU,IDX1] = psi_i[PA,IDX1] + \
- c1*(psi_r[PR,IDX2] - 2*psi_r[PR,IDX1] +
- psi_r[PR,IDX3])
- psi_i[FU] = psi_i[FU] - c2V*psi_r[PR]
+ c1*(psi_rPR[IDX2] - 2*psi_rPR[IDX1] +
+ psi_rPR[IDX3])
+ psi_i[FU] -= c2V*psi_r[PR]
 
 psi_r[FU,IDX1] = psi_r[PA,IDX1] - \
- c1*(psi_i[PR,IDX2] - 2*psi_i[PR,IDX1] +
- psi_i[PR,IDX3])
- psi_r[FU] = psi_r[FU] + c2V*psi_i[PR]
+ c1*(psi_iPR[IDX2] - 2*psi_iPR[IDX1] +
+ psi_iPR[IDX3])
+ psi_r[FU] += c2V*psi_i[PR]
 
 # Increment the time steps. PR -> PA and FU -> PR
- psi_r[PA] = psi_r[PR]
+ psi_r[PA] = psi_rPR
 psi_r[PR] = psi_r[FU]
- psi_i[PA] = psi_i[PR]
+ psi_i[PA] = psi_iPR
 psi_i[PR] = psi_i[FU]
 
 # Only plot after a few iterations to make the simulation run faster.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3626
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3626&view=rev
Author: fer_perez
Date: 2007年07月28日 23:50:34 -0700 (2007年7月28日)
Log Message:
-----------
Add energy display in the same units as the potential
Modified Paths:
--------------
 trunk/py4science/examples/schrodinger/schrod_fdtd.py
Modified: trunk/py4science/examples/schrodinger/schrod_fdtd.py
===================================================================
--- trunk/py4science/examples/schrodinger/schrod_fdtd.py	2007年07月28日 21:31:18 UTC (rev 3625)
+++ trunk/py4science/examples/schrodinger/schrod_fdtd.py	2007年07月29日 06:50:34 UTC (rev 3626)
@@ -88,7 +88,7 @@
 N = 1200 # Number of spatial points.
 T = 5*N # Number of time steps. 5*N is a nice value for terminating
 # before anything reaches the boundaries.
-Tp = 40 # Number of time steps to increment before updating the plot.
+Tp = 50 # Number of time steps to increment before updating the plot.
 dx = 1.0e0 # Spatial resolution
 m = 1.0e0 # Particle mass
 hbar = 1.0e0 # Plank's constant
@@ -98,7 +98,7 @@
 # and thickness (for barriers), you'll see the various transmission/reflection
 # regimes of quantum mechanical tunneling.
 V0 = 1.0e-2 # Potential amplitude (used for steps and barriers)
-THCK = 10 # "Thickness" of the potential barrier (if appropriate
+THCK = 15 # "Thickness" of the potential barrier (if appropriate
 # V-function is chosen)
 
 # Uncomment the potential type you want to use here:
@@ -108,12 +108,12 @@
 
 # Potential step. The height (V0) of the potential chosen above will determine
 # the amount of reflection/transmission you'll observe
-#POTENTIAL = 'step'
+POTENTIAL = 'step'
 
 # Potential barrier. Note that BOTH the potential height (V0) and thickness
 # of the barrier (THCK) affect the amount of tunneling vs reflection you'll
 # observe. 
-POTENTIAL = 'barrier'
+#POTENTIAL = 'barrier'
 
 # Initial wave function constants
 sigma = 40.0 # Standard deviation on the Gaussian envelope (remember Heisenberg
@@ -121,6 +121,11 @@
 x0 = round(N/2) - 5*sigma # Time shift
 k0 = np.pi/20 # Wavenumber (note that energy is a function of k)
 
+# Energy for a localized gaussian wavepacket interacting with a localized
+# potential (so the interaction term can be neglected by computing the energy
+# integral over a region where V=0)
+E = (hbar**2/2.0/m)*(k0**2+0.5/sigma**2)
+
 #=============================================================================
 # Code begins
 #
@@ -140,7 +145,7 @@
 
 # More simulation parameters. The maximum stable time step is a function of
 # the potential, V.
-Vmax = max(V) # Maximum potential of the domain.
+Vmax = V.max() # Maximum potential of the domain.
 dt = hbar/(2*hbar**2/(m*dx**2)+Vmax) # Critical time step.
 c1 = hbar*dt/(m*dx**2) # Constant coefficient 1.
 c2 = 2*dt/hbar # Constant coefficient 2.
@@ -148,6 +153,7 @@
 
 # Print summary info
 print 'One-dimensional Schrodinger equation - time evolution'
+print 'Wavepacket energy: ',E
 print 'Potential type: ',POTENTIAL
 print 'Potential height V0: ',V0
 print 'Barrier thickness: ',THCK
@@ -190,30 +196,40 @@
 
 # Initialize the figure and axes.
 pylab.figure()
+xmin = X.min()
+xmax = X.max()
 ymax = 1.5*(psi_r[PR]).max()
-pylab.axis([X.min(),X.max(),-ymax,ymax])
+pylab.axis([xmin,xmax,-ymax,ymax])
 
 # Initialize the plots with their own line objects. The figures plot MUCH
 # faster if you simply update the lines as opposed to redrawing the entire
 # figure. For reference, include the potential function as well.
-lineR, = pylab.plot(X,psi_r[PR],'b',alpha=0.7) # "Real" line
-lineI, = pylab.plot(X,psi_i[PR],'r',alpha=0.7) # "Imag" line.
-lineP, = pylab.plot(X,psi_p,'k') # "Probability" line
+lineR, = pylab.plot(X,psi_r[PR],'b',alpha=0.7,label='Real')
+lineI, = pylab.plot(X,psi_i[PR],'r',alpha=0.7,label='Imag')
+lineP, = pylab.plot(X,6*psi_p,'k',label='Prob')
 pylab.title('Potential height: %.2e' % V0)
-pylab.legend(('Real','Imag','Prob'))
 
 # For non-zero potentials, plot them and shade the classically forbidden region
-# in light red
-if V.max() !=0 :
- V_plot = V/V.max()*ymax/2
+# in light red, as well as drawing a green line at the wavepacket's total
+# energy, in the same units the potential is being plotted.
+if Vmax !=0 :
+ Efac = ymax/2.0/Vmax
+ V_plot = V*Efac
 pylab.plot(X,V_plot,':k',zorder=0) # Potential line.
 # reverse x and y2 so the polygon fills in order
 y1 = free(N) # lower boundary for polygon drawing
 x = np.concatenate( (X,X[::-1]) )
 y = np.concatenate( (y1,V_plot[::-1]) )
 pylab.fill(x, y, facecolor='y', alpha=0.2,zorder=0)
+ # Plot the wavefunction energy, in the same scale as the potential
+ pylab.axhline(E*Efac,color='g',label='Energy',zorder=1)
+pylab.legend(loc='lower right')
 pylab.draw()
 
+# I think there's a problem with pylab, because it resets the xlim after
+# plotting the E line. Fix it back manually.
+pylab.xlim(xmin,xmax)
+
 # Direct index assignment is MUCH faster than using a spatial FOR loop, so
 # these constants are used in the update equations. Remember that Python uses
 # zero-based indexing.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <fer...@us...> - 2007年07月28日 21:31:24
Revision: 3625
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3625&view=rev
Author: fer_perez
Date: 2007年07月28日 14:31:18 -0700 (2007年7月28日)
Log Message:
-----------
Add Schrodinger equation example, contributed by James Nagel <na...@me...>
Added Paths:
-----------
 trunk/py4science/examples/schrodinger/
 trunk/py4science/examples/schrodinger/Schrodinger_FDTD.pdf
 trunk/py4science/examples/schrodinger/schrod_fdtd.py
Added: trunk/py4science/examples/schrodinger/Schrodinger_FDTD.pdf
===================================================================
(Binary files differ)
Property changes on: trunk/py4science/examples/schrodinger/Schrodinger_FDTD.pdf
___________________________________________________________________
Name: svn:mime-type
 + application/octet-stream
Added: trunk/py4science/examples/schrodinger/schrod_fdtd.py
===================================================================
--- trunk/py4science/examples/schrodinger/schrod_fdtd.py	 (rev 0)
+++ trunk/py4science/examples/schrodinger/schrod_fdtd.py	2007年07月28日 21:31:18 UTC (rev 3625)
@@ -0,0 +1,258 @@
+#!/usr/bin/env python
+#=============================================================================
+#
+# Quantum Mechanical Simulation using Finite-Difference
+# Time-Domain (FDTD) Method
+#
+# This script simulates a probability wave in the presence of multiple
+# potentials. The simulation is c arried out by using the FDTD algorithm
+# applied to the Schrodinger equation. The program is intended to act as
+# a demonstration of the FDTD algorithm and can be used as an educational
+# aid for quantum mechanics and numerical methods. The simulation
+# parameters are defined in the code constants and can be freely
+# manipulated to see different behaviors.
+#
+# NOTES
+#
+# The probability density plots are amplified by a factor for visual
+# purposes. The psi_p quanity contains the actual probability density
+# without any rescaling.
+#
+# BEWARE: The time step, dt, has strict requirements or else the
+# simulation becomes unstable.
+#
+# The code has three built-in potential functions for demonstration.
+#
+# 1) Constant potential: Demonstrates a free particle with dispersion.
+#
+# 2) Step potential: Demonstrates transmission and reflection.
+#
+# 3) Potential barrier: Demonstrates tunneling.
+#
+# By tweaking the height of the potential (V0 below) as well as the
+# barrier thickness (THCK below), you can see different behaviors: full
+# reflection with no noticeable transmission, transmission and
+# reflection, or mostly transmission with tunneling.
+#
+# This script requires pylab and numpy to be installed with
+# Python or else it will not run.
+#
+#============================================================================
+# Author: James Nagel <na...@me...>
+# 5/25/07
+#
+# Updates by Fernando Perez <Fer...@co...>, 7/28/07
+#============================================================================
+
+# Numerical and plotting libraries
+import numpy as np
+import pylab
+
+# Set pylab to interactive mode so plots update when run outside ipython
+pylab.ion()
+
+#=============================================================================
+
+# Utility functions
+
+# Defines a quick Gaussian pulse function to act as an envelope to the wave
+# function.
+def Gaussian(x,t,sigma):
+ """ A Gaussian curve.
+ x = Variable
+ t = time shift
+ sigma = standard deviation """
+ return np.exp(-(x-t)**2/(2*sigma**2))
+
+def free(npts):
+ "Free particle."
+ return np.zeros(npts)
+
+def step(npts,v0):
+ "Potential step"
+ v = free(npts)
+ v[npts/2:] = v0
+ return v
+
+def barrier(npts,v0,thickness):
+ "Barrier potential"
+ v = free(npts)
+ v[npts/2:npts/2+thickness] = v0
+ return v
+
+#=============================================================================
+#
+# Simulation Constants. Be sure to include decimal points on appropriate
+# variables so they become floats instead of integers.
+#
+N = 1200 # Number of spatial points.
+T = 5*N # Number of time steps. 5*N is a nice value for terminating
+ # before anything reaches the boundaries.
+Tp = 40 # Number of time steps to increment before updating the plot.
+dx = 1.0e0 # Spatial resolution
+m = 1.0e0 # Particle mass
+hbar = 1.0e0 # Plank's constant
+X = dx*np.linspace(0,N,N) # Spatial axis.
+
+# Potential parameters. By playing with the type of potential and the height
+# and thickness (for barriers), you'll see the various transmission/reflection
+# regimes of quantum mechanical tunneling.
+V0 = 1.0e-2 # Potential amplitude (used for steps and barriers)
+THCK = 10 # "Thickness" of the potential barrier (if appropriate
+ # V-function is chosen)
+
+# Uncomment the potential type you want to use here:
+
+# Zero potential, packet propagates freely.
+#POTENTIAL = 'free'
+
+# Potential step. The height (V0) of the potential chosen above will determine
+# the amount of reflection/transmission you'll observe
+#POTENTIAL = 'step'
+
+# Potential barrier. Note that BOTH the potential height (V0) and thickness
+# of the barrier (THCK) affect the amount of tunneling vs reflection you'll
+# observe. 
+POTENTIAL = 'barrier'
+
+# Initial wave function constants
+sigma = 40.0 # Standard deviation on the Gaussian envelope (remember Heisenberg
+ # uncertainty).
+x0 = round(N/2) - 5*sigma # Time shift
+k0 = np.pi/20 # Wavenumber (note that energy is a function of k)
+
+#=============================================================================
+# Code begins
+#
+# You shouldn't need to change anything below unless you want to actually play
+# with the numerical algorithm or modify the plotting.
+#
+# Fill in the appropriate potential function (is there a Python equivalent to
+# the SWITCH statement?).
+if POTENTIAL=='free':
+ V = free(N)
+elif POTENTIAL=='step':
+ V = step(N,V0)
+elif POTENTIAL=='barrier':
+ V = barrier(N,V0,THCK)
+else:
+ raise ValueError("Unrecognized potential type: %s" % POTENTIAL)
+
+# More simulation parameters. The maximum stable time step is a function of
+# the potential, V.
+Vmax = max(V) # Maximum potential of the domain.
+dt = hbar/(2*hbar**2/(m*dx**2)+Vmax) # Critical time step.
+c1 = hbar*dt/(m*dx**2) # Constant coefficient 1.
+c2 = 2*dt/hbar # Constant coefficient 2.
+c2V = c2*V # pre-compute outside of update loop
+
+# Print summary info
+print 'One-dimensional Schrodinger equation - time evolution'
+print 'Potential type: ',POTENTIAL
+print 'Potential height V0: ',V0
+print 'Barrier thickness: ',THCK
+
+# Wave functions. Three states represent past, present, and future.
+psi_r = np.zeros((3,N)) # Real
+psi_i = np.zeros((3,N)) # Imaginary
+psi_p = np.zeros(N,) # Observable probability (magnitude-squared
+ # of the complex wave function).
+
+# Temporal indexing constants, used for accessing rows of the wavefunctions.
+PA = 0 # Past
+PR = 1 # Present
+FU = 2 # Future
+
+# Initialize wave function. A present-only state will "split" with half the
+# wave function propagating to the left and the other half to the right.
+# Including a "past" state will cause it to propagate one way.
+xn = range(1,N/2)
+x = X[xn]/dx # Normalized position coordinate
+gg = Gaussian(x,x0,sigma)
+cx = np.cos(k0*x)
+sx = np.sin(k0*x)
+psi_r[PR,xn] = cx*gg
+psi_i[PR,xn] = sx*gg
+psi_r[PA,xn] = cx*gg
+psi_i[PA,xn] = sx*gg
+
+# Initial normalization of wavefunctions
+# Compute the observable probability.
+psi_p = psi_r[PR]**2 + psi_i[PR]**2
+
+# Normalize the wave functions so that the total probability in the simulation
+# is equal to 1.
+P = dx * psi_p.sum() # Total probability.
+nrm = np.sqrt(P)
+psi_r /= nrm
+psi_i /= nrm
+psi_p /= P
+
+# Initialize the figure and axes.
+pylab.figure()
+ymax = 1.5*(psi_r[PR]).max()
+pylab.axis([X.min(),X.max(),-ymax,ymax])
+
+# Initialize the plots with their own line objects. The figures plot MUCH
+# faster if you simply update the lines as opposed to redrawing the entire
+# figure. For reference, include the potential function as well.
+lineR, = pylab.plot(X,psi_r[PR],'b',alpha=0.7) # "Real" line
+lineI, = pylab.plot(X,psi_i[PR],'r',alpha=0.7) # "Imag" line.
+lineP, = pylab.plot(X,psi_p,'k') # "Probability" line
+pylab.title('Potential height: %.2e' % V0)
+pylab.legend(('Real','Imag','Prob'))
+
+# For non-zero potentials, plot them and shade the classically forbidden region
+# in light red
+if V.max() !=0 :
+ V_plot = V/V.max()*ymax/2
+ pylab.plot(X,V_plot,':k',zorder=0) # Potential line.
+ # reverse x and y2 so the polygon fills in order
+ y1 = free(N) # lower boundary for polygon drawing
+ x = np.concatenate( (X,X[::-1]) )
+ y = np.concatenate( (y1,V_plot[::-1]) )
+ pylab.fill(x, y, facecolor='y', alpha=0.2,zorder=0)
+pylab.draw()
+
+# Direct index assignment is MUCH faster than using a spatial FOR loop, so
+# these constants are used in the update equations. Remember that Python uses
+# zero-based indexing.
+IDX1 = range(1,N-1) # psi [ k ]
+IDX2 = range(2,N) # psi [ k + 1 ]
+IDX3 = range(0,N-2) # psi [ k - 1 ]
+
+for t in range(0,T+1):
+ # Apply the update equations.
+ psi_i[FU,IDX1] = psi_i[PA,IDX1] + \
+ c1*(psi_r[PR,IDX2] - 2*psi_r[PR,IDX1] +
+ psi_r[PR,IDX3])
+ psi_i[FU] = psi_i[FU] - c2V*psi_r[PR]
+ 
+ psi_r[FU,IDX1] = psi_r[PA,IDX1] - \
+ c1*(psi_i[PR,IDX2] - 2*psi_i[PR,IDX1] +
+ psi_i[PR,IDX3])
+ psi_r[FU] = psi_r[FU] + c2V*psi_i[PR]
+
+ # Increment the time steps. PR -> PA and FU -> PR
+ psi_r[PA] = psi_r[PR]
+ psi_r[PR] = psi_r[FU]
+ psi_i[PA] = psi_i[PR]
+ psi_i[PR] = psi_i[FU]
+
+ # Only plot after a few iterations to make the simulation run faster.
+ if t % Tp == 0:
+ # Compute observable probability for the plot.
+ psi_p = psi_r[PR]**2 + psi_i[PR]**2
+
+ # Update the plots.
+ lineR.set_ydata(psi_r[PR])
+ lineI.set_ydata(psi_i[PR])
+ # Note: we plot the probability density amplified by a factor so it's a
+ # bit easier to see.
+ lineP.set_ydata(6*psi_p)
+ 
+ pylab.draw()
+
+# So the windows don't auto-close at the end if run outside ipython
+pylab.ioff()
+pylab.show()
Property changes on: trunk/py4science/examples/schrodinger/schrod_fdtd.py
___________________________________________________________________
Name: svn:executable
 + *
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <ef...@us...> - 2007年07月27日 23:34:33
Revision: 3624
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3624&view=rev
Author: efiring
Date: 2007年07月27日 16:34:29 -0700 (2007年7月27日)
Log Message:
-----------
tweaked cbook.dedent, inspired by Fernando's version
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/cbook.py
Modified: trunk/matplotlib/lib/matplotlib/cbook.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/cbook.py	2007年07月27日 15:45:26 UTC (rev 3623)
+++ trunk/matplotlib/lib/matplotlib/cbook.py	2007年07月27日 23:34:29 UTC (rev 3624)
@@ -543,6 +543,8 @@
 first line. It differs from textwrap.dedent in its
 deletion of leading blank lines and its use of the
 first non-blank line to determine the indentation.
+
+ It is also faster in most cases.
 """
 if not s: # includes case of s is None
 return ''
@@ -552,6 +554,9 @@
 ii += 1
 lines = lines[ii:]
 nshift = len(lines[0]) - len(lines[0].lstrip())
+ # Don't use first line in case of """blah...
+ if ii == 0 and len(lines) > 1:
+ nshift = len(lines[1]) - len(lines[1].lstrip())
 for i, line in enumerate(lines):
 nwhite = len(line) - len(line.lstrip())
 lines[i] = line[min(nshift, nwhite):]
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <ds...@us...> - 2007年07月27日 15:45:29
Revision: 3623
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3623&view=rev
Author: dsdale
Date: 2007年07月27日 08:45:26 -0700 (2007年7月27日)
Log Message:
-----------
added config module, for testing a traited config system
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc
Added Paths:
-----------
 trunk/matplotlib/lib/matplotlib/config/
 trunk/matplotlib/lib/matplotlib/config/__init__.py
 trunk/matplotlib/lib/matplotlib/config/api.py
 trunk/matplotlib/lib/matplotlib/config/checkdep.py
 trunk/matplotlib/lib/matplotlib/config/configobj.py
 trunk/matplotlib/lib/matplotlib/config/configtest.py
 trunk/matplotlib/lib/matplotlib/config/cutils.py
 trunk/matplotlib/lib/matplotlib/config/matplotlib.conf.default
 trunk/matplotlib/lib/matplotlib/config/mplconfig.py
 trunk/matplotlib/lib/matplotlib/config/mpltraits.py
 trunk/matplotlib/lib/matplotlib/config/rcparams.py
 trunk/matplotlib/lib/matplotlib/config/rcsetup.py
 trunk/matplotlib/lib/matplotlib/config/tconfig.py
 trunk/matplotlib/lib/matplotlib/config/verbose.py
 trunk/matplotlib/lib/matplotlib/mpl-data/matplotlib.conf
Added: trunk/matplotlib/lib/matplotlib/config/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/__init__.py	 (rev 0)
+++ trunk/matplotlib/lib/matplotlib/config/__init__.py	2007年07月27日 15:45:26 UTC (rev 3623)
@@ -0,0 +1 @@
+# Please keep this file empty
\ No newline at end of file
Property changes on: trunk/matplotlib/lib/matplotlib/config/__init__.py
___________________________________________________________________
Name: svn:eol-style
 + native
Added: trunk/matplotlib/lib/matplotlib/config/api.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/api.py	 (rev 0)
+++ trunk/matplotlib/lib/matplotlib/config/api.py	2007年07月27日 15:45:26 UTC (rev 3623)
@@ -0,0 +1,12 @@
+"""
+"""
+
+USE_NEW_CONFIG = True
+
+from rcparams import rc
+from cutils import get_config_file
+
+if USE_NEW_CONFIG:
+ from mplconfig import rcParams, mplConfig, save_config
+else:
+ from rcparams import rcParams
Property changes on: trunk/matplotlib/lib/matplotlib/config/api.py
___________________________________________________________________
Name: svn:eol-style
 + native
Added: trunk/matplotlib/lib/matplotlib/config/checkdep.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/checkdep.py	 (rev 0)
+++ trunk/matplotlib/lib/matplotlib/config/checkdep.py	2007年07月27日 15:45:26 UTC (rev 3623)
@@ -0,0 +1,133 @@
+import os, re, sys
+import distutils.version as version
+
+def dvipng():
+ try:
+ stdin, stdout = os.popen4('dvipng -version')
+ line = stdout.readlines()[1]
+ v = line.split()[-1]
+ float(v)
+ return v
+ except (IndexError, ValueError):
+ return None
+
+def ghostscript():
+ try:
+ if sys.platform == 'win32':
+ command = 'gswin32c -v'
+ else:
+ command = 'gs -v'
+ stdin, stdout = os.popen4(command)
+ line = stdout.readlines()[0]
+ v = line.split()[2]
+ vtest = '.'.join(v.split('.')[:2]) # deal with version numbers like '7.07.1'
+ float(vtest)
+ return vtest
+ except (IndexError, ValueError):
+ return None
+
+def tex():
+ try:
+ stdin, stdout = os.popen4('tex -version')
+ line = stdout.readlines()[0]
+ pattern = '3\.1\d+'
+ match = re.search(pattern, line)
+ v = match.group(0)
+ float(v)
+ return v
+ except (IndexError, ValueError):
+ return None
+
+def pdftops():
+ try:
+ stdin, stdout = os.popen4('pdftops -v')
+ for line in stdout.readlines():
+ if 'version' in line:
+ v = line.split()[-1]
+ float(v)
+ return v
+ except (IndexError, ValueError):
+ return None
+
+def compare_versions(a, b):
+ "return True if a is greater than or equal to b"
+ if a:
+ a = version.LooseVersion(a)
+ b = version.LooseVersion(b)
+ if a>=b: return True
+ else: return False
+ else: return False
+
+def ps_distiller(s):
+ if not s:
+ return False
+
+ flag = True
+ gs_req = '7.07'
+ gs_sugg = '7.07'
+ gs_v = ghostscript()
+ if compare_versions(gs_v, gs_sugg): pass
+ elif compare_versions(gs_v, gs_req):
+ verbose.report(('ghostscript-%s found. ghostscript-%s or later '
+ 'is recommended to use the ps.usedistiller option.') %\
+ (gs_v, gs_sugg))
+ else:
+ flag = False
+ warnings.warn(('matplotlibrc ps.usedistiller option can not be used '
+ 'unless ghostscript-%s or later is installed on your '
+ 'system.') % gs_req)
+
+ if s == 'xpdf':
+ pdftops_req = '3.0'
+ pdftops_v = pdftops()
+ if compare_versions(pdftops_v, pdftops_req): pass
+ else:
+ flag = False
+ warnings.warn(('matplotlibrc ps.usedistiller can not be set to '
+ 'xpdf unless xpdf-%s or later is installed on your '
+ 'system.') % pdftops_req)
+
+ if flag:
+ return s
+ else:
+ return False
+
+def usetex(s):
+ if not s:
+ return False
+
+ tex_req = '3.1415'
+ gs_req = '7.07'
+ gs_sugg = '7.07'
+ dvipng_req = '1.5'
+ flag = True
+
+ tex_v = tex()
+ if compare_versions(tex_v, tex_req): pass
+ else:
+ flag = False
+ warnings.warn(('matplotlibrc text.usetex option can not be used '
+ 'unless TeX-%s or later is '
+ 'installed on your system') % tex_req)
+
+ dvipng_v = dvipng()
+ if compare_versions(dvipng_v, dvipng_req): pass
+ else:
+ flag = False
+ warnings.warn( 'matplotlibrc text.usetex can not be used with *Agg '
+ 'backend unless dvipng-1.5 or later is '
+ 'installed on your system')
+
+ gs_v = ghostscript()
+ if compare_versions(gs_v, gs_sugg): pass
+ elif compare_versions(gs_v, gs_req):
+ verbose.report(('ghostscript-%s found. ghostscript-%s or later is '
+ 'recommended for use with the text.usetex '
+ 'option.') % (gs_v, gs_sugg))
+ else:
+ flag = False
+ warnings.warn(('matplotlibrc text.usetex can not be used '
+ 'unless ghostscript-%s or later is '
+ 'installed on your system') % gs_req)
+
+ return flag
\ No newline at end of file
Property changes on: trunk/matplotlib/lib/matplotlib/config/checkdep.py
___________________________________________________________________
Name: svn:eol-style
 + native
Added: trunk/matplotlib/lib/matplotlib/config/configobj.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/configobj.py	 (rev 0)
+++ trunk/matplotlib/lib/matplotlib/config/configobj.py	2007年07月27日 15:45:26 UTC (rev 3623)
@@ -0,0 +1,2279 @@
+# configobj.py
+# A config file reader/writer that supports nested sections in config files.
+# Copyright (C) 2005-2006 Michael Foord, Nicola Larosa
+# E-mail: fuzzyman AT voidspace DOT org DOT uk
+# nico AT tekNico DOT net
+
+# ConfigObj 4
+# http://www.voidspace.org.uk/python/configobj.html
+
+# Released subject to the BSD License
+# Please see http://www.voidspace.org.uk/python/license.shtml
+
+# Scripts maintained at http://www.voidspace.org.uk/python/index.shtml
+# For information about bugfixes, updates and support, please join the
+# ConfigObj mailing list:
+# http://lists.sourceforge.net/lists/listinfo/configobj-develop
+# Comments, suggestions and bug reports welcome.
+
+from __future__ import generators
+
+import sys
+INTP_VER = sys.version_info[:2]
+if INTP_VER < (2, 2):
+ raise RuntimeError("Python v.2.2 or later needed")
+
+import os, re
+compiler = None
+try:
+ import compiler
+except ImportError:
+ # for IronPython
+ pass
+from types import StringTypes
+from warnings import warn
+try:
+ from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE
+except ImportError:
+ # Python 2.2 does not have these
+ # UTF-8
+ BOM_UTF8 = '\xef\xbb\xbf'
+ # UTF-16, little endian
+ BOM_UTF16_LE = '\xff\xfe'
+ # UTF-16, big endian
+ BOM_UTF16_BE = '\xfe\xff'
+ if sys.byteorder == 'little':
+ # UTF-16, native endianness
+ BOM_UTF16 = BOM_UTF16_LE
+ else:
+ # UTF-16, native endianness
+ BOM_UTF16 = BOM_UTF16_BE
+
+# A dictionary mapping BOM to
+# the encoding to decode with, and what to set the
+# encoding attribute to.
+BOMS = {
+ BOM_UTF8: ('utf_8', None),
+ BOM_UTF16_BE: ('utf16_be', 'utf_16'),
+ BOM_UTF16_LE: ('utf16_le', 'utf_16'),
+ BOM_UTF16: ('utf_16', 'utf_16'),
+ }
+# All legal variants of the BOM codecs.
+# TODO: the list of aliases is not meant to be exhaustive, is there a
+# better way ?
+BOM_LIST = {
+ 'utf_16': 'utf_16',
+ 'u16': 'utf_16',
+ 'utf16': 'utf_16',
+ 'utf-16': 'utf_16',
+ 'utf16_be': 'utf16_be',
+ 'utf_16_be': 'utf16_be',
+ 'utf-16be': 'utf16_be',
+ 'utf16_le': 'utf16_le',
+ 'utf_16_le': 'utf16_le',
+ 'utf-16le': 'utf16_le',
+ 'utf_8': 'utf_8',
+ 'u8': 'utf_8',
+ 'utf': 'utf_8',
+ 'utf8': 'utf_8',
+ 'utf-8': 'utf_8',
+ }
+
+# Map of encodings to the BOM to write.
+BOM_SET = {
+ 'utf_8': BOM_UTF8,
+ 'utf_16': BOM_UTF16,
+ 'utf16_be': BOM_UTF16_BE,
+ 'utf16_le': BOM_UTF16_LE,
+ None: BOM_UTF8
+ }
+
+try:
+ from validate import VdtMissingValue
+except ImportError:
+ VdtMissingValue = None
+
+try:
+ enumerate
+except NameError:
+ def enumerate(obj):
+ """enumerate for Python 2.2."""
+ i = -1
+ for item in obj:
+ i += 1
+ yield i, item
+
+try:
+ True, False
+except NameError:
+ True, False = 1, 0
+
+
+__version__ = '4.4.0'
+
+__revision__ = '$Id: configobj.py 156 2006年01月31日 14:57:08Z fuzzyman $'
+
+__docformat__ = "restructuredtext en"
+
+__all__ = (
+ '__version__',
+ 'DEFAULT_INDENT_TYPE',
+ 'DEFAULT_INTERPOLATION',
+ 'ConfigObjError',
+ 'NestingError',
+ 'ParseError',
+ 'DuplicateError',
+ 'ConfigspecError',
+ 'ConfigObj',
+ 'SimpleVal',
+ 'InterpolationError',
+ 'InterpolationLoopError',
+ 'MissingInterpolationOption',
+ 'RepeatSectionError',
+ 'UnreprError',
+ 'UnknownType',
+ '__docformat__',
+ 'flatten_errors',
+)
+
+DEFAULT_INTERPOLATION = 'configparser'
+DEFAULT_INDENT_TYPE = ' '
+MAX_INTERPOL_DEPTH = 10
+
+OPTION_DEFAULTS = {
+ 'interpolation': True,
+ 'raise_errors': False,
+ 'list_values': True,
+ 'create_empty': False,
+ 'file_error': False,
+ 'configspec': None,
+ 'stringify': True,
+ # option may be set to one of ('', ' ', '\t')
+ 'indent_type': None,
+ 'encoding': None,
+ 'default_encoding': None,
+ 'unrepr': False,
+ 'write_empty_values': False,
+}
+
+
+def getObj(s):
+ s = "a=" + s
+ if compiler is None:
+ raise ImportError('compiler module not available')
+ p = compiler.parse(s)
+ return p.getChildren()[1].getChildren()[0].getChildren()[1]
+
+class UnknownType(Exception):
+ pass
+
+class Builder:
+ 
+ def build(self, o):
+ m = getattr(self, 'build_' + o.__class__.__name__, None)
+ if m is None:
+ raise UnknownType(o.__class__.__name__)
+ return m(o)
+ 
+ def build_List(self, o):
+ return map(self.build, o.getChildren())
+ 
+ def build_Const(self, o):
+ return o.value
+ 
+ def build_Dict(self, o):
+ d = {}
+ i = iter(map(self.build, o.getChildren()))
+ for el in i:
+ d[el] = i.next()
+ return d
+ 
+ def build_Tuple(self, o):
+ return tuple(self.build_List(o))
+ 
+ def build_Name(self, o):
+ if o.name == 'None':
+ return None
+ if o.name == 'True':
+ return True
+ if o.name == 'False':
+ return False
+ 
+ # An undefinted Name
+ raise UnknownType('Undefined Name')
+ 
+ def build_Add(self, o):
+ real, imag = map(self.build_Const, o.getChildren())
+ try:
+ real = float(real)
+ except TypeError:
+ raise UnknownType('Add')
+ if not isinstance(imag, complex) or imag.real != 0.0:
+ raise UnknownType('Add')
+ return real+imag
+ 
+ def build_Getattr(self, o):
+ parent = self.build(o.expr)
+ return getattr(parent, o.attrname)
+ 
+ def build_UnarySub(self, o):
+ return -self.build_Const(o.getChildren()[0])
+ 
+ def build_UnaryAdd(self, o):
+ return self.build_Const(o.getChildren()[0])
+
+def unrepr(s):
+ if not s:
+ return s
+ return Builder().build(getObj(s))
+
+def _splitlines(instring):
+ """Split a string on lines, without losing line endings or truncating."""
+ 
+
+class ConfigObjError(SyntaxError):
+ """
+ This is the base class for all errors that ConfigObj raises.
+ It is a subclass of SyntaxError.
+ """
+ def __init__(self, message='', line_number=None, line=''):
+ self.line = line
+ self.line_number = line_number
+ self.message = message
+ SyntaxError.__init__(self, message)
+
+class NestingError(ConfigObjError):
+ """
+ This error indicates a level of nesting that doesn't match.
+ """
+
+class ParseError(ConfigObjError):
+ """
+ This error indicates that a line is badly written.
+ It is neither a valid ``key = value`` line,
+ nor a valid section marker line.
+ """
+
+class DuplicateError(ConfigObjError):
+ """
+ The keyword or section specified already exists.
+ """
+
+class ConfigspecError(ConfigObjError):
+ """
+ An error occured whilst parsing a configspec.
+ """
+
+class InterpolationError(ConfigObjError):
+ """Base class for the two interpolation errors."""
+
+class InterpolationLoopError(InterpolationError):
+ """Maximum interpolation depth exceeded in string interpolation."""
+
+ def __init__(self, option):
+ InterpolationError.__init__(
+ self,
+ 'interpolation loop detected in value "%s".' % option)
+
+class RepeatSectionError(ConfigObjError):
+ """
+ This error indicates additional sections in a section with a
+ ``__many__`` (repeated) section.
+ """
+
+class MissingInterpolationOption(InterpolationError):
+ """A value specified for interpolation was missing."""
+
+ def __init__(self, option):
+ InterpolationError.__init__(
+ self,
+ 'missing option "%s" in interpolation.' % option)
+
+class UnreprError(ConfigObjError):
+ """An error parsing in unrepr mode."""
+
+
+class InterpolationEngine(object):
+ """
+ A helper class to help perform string interpolation.
+
+ This class is an abstract base class; its descendants perform
+ the actual work.
+ """
+
+ # compiled regexp to use in self.interpolate()
+ _KEYCRE = re.compile(r"%\(([^)]*)\)s")
+
+ def __init__(self, section):
+ # the Section instance that "owns" this engine
+ self.section = section
+
+ def interpolate(self, key, value):
+ def recursive_interpolate(key, value, section, backtrail):
+ """The function that does the actual work.
+
+ ``value``: the string we're trying to interpolate.
+ ``section``: the section in which that string was found
+ ``backtrail``: a dict to keep track of where we've been,
+ to detect and prevent infinite recursion loops
+
+ This is similar to a depth-first-search algorithm.
+ """
+ # Have we been here already?
+ if backtrail.has_key((key, section.name)):
+ # Yes - infinite loop detected
+ raise InterpolationLoopError(key)
+ # Place a marker on our backtrail so we won't come back here again
+ backtrail[(key, section.name)] = 1
+
+ # Now start the actual work
+ match = self._KEYCRE.search(value)
+ while match:
+ # The actual parsing of the match is implementation-dependent,
+ # so delegate to our helper function
+ k, v, s = self._parse_match(match)
+ if k is None:
+ # That's the signal that no further interpolation is needed
+ replacement = v
+ else:
+ # Further interpolation may be needed to obtain final value
+ replacement = recursive_interpolate(k, v, s, backtrail)
+ # Replace the matched string with its final value
+ start, end = match.span()
+ value = ''.join((value[:start], replacement, value[end:]))
+ new_search_start = start + len(replacement)
+ # Pick up the next interpolation key, if any, for next time
+ # through the while loop
+ match = self._KEYCRE.search(value, new_search_start)
+
+ # Now safe to come back here again; remove marker from backtrail
+ del backtrail[(key, section.name)]
+
+ return value
+
+ # Back in interpolate(), all we have to do is kick off the recursive
+ # function with appropriate starting values
+ value = recursive_interpolate(key, value, self.section, {})
+ return value
+
+ def _fetch(self, key):
+ """Helper function to fetch values from owning section.
+
+ Returns a 2-tuple: the value, and the section where it was found.
+ """
+ # switch off interpolation before we try and fetch anything !
+ save_interp = self.section.main.interpolation
+ self.section.main.interpolation = False
+
+ # Start at section that "owns" this InterpolationEngine
+ current_section = self.section
+ while True:
+ # try the current section first
+ val = current_section.get(key)
+ if val is not None:
+ break
+ # try "DEFAULT" next
+ val = current_section.get('DEFAULT', {}).get(key)
+ if val is not None:
+ break
+ # move up to parent and try again
+ # top-level's parent is itself
+ if current_section.parent is current_section:
+ # reached top level, time to give up
+ break
+ current_section = current_section.parent
+
+ # restore interpolation to previous value before returning
+ self.section.main.interpolation = save_interp
+ if val is None:
+ raise MissingInterpolationOption(key)
+ return val, current_section
+
+ def _parse_match(self, match):
+ """Implementation-dependent helper function.
+
+ Will be passed a match object corresponding to the interpolation
+ key we just found (e.g., "%(foo)s" or "$foo"). Should look up that
+ key in the appropriate config file section (using the ``_fetch()``
+ helper function) and return a 3-tuple: (key, value, section)
+
+ ``key`` is the name of the key we're looking for
+ ``value`` is the value found for that key
+ ``section`` is a reference to the section where it was found
+
+ ``key`` and ``section`` should be None if no further
+ interpolation should be performed on the resulting value
+ (e.g., if we interpolated "$$" and returned "$").
+ """
+ raise NotImplementedError
+ 
+
+class ConfigParserInterpolation(InterpolationEngine):
+ """Behaves like ConfigParser."""
+ _KEYCRE = re.compile(r"%\(([^)]*)\)s")
+
+ def _parse_match(self, match):
+ key = match.group(1)
+ value, section = self._fetch(key)
+ return key, value, section
+
+
+class TemplateInterpolation(InterpolationEngine):
+ """Behaves like string.Template."""
+ _delimiter = '$'
+ _KEYCRE = re.compile(r"""
+ \$(?:
+ (?P<escaped>\$) | # Two $ signs
+ (?P<named>[_a-z][_a-z0-9]*) | # $name format
+ {(?P<braced>[^}]*)} # ${name} format
+ )
+ """, re.IGNORECASE | re.VERBOSE)
+
+ def _parse_match(self, match):
+ # Valid name (in or out of braces): fetch value from section
+ key = match.group('named') or match.group('braced')
+ if key is not None:
+ value, section = self._fetch(key)
+ return key, value, section
+ # Escaped delimiter (e.g., $$): return single delimiter
+ if match.group('escaped') is not None:
+ # Return None for key and section to indicate it's time to stop
+ return None, self._delimiter, None
+ # Anything else: ignore completely, just return it unchanged
+ return None, match.group(), None
+
+interpolation_engines = {
+ 'configparser': ConfigParserInterpolation,
+ 'template': TemplateInterpolation,
+}
+
+class Section(dict):
+ """
+ A dictionary-like object that represents a section in a config file.
+ 
+ It does string interpolation if the 'interpolation' attribute
+ of the 'main' object is set to True.
+ 
+ Interpolation is tried first from this object, then from the 'DEFAULT'
+ section of this object, next from the parent and its 'DEFAULT' section,
+ and so on until the main object is reached.
+ 
+ A Section will behave like an ordered dictionary - following the
+ order of the ``scalars`` and ``sections`` attributes.
+ You can use this to change the order of members.
+ 
+ Iteration follows the order: scalars, then sections.
+ """
+
+ def __init__(self, parent, depth, main, indict=None, name=None):
+ """
+ * parent is the section above
+ * depth is the depth level of this section
+ * main is the main ConfigObj
+ * indict is a dictionary to initialise the section with
+ """
+ if indict is None:
+ indict = {}
+ dict.__init__(self)
+ # used for nesting level *and* interpolation
+ self.parent = parent
+ # used for the interpolation attribute
+ self.main = main
+ # level of nesting depth of this Section
+ self.depth = depth
+ # the sequence of scalar values in this Section
+ self.scalars = []
+ # the sequence of sections in this Section
+ self.sections = []
+ # purely for information
+ self.name = name
+ # for comments :-)
+ self.comments = {}
+ self.inline_comments = {}
+ # for the configspec
+ self.configspec = {}
+ self._order = []
+ self._configspec_comments = {}
+ self._configspec_inline_comments = {}
+ self._cs_section_comments = {}
+ self._cs_section_inline_comments = {}
+ # for defaults
+ self.defaults = []
+ #
+ # we do this explicitly so that __setitem__ is used properly
+ # (rather than just passing to ``dict.__init__``)
+ for entry in indict:
+ self[entry] = indict[entry]
+
+ def _interpolate(self, key, value):
+ try:
+ # do we already have an interpolation engine?
+ engine = self._interpolation_engine
+ except AttributeError:
+ # not yet: first time running _interpolate(), so pick the engine
+ name = self.main.interpolation
+ if name == True: # note that "if name:" would be incorrect here
+ # backwards-compatibility: interpolation=True means use default
+ name = DEFAULT_INTERPOLATION
+ name = name.lower() # so that "Template", "template", etc. all work
+ class_ = interpolation_engines.get(name, None)
+ if class_ is None:
+ # invalid value for self.main.interpolation
+ self.main.interpolation = False
+ return value
+ else:
+ # save reference to engine so we don't have to do this again
+ engine = self._interpolation_engine = class_(self)
+ # let the engine do the actual work
+ return engine.interpolate(key, value)
+
+ def __getitem__(self, key):
+ """Fetch the item and do string interpolation."""
+ val = dict.__getitem__(self, key)
+ if self.main.interpolation and isinstance(val, StringTypes):
+ return self._interpolate(key, val)
+ return val
+
+ def __setitem__(self, key, value, unrepr=False):
+ """
+ Correctly set a value.
+ 
+ Making dictionary values Section instances.
+ (We have to special case 'Section' instances - which are also dicts)
+ 
+ Keys must be strings.
+ Values need only be strings (or lists of strings) if
+ ``main.stringify`` is set.
+ 
+ `unrepr`` must be set when setting a value to a dictionary, without
+ creating a new sub-section.
+ """
+ if not isinstance(key, StringTypes):
+ raise ValueError, 'The key "%s" is not a string.' % key
+ # add the comment
+ if not self.comments.has_key(key):
+ self.comments[key] = []
+ self.inline_comments[key] = ''
+ # remove the entry from defaults
+ if key in self.defaults:
+ self.defaults.remove(key)
+ #
+ if isinstance(value, Section):
+ if not self.has_key(key):
+ self.sections.append(key)
+ dict.__setitem__(self, key, value)
+ elif isinstance(value, dict) and not unrepr:
+ # First create the new depth level,
+ # then create the section
+ if not self.has_key(key):
+ self.sections.append(key)
+ new_depth = self.depth + 1
+ dict.__setitem__(
+ self,
+ key,
+ Section(
+ self,
+ new_depth,
+ self.main,
+ indict=value,
+ name=key))
+ else:
+ if not self.has_key(key):
+ self.scalars.append(key)
+ if not self.main.stringify:
+ if isinstance(value, StringTypes):
+ pass
+ elif isinstance(value, (list, tuple)):
+ for entry in value:
+ if not isinstance(entry, StringTypes):
+ raise TypeError, (
+ 'Value is not a string "%s".' % entry)
+ else:
+ raise TypeError, 'Value is not a string "%s".' % value
+ dict.__setitem__(self, key, value)
+
+ def __delitem__(self, key):
+ """Remove items from the sequence when deleting."""
+ dict. __delitem__(self, key)
+ if key in self.scalars:
+ self.scalars.remove(key)
+ else:
+ self.sections.remove(key)
+ del self.comments[key]
+ del self.inline_comments[key]
+
+ def get(self, key, default=None):
+ """A version of ``get`` that doesn't bypass string interpolation."""
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ def update(self, indict):
+ """
+ A version of update that uses our ``__setitem__``.
+ """
+ for entry in indict:
+ self[entry] = indict[entry]
+
+ def pop(self, key, *args):
+ """ """
+ val = dict.pop(self, key, *args)
+ if key in self.scalars:
+ del self.comments[key]
+ del self.inline_comments[key]
+ self.scalars.remove(key)
+ elif key in self.sections:
+ del self.comments[key]
+ del self.inline_comments[key]
+ self.sections.remove(key)
+ if self.main.interpolation and isinstance(val, StringTypes):
+ return self._interpolate(key, val)
+ return val
+
+ def popitem(self):
+ """Pops the first (key,val)"""
+ sequence = (self.scalars + self.sections)
+ if not sequence:
+ raise KeyError, ": 'popitem(): dictionary is empty'"
+ key = sequence[0]
+ val = self[key]
+ del self[key]
+ return key, val
+
+ def clear(self):
+ """
+ A version of clear that also affects scalars/sections
+ Also clears comments and configspec.
+ 
+ Leaves other attributes alone :
+ depth/main/parent are not affected
+ """
+ dict.clear(self)
+ self.scalars = []
+ self.sections = []
+ self.comments = {}
+ self.inline_comments = {}
+ self.configspec = {}
+
+ def setdefault(self, key, default=None):
+ """A version of setdefault that sets sequence if appropriate."""
+ try:
+ return self[key]
+ except KeyError:
+ self[key] = default
+ return self[key]
+
+ def items(self):
+ """ """
+ return zip((self.scalars + self.sections), self.values())
+
+ def keys(self):
+ """ """
+ return (self.scalars + self.sections)
+
+ def values(self):
+ """ """
+ return [self[key] for key in (self.scalars + self.sections)]
+
+ def iteritems(self):
+ """ """
+ return iter(self.items())
+
+ def iterkeys(self):
+ """ """
+ return iter((self.scalars + self.sections))
+
+ __iter__ = iterkeys
+
+ def itervalues(self):
+ """ """
+ return iter(self.values())
+
+ def __repr__(self):
+ return '{%s}' % ', '.join([('%s: %s' % (repr(key), repr(self[key])))
+ for key in (self.scalars + self.sections)])
+
+ __str__ = __repr__
+
+ # Extra methods - not in a normal dictionary
+
+ def dict(self):
+ """
+ Return a deepcopy of self as a dictionary.
+ 
+ All members that are ``Section`` instances are recursively turned to
+ ordinary dictionaries - by calling their ``dict`` method.
+ 
+ >>> n = a.dict()
+ >>> n == a
+ 1
+ >>> n is a
+ 0
+ """
+ newdict = {}
+ for entry in self:
+ this_entry = self[entry]
+ if isinstance(this_entry, Section):
+ this_entry = this_entry.dict()
+ elif isinstance(this_entry, list):
+ # create a copy rather than a reference
+ this_entry = list(this_entry)
+ elif isinstance(this_entry, tuple):
+ # create a copy rather than a reference
+ this_entry = tuple(this_entry)
+ newdict[entry] = this_entry
+ return newdict
+
+ def merge(self, indict):
+ """
+ A recursive update - useful for merging config files.
+ 
+ >>> a = '''[section1]
+ ... option1 = True
+ ... [[subsection]]
+ ... more_options = False
+ ... # end of file'''.splitlines()
+ >>> b = '''# File is user.ini
+ ... [section1]
+ ... option1 = False
+ ... # end of file'''.splitlines()
+ >>> c1 = ConfigObj(b)
+ >>> c2 = ConfigObj(a)
+ >>> c2.merge(c1)
+ >>> c2
+ {'section1': {'option1': 'False', 'subsection': {'more_options': 'False'}}}
+ """
+ for key, val in indict.items():
+ if (key in self and isinstance(self[key], dict) and
+ isinstance(val, dict)):
+ self[key].merge(val)
+ else: 
+ self[key] = val
+
+ def rename(self, oldkey, newkey):
+ """
+ Change a keyname to another, without changing position in sequence.
+ 
+ Implemented so that transformations can be made on keys,
+ as well as on values. (used by encode and decode)
+ 
+ Also renames comments.
+ """
+ if oldkey in self.scalars:
+ the_list = self.scalars
+ elif oldkey in self.sections:
+ the_list = self.sections
+ else:
+ raise KeyError, 'Key "%s" not found.' % oldkey
+ pos = the_list.index(oldkey)
+ #
+ val = self[oldkey]
+ dict.__delitem__(self, oldkey)
+ dict.__setitem__(self, newkey, val)
+ the_list.remove(oldkey)
+ the_list.insert(pos, newkey)
+ comm = self.comments[oldkey]
+ inline_comment = self.inline_comments[oldkey]
+ del self.comments[oldkey]
+ del self.inline_comments[oldkey]
+ self.comments[newkey] = comm
+ self.inline_comments[newkey] = inline_comment
+
+ def walk(self, function, raise_errors=True,
+ call_on_sections=False, **keywargs):
+ """
+ Walk every member and call a function on the keyword and value.
+ 
+ Return a dictionary of the return values
+ 
+ If the function raises an exception, raise the errror
+ unless ``raise_errors=False``, in which case set the return value to
+ ``False``.
+ 
+ Any unrecognised keyword arguments you pass to walk, will be pased on
+ to the function you pass in.
+ 
+ Note: if ``call_on_sections`` is ``True`` then - on encountering a
+ subsection, *first* the function is called for the *whole* subsection,
+ and then recurses into it's members. This means your function must be
+ able to handle strings, dictionaries and lists. This allows you
+ to change the key of subsections as well as for ordinary members. The
+ return value when called on the whole subsection has to be discarded.
+ 
+ See the encode and decode methods for examples, including functions.
+ 
+ .. caution::
+ 
+ You can use ``walk`` to transform the names of members of a section
+ but you mustn't add or delete members.
+ 
+ >>> config = '''[XXXXsection]
+ ... XXXXkey = XXXXvalue'''.splitlines()
+ >>> cfg = ConfigObj(config)
+ >>> cfg
+ {'XXXXsection': {'XXXXkey': 'XXXXvalue'}}
+ >>> def transform(section, key):
+ ... val = section[key]
+ ... newkey = key.replace('XXXX', 'CLIENT1')
+ ... section.rename(key, newkey)
+ ... if isinstance(val, (tuple, list, dict)):
+ ... pass
+ ... else:
+ ... val = val.replace('XXXX', 'CLIENT1')
+ ... section[newkey] = val
+ >>> cfg.walk(transform, call_on_sections=True)
+ {'CLIENT1section': {'CLIENT1key': None}}
+ >>> cfg
+ {'CLIENT1section': {'CLIENT1key': 'CLIENT1value'}}
+ """
+ out = {}
+ # scalars first
+ for i in range(len(self.scalars)):
+ entry = self.scalars[i]
+ try:
+ val = function(self, entry, **keywargs)
+ # bound again in case name has changed
+ entry = self.scalars[i]
+ out[entry] = val
+ except Exception:
+ if raise_errors:
+ raise
+ else:
+ entry = self.scalars[i]
+ out[entry] = False
+ # then sections
+ for i in range(len(self.sections)):
+ entry = self.sections[i]
+ if call_on_sections:
+ try:
+ function(self, entry, **keywargs)
+ except Exception:
+ if raise_errors:
+ raise
+ else:
+ entry = self.sections[i]
+ out[entry] = False
+ # bound again in case name has changed
+ entry = self.sections[i]
+ # previous result is discarded
+ out[entry] = self[entry].walk(
+ function,
+ raise_errors=raise_errors,
+ call_on_sections=call_on_sections,
+ **keywargs)
+ return out
+
+ def decode(self, encoding):
+ """
+ Decode all strings and values to unicode, using the specified encoding.
+ 
+ Works with subsections and list values.
+ 
+ Uses the ``walk`` method.
+ 
+ Testing ``encode`` and ``decode``.
+ >>> m = ConfigObj(a)
+ >>> m.decode('ascii')
+ >>> def testuni(val):
+ ... for entry in val:
+ ... if not isinstance(entry, unicode):
+ ... print >> sys.stderr, type(entry)
+ ... raise AssertionError, 'decode failed.'
+ ... if isinstance(val[entry], dict):
+ ... testuni(val[entry])
+ ... elif not isinstance(val[entry], unicode):
+ ... raise AssertionError, 'decode failed.'
+ >>> testuni(m)
+ >>> m.encode('ascii')
+ >>> a == m
+ 1
+ """
+ warn('use of ``decode`` is deprecated.', DeprecationWarning)
+ def decode(section, key, encoding=encoding, warn=True):
+ """ """
+ val = section[key]
+ if isinstance(val, (list, tuple)):
+ newval = []
+ for entry in val:
+ newval.append(entry.decode(encoding))
+ elif isinstance(val, dict):
+ newval = val
+ else:
+ newval = val.decode(encoding)
+ newkey = key.decode(encoding)
+ section.rename(key, newkey)
+ section[newkey] = newval
+ # using ``call_on_sections`` allows us to modify section names
+ self.walk(decode, call_on_sections=True)
+
+ def encode(self, encoding):
+ """
+ Encode all strings and values from unicode,
+ using the specified encoding.
+ 
+ Works with subsections and list values.
+ Uses the ``walk`` method.
+ """
+ warn('use of ``encode`` is deprecated.', DeprecationWarning)
+ def encode(section, key, encoding=encoding):
+ """ """
+ val = section[key]
+ if isinstance(val, (list, tuple)):
+ newval = []
+ for entry in val:
+ newval.append(entry.encode(encoding))
+ elif isinstance(val, dict):
+ newval = val
+ else:
+ newval = val.encode(encoding)
+ newkey = key.encode(encoding)
+ section.rename(key, newkey)
+ section[newkey] = newval
+ self.walk(encode, call_on_sections=True)
+
+ def istrue(self, key):
+ """A deprecated version of ``as_bool``."""
+ warn('use of ``istrue`` is deprecated. Use ``as_bool`` method '
+ 'instead.', DeprecationWarning)
+ return self.as_bool(key)
+
+ def as_bool(self, key):
+ """
+ Accepts a key as input. The corresponding value must be a string or
+ the objects (``True`` or 1) or (``False`` or 0). We allow 0 and 1 to
+ retain compatibility with Python 2.2.
+ 
+ If the string is one of ``True``, ``On``, ``Yes``, or ``1`` it returns 
+ ``True``.
+ 
+ If the string is one of ``False``, ``Off``, ``No``, or ``0`` it returns 
+ ``False``.
+ 
+ ``as_bool`` is not case sensitive.
+ 
+ Any other input will raise a ``ValueError``.
+ 
+ >>> a = ConfigObj()
+ >>> a['a'] = 'fish'
+ >>> a.as_bool('a')
+ Traceback (most recent call last):
+ ValueError: Value "fish" is neither True nor False
+ >>> a['b'] = 'True'
+ >>> a.as_bool('b')
+ 1
+ >>> a['b'] = 'off'
+ >>> a.as_bool('b')
+ 0
+ """
+ val = self[key]
+ if val == True:
+ return True
+ elif val == False:
+ return False
+ else:
+ try:
+ if not isinstance(val, StringTypes):
+ raise KeyError
+ else:
+ return self.main._bools[val.lower()]
+ except KeyError:
+ raise ValueError('Value "%s" is neither True nor False' % val)
+
+ def as_int(self, key):
+ """
+ A convenience method which coerces the specified value to an integer.
+ 
+ If the value is an invalid literal for ``int``, a ``ValueError`` will
+ be raised.
+ 
+ >>> a = ConfigObj()
+ >>> a['a'] = 'fish'
+ >>> a.as_int('a')
+ Traceback (most recent call last):
+ ValueError: invalid literal for int(): fish
+ >>> a['b'] = '1'
+ >>> a.as_int('b')
+ 1
+ >>> a['b'] = '3.2'
+ >>> a.as_int('b')
+ Traceback (most recent call last):
+ ValueError: invalid literal for int(): 3.2
+ """
+ return int(self[key])
+
+ def as_float(self, key):
+ """
+ A convenience method which coerces the specified value to a float.
+ 
+ If the value is an invalid literal for ``float``, a ``ValueError`` will
+ be raised.
+ 
+ >>> a = ConfigObj()
+ >>> a['a'] = 'fish'
+ >>> a.as_float('a')
+ Traceback (most recent call last):
+ ValueError: invalid literal for float(): fish
+ >>> a['b'] = '1'
+ >>> a.as_float('b')
+ 1.0
+ >>> a['b'] = '3.2'
+ >>> a.as_float('b')
+ 3.2000000000000002
+ """
+ return float(self[key])
+ 
+
+class ConfigObj(Section):
+ """An object to read, create, and write config files."""
+
+ _keyword = re.compile(r'''^ # line start
+ (\s*) # indentation
+ ( # keyword
+ (?:".*?")| # double quotes
+ (?:'.*?')| # single quotes
+ (?:[^'"=].*?) # no quotes
+ )
+ \s*=\s* # divider
+ (.*) # value (including list values and comments)
+ $ # line end
+ ''',
+ re.VERBOSE)
+
+ _sectionmarker = re.compile(r'''^
+ (\s*) # 1: indentation
+ ((?:\[\s*)+) # 2: section marker open
+ ( # 3: section name open
+ (?:"\s*\S.*?\s*")| # at least one non-space with double quotes
+ (?:'\s*\S.*?\s*')| # at least one non-space with single quotes
+ (?:[^'"\s].*?) # at least one non-space unquoted
+ ) # section name close
+ ((?:\s*\])+) # 4: section marker close
+ \s*(\#.*)? # 5: optional comment
+ $''',
+ re.VERBOSE)
+
+ # this regexp pulls list values out as a single string
+ # or single values and comments
+ # FIXME: this regex adds a '' to the end of comma terminated lists
+ # workaround in ``_handle_value``
+ _valueexp = re.compile(r'''^
+ (?:
+ (?:
+ (
+ (?:
+ (?:
+ (?:".*?")| # double quotes
+ (?:'.*?')| # single quotes
+ (?:[^'",\#][^,\#]*?) # unquoted
+ )
+ \s*,\s* # comma
+ )* # match all list items ending in a comma (if any)
+ )
+ (
+ (?:".*?")| # double quotes
+ (?:'.*?')| # single quotes
+ (?:[^'",\#\s][^,]*?)| # unquoted
+ (?:(?<!,)) # Empty value
+ )? # last item in a list - or string value
+ )|
+ (,) # alternatively a single comma - empty list
+ )
+ \s*(\#.*)? # optional comment
+ $''',
+ re.VERBOSE)
+
+ # use findall to get the members of a list value
+ _listvalueexp = re.compile(r'''
+ (
+ (?:".*?")| # double quotes
+ (?:'.*?')| # single quotes
+ (?:[^'",\#].*?) # unquoted
+ )
+ \s*,\s* # comma
+ ''',
+ re.VERBOSE)
+
+ # this regexp is used for the value
+ # when lists are switched off
+ _nolistvalue = re.compile(r'''^
+ (
+ (?:".*?")| # double quotes
+ (?:'.*?')| # single quotes
+ (?:[^'"\#].*?)| # unquoted
+ (?:) # Empty value
+ )
+ \s*(\#.*)? # optional comment
+ $''',
+ re.VERBOSE)
+
+ # regexes for finding triple quoted values on one line
+ _single_line_single = re.compile(r"^'''(.*?)'''\s*(#.*)?$")
+ _single_line_double = re.compile(r'^"""(.*?)"""\s*(#.*)?$')
+ _multi_line_single = re.compile(r"^(.*?)'''\s*(#.*)?$")
+ _multi_line_double = re.compile(r'^(.*?)"""\s*(#.*)?$')
+
+ _triple_quote = {
+ "'''": (_single_line_single, _multi_line_single),
+ '"""': (_single_line_double, _multi_line_double),
+ }
+
+ # Used by the ``istrue`` Section method
+ _bools = {
+ 'yes': True, 'no': False,
+ 'on': True, 'off': False,
+ '1': True, '0': False,
+ 'true': True, 'false': False,
+ }
+
+ def __init__(self, infile=None, options=None, **kwargs):
+ """
+ Parse or create a config file object.
+ 
+ ``ConfigObj(infile=None, options=None, **kwargs)``
+ """
+ if infile is None:
+ infile = []
+ if options is None:
+ options = {}
+ else:
+ options = dict(options)
+ # keyword arguments take precedence over an options dictionary
+ options.update(kwargs)
+ # init the superclass
+ Section.__init__(self, self, 0, self)
+ #
+ defaults = OPTION_DEFAULTS.copy()
+ for entry in options.keys():
+ if entry not in defaults.keys():
+ raise TypeError, 'Unrecognised option "%s".' % entry
+ # TODO: check the values too.
+ #
+ # Add any explicit options to the defaults
+ defaults.update(options)
+ #
+ # initialise a few variables
+ self.filename = None
+ self._errors = []
+ self.raise_errors = defaults['raise_errors']
+ self.interpolation = defaults['interpolation']
+ self.list_values = defaults['list_values']
+ self.create_empty = defaults['create_empty']
+ self.file_error = defaults['file_error']
+ self.stringify = defaults['stringify']
+ self.indent_type = defaults['indent_type']
+ self.encoding = defaults['encoding']
+ self.default_encoding = defaults['default_encoding']
+ self.BOM = False
+ self.newlines = None
+ self.write_empty_values = defaults['write_empty_values']
+ self.unrepr = defaults['unrepr']
+ #
+ self.initial_comment = []
+ self.final_comment = []
+ #
+ self._terminated = False
+ #
+ if isinstance(infile, StringTypes):
+ self.filename = infile
+ if os.path.isfile(infile):
+ infile = open(infile).read() or []
+ elif self.file_error:
+ # raise an error if the file doesn't exist
+ raise IOError, 'Config file not found: "%s".' % self.filename
+ else:
+ # file doesn't already exist
+ if self.create_empty:
+ # this is a good test that the filename specified
+ # isn't impossible - like on a non existent device
+ h = open(infile, 'w')
+ h.write('')
+ h.close()
+ infile = []
+ elif isinstance(infile, (list, tuple)):
+ infile = list(infile)
+ elif isinstance(infile, dict):
+ # initialise self
+ # the Section class handles creating subsections
+ if isinstance(infile, ConfigObj):
+ # get a copy of our ConfigObj
+ infile = infile.dict()
+ for entry in infile:
+ self[entry] = infile[entry]
+ del self._errors
+ if defaults['configspec'] is not None:
+ self._handle_configspec(defaults['configspec'])
+ else:
+ self.configspec = None
+ return
+ elif hasattr(infile, 'read'):
+ # This supports file like objects
+ infile = infile.read() or []
+ # needs splitting into lines - but needs doing *after* decoding
+ # in case it's not an 8 bit encoding
+ else:
+ raise TypeError, ('infile must be a filename,'
+ ' file like object, or list of lines.')
+ #
+ if infile:
+ # don't do it for the empty ConfigObj
+ infile = self._handle_bom(infile)
+ # infile is now *always* a list
+ #
+ # Set the newlines attribute (first line ending it finds)
+ # and strip trailing '\n' or '\r' from lines
+ for line in infile:
+ if (not line) or (line[-1] not in ('\r', '\n', '\r\n')):
+ continue
+ for end in ('\r\n', '\n', '\r'):
+ if line.endswith(end):
+ self.newlines = end
+ break
+ break
+ if infile[-1] and infile[-1] in ('\r', '\n', '\r\n'):
+ self._terminated = True
+ infile = [line.rstrip('\r\n') for line in infile]
+ #
+ self._parse(infile)
+ # if we had any errors, now is the time to raise them
+ if self._errors:
+ info = "at line %s." % self._errors[0].line_number
+ if len(self._errors) > 1:
+ msg = ("Parsing failed with several errors.\nFirst error %s" %
+ info)
+ error = ConfigObjError(msg)
+ else:
+ error = self._errors[0]
+ # set the errors attribute; it's a list of tuples:
+ # (error_type, message, line_number)
+ error.errors = self._errors
+ # set the config attribute
+ error.config = self
+ raise error
+ # delete private attributes
+ del self._errors
+ #
+ if defaults['configspec'] is None:
+ self.configspec = None
+ else:
+ self._handle_configspec(defaults['configspec'])
+ 
+ def __repr__(self):
+ return 'ConfigObj({%s})' % ', '.join(
+ [('%s: %s' % (repr(key), repr(self[key]))) for key in
+ (self.scalars + self.sections)])
+ 
+ def _handle_bom(self, infile):
+ """
+ Handle any BOM, and decode if necessary.
+ 
+ If an encoding is specified, that *must* be used - but the BOM should
+ still be removed (and the BOM attribute set).
+ 
+ (If the encoding is wrongly specified, then a BOM for an alternative
+ encoding won't be discovered or removed.)
+ 
+ If an encoding is not specified, UTF8 or UTF16 BOM will be detected and
+ removed. The BOM attribute will be set. UTF16 will be decoded to
+ unicode.
+ 
+ NOTE: This method must not be called with an empty ``infile``.
+ 
+ Specifying the *wrong* encoding is likely to cause a
+ ``UnicodeDecodeError``.
+ 
+ ``infile`` must always be returned as a list of lines, but may be
+ passed in as a single string.
+ """
+ if ((self.encoding is not None) and
+ (self.encoding.lower() not in BOM_LIST)):
+ # No need to check for a BOM
+ # the encoding specified doesn't have one
+ # just decode
+ return self._decode(infile, self.encoding)
+ #
+ if isinstance(infile, (list, tuple)):
+ line = infile[0]
+ else:
+ line = infile
+ if self.encoding is not None:
+ # encoding explicitly supplied
+ # And it could have an associated BOM
+ # TODO: if encoding is just UTF16 - we ought to check for both
+ # TODO: big endian and little endian versions.
+ enc = BOM_LIST[self.encoding.lower()]
+ if enc == 'utf_16':
+ # For UTF16 we try big endian and little endian
+ for BOM, (encoding, final_encoding) in BOMS.items():
+ if not final_encoding:
+ # skip UTF8
+ continue
+ if infile.startswith(BOM):
+ ### BOM discovered
+ ##self.BOM = True
+ # Don't need to remove BOM
+ return self._decode(infile, encoding)
+ #
+ # If we get this far, will *probably* raise a DecodeError
+ # As it doesn't appear to start with a BOM
+ return self._decode(infile, self.encoding)
+ #
+ # Must be UTF8
+ BOM = BOM_SET[enc]
+ if not line.startswith(BOM):
+ return self._decode(infile, self.encoding)
+ #
+ newline = line[len(BOM):]
+ #
+ # BOM removed
+ if isinstance(infile, (list, tuple)):
+ infile[0] = newline
+ else:
+ infile = newline
+ self.BOM = True
+ return self._decode(infile, self.encoding)
+ #
+ # No encoding specified - so we need to check for UTF8/UTF16
+ for BOM, (encoding, final_encoding) in BOMS.items():
+ if not line.startswith(BOM):
+ continue
+ else:
+ # BOM discovered
+ self.encoding = final_encoding
+ if not final_encoding:
+ self.BOM = True
+ # UTF8
+ # remove BOM
+ newline = line[len(BOM):]
+ if isinstance(infile, (list, tuple)):
+ infile[0] = newline
+ else:
+ infile = newline
+ # UTF8 - don't decode
+ if isinstance(infile, StringTypes):
+ return infile.splitlines(True)
+ else:
+ return infile
+ # UTF16 - have to decode
+ return self._decode(infile, encoding)
+ #
+ # No BOM discovered and no encoding specified, just return
+ if isinstance(infile, StringTypes):
+ # infile read from a file will be a single string
+ return infile.splitlines(True)
+ else:
+ return infile
+
+ def _a_to_u(self, aString):
+ """Decode ASCII strings to unicode if a self.encoding is specified."""
+ if self.encoding:
+ return aString.decode('ascii')
+ else:
+ return aString
+
+ def _decode(self, infile, encoding):
+ """
+ Decode infile to unicode. Using the specified encoding.
+ 
+ if is a string, it also needs converting to a list.
+ """
+ if isinstance(infile, StringTypes):
+ # can't be unicode
+ # NOTE: Could raise a ``UnicodeDecodeError``
+ return infile.decode(encoding).splitlines(True)
+ for i, line in enumerate(infile):
+ if not isinstance(line, unicode):
+ # NOTE: The isinstance test here handles mixed lists of unicode/string
+ # NOTE: But the decode will break on any non-string values
+ # NOTE: Or could raise a ``UnicodeDecodeError``
+ infile[i] = line.decode(encoding)
+ return infile
+
+ def _decode_element(self, line):
+ """Decode element to unicode if necessary."""
+ if not self.encoding:
+ return line
+ if isinstance(line, str) and self.default_encoding:
+ return line.decode(self.default_encoding)
+ return line
+
+ def _str(self, value):
+ """
+ Used by ``stringify`` within validate, to turn non-string values
+ into strings.
+ """
+ if not isinstance(value, StringTypes):
+ return str(value)
+ else:
+ return value
+
+ def _parse(self, infile):
+ """Actually parse the config file."""
+ temp_list_values = self.list_values
+ if self.unrepr:
+ self.list_values = False
+ comment_list = []
+ done_start = False
+ this_section = self
+ maxline = len(infile) - 1
+ cur_index = -1
+ reset_comment = False
+ while cur_index < maxline:
+ if reset_comment:
+ comment_list = []
+ cur_index += 1
+ line = infile[cur_index]
+ sline = line.strip()
+ # do we have anything on the line ?
+ if not sline or sline.startswith('#'):
+ reset_comment = False
+ comment_list.append(line)
+ continue
+ if not done_start:
+ # preserve initial comment
+ self.initial_comment = comment_list
+ comment_list = []
+ done_start = True
+ reset_comment = True
+ # first we check if it's a section marker
+ mat = self._sectionmarker.match(line)
+ if mat is not None:
+ # is a section line
+ (indent, sect_open, sect_name, sect_close, comment) = (
+ mat.groups())
+ if indent and (self.indent_type is None):
+ self.indent_type = indent
+ cur_depth = sect_open.count('[')
+ if cur_depth != sect_close.count(']'):
+ self._handle_error(
+ "Cannot compute the section depth at line %s.",
+ NestingError, infile, cur_index)
+ continue
+ #
+ if cur_depth < this_section.depth:
+ # the new section is dropping back to a previous level
+ try:
+ parent = self._match_depth(
+ this_section,
+ cur_depth).parent
+ except SyntaxError:
+ self._handle_error(
+ "Cannot compute nesting level at line %s.",
+ NestingError, infile, cur_index)
+ continue
+ elif cur_depth == this_section.depth:
+ # the new section is a sibling of the current section
+ parent = this_section.parent
+ elif cur_depth == this_section.depth + 1:
+ # the new section is a child the current section
+ parent = this_section
+ else:
+ self._handle_error(
+ "Section too nested at line %s.",
+ NestingError, infile, cur_index)
+ #
+ sect_name = self._unquote(sect_name)
+ if parent.has_key(sect_name):
+ self._handle_error(
+ 'Duplicate section name at line %s.',
+ DuplicateError, infile, cur_index)
+ continue
+ # create the new section
+ this_section = Section(
+ parent,
+ cur_depth,
+ self,
+ name=sect_name)
+ parent[sect_name] = this_section
+ parent.inline_comments[sect_name] = comment
+ parent.comments[sect_name] = comment_list
+ continue
+ #
+ # it's not a section...
 
[truncated message content]
Revision: 3622
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3622&view=rev
Author: jouni
Date: 2007年07月26日 14:13:58 -0700 (2007年7月26日)
Log Message:
-----------
Numpy has isfinite, unlike the old numerix
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2007年07月26日 19:44:35 UTC (rev 3621)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2007年07月26日 21:13:58 UTC (rev 3622)
@@ -112,7 +112,7 @@
 # need to use %f with some precision. Perhaps the precision
 # should adapt to the magnitude of the number?
 elif isinstance(obj, float):
- if npy.isnan(obj) or obj in (-npy.inf, npy.inf):
+ if not npy.isfinite(obj):
 raise ValueError, "Can only output finite numbers in PDF"
 r = "%.10f" % obj
 return r.rstrip('0').rstrip('.')
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3621
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3621&view=rev
Author: mdboom
Date: 2007年07月26日 12:44:35 -0700 (2007年7月26日)
Log Message:
-----------
Some examples to go with the last commit.
Modified Paths:
--------------
 trunk/matplotlib/examples/mathtext_examples.py
Modified: trunk/matplotlib/examples/mathtext_examples.py
===================================================================
--- trunk/matplotlib/examples/mathtext_examples.py	2007年07月26日 19:44:09 UTC (rev 3620)
+++ trunk/matplotlib/examples/mathtext_examples.py	2007年07月26日 19:44:35 UTC (rev 3621)
@@ -7,7 +7,7 @@
 r'$x y$',
 r'$x+y\ x=y\ x<y\ x:y\ x,y\ x@y$',
 r'100ドル\%y\ x*y\ x/y x\$y$',
- r'$x\leftarrow y\ x\forall y$',
+ r'$x\leftarrow y\ x\forall y\ x-y$',
 r'$x \sf x \bf x {\cal X} \rm x$',
 r'$\{ \rm braces \}$',
 r'$\left[\left\lfloor\frac{5}{\frac{\left(3\right)}{4}} y\right)\right]$',
@@ -30,8 +30,13 @@
 r'$_i$',
 r"$\arccos((x^i))$",
 r"$\gamma = \frac{x=\frac{6}{8}}{y} \delta$",
- r'$\"o\ddot o \'e\`e\~n\.x\^y$',
- 
+ r'$\limsup_{x\to\infty}$',
+ r'$\oint^\infty_0$',
+ r"$f'$",
+ r'$\frac{x_2888}{y}$',
+ r"$\sqrt[3]{\frac{X_2}{Y}}=5$",
+ r"$\sqrt[3]{x}=5$",
+ r'$\frac{X}{\frac{X}{Y}}$'
 ]
 
 from pylab import *
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年07月26日 19:44:15
Revision: 3620
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3620&view=rev
Author: mdboom
Date: 2007年07月26日 12:44:09 -0700 (2007年7月26日)
Log Message:
-----------
Lots of sizing and layout tweaks. Support $\sqrt[3]{foo}. The line
meets up with the check mark rather clumsily on the Agg backends due
to rounding errors and lack of subpixel placement... will look into that.
Modified Paths:
--------------
 trunk/matplotlib/CHANGELOG
 trunk/matplotlib/lib/matplotlib/_mathtext_data.py
 trunk/matplotlib/lib/matplotlib/mathtext.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG	2007年07月26日 18:40:36 UTC (rev 3619)
+++ trunk/matplotlib/CHANGELOG	2007年07月26日 19:44:09 UTC (rev 3620)
@@ -23,8 +23,11 @@
 	 - Double sub/superscripts (eg. $x_i_j$) are considered
 ambiguous and raise an exception. Use braces to disambiguate.
 
-	 - $\frac{x}{y}$ can be used for displaying fractions
+	 - $\frac{x}{y}$ can be used for displaying fractions.
 
+	 - $\sqrt[3]{x}$ can be used to display the radical symbol
+ with a root number and body.
+
 	 - $\left(\frac{x}{y}\right)$ may be used to create
 parentheses and other delimiters that automatically
 resize to the height of their contents.
Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/_mathtext_data.py	2007年07月26日 18:40:36 UTC (rev 3619)
+++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py	2007年07月26日 19:44:09 UTC (rev 3620)
@@ -170,6 +170,7 @@
 r'\swarrow' : ('cmsy10', 116),
 r'\propto' : ('cmsy10', 15),
 r'\prime' : ('cmsy10', 73),
+ r"'" : ('cmsy10', 73),
 r'\infty' : ('cmsy10', 32),
 r'\in' : ('cmsy10', 59),
 r'\ni' : ('cmsy10', 122),
@@ -253,6 +254,7 @@
 r'\prec' : ('cmsy10', 93),
 r'\succ' : ('cmsy10', 49),
 r'\rightarrow' : ('cmsy10', 12),
+ r'\to' : ('cmsy10', 12),
 r'\spadesuit' : ('cmsy10', 7),
 }
 
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py	2007年07月26日 18:40:36 UTC (rev 3619)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py	2007年07月26日 19:44:09 UTC (rev 3620)
@@ -138,7 +138,8 @@
 from matplotlib.pyparsing import Literal, Word, OneOrMore, ZeroOrMore, \
 Combine, Group, Optional, Forward, NotAny, alphas, nums, alphanums, \
 StringStart, StringEnd, ParseFatalException, FollowedBy, Regex, \
- operatorPrecedence, opAssoc, ParseResults, Or, Suppress, oneOf
+ operatorPrecedence, opAssoc, ParseResults, Or, Suppress, oneOf, \
+ ParseException, MatchFirst
 
 from matplotlib.afm import AFM
 from matplotlib.cbook import enumerate, iterable, Bunch, get_realpath_and_stat, \
@@ -151,13 +152,7 @@
 
 ####################
 
-# symbols that have the sub and superscripts over/under
-overunder_symbols = {
- r'\sum' : 1,
- r'\int' : 1,
- r'\prod' : 1,
- r'\coprod' : 1,
- }
+ 
 # a character over another character
 charOverChars = {
 # The first 2 entires in the tuple are (font, char, sizescale) for
@@ -692,7 +687,11 @@
 def render_rect_filled(self, x1, y1, x2, y2):
 assert len(self.fonts)
 font = self.fonts.values()[0]
- font.font.draw_rect_filled(x1, y1, max(x2 - 1, x1), max(y2 - 1, y1))
+ font.font.draw_rect_filled(
+ max(0, x1 - 1),
+ y1,
+ max(x2 - 1, x1),
+ max(y2 - 1, y1))
 
 def get_used_characters(self):
 return self.used_characters
@@ -956,14 +955,16 @@
 # The number of different sizes of chars to use, beyond which they will not
 # get any smaller
 NUM_SIZE_LEVELS = 3
-# Percentage of x-height that subscripts drop below the baseline
-SUBDROP = 0.05
+# Percentage of x-height of additional horiz. space after sub/superscripts
+SCRIPT_SPACE = 0.3
+# Percentage of x-height that sub/superscripts drop below the baseline
+SUBDROP = 0.4
 # Percentage of x-height that superscripts drop below the baseline
-SUP1 = 0.2
+SUP1 = 0.7
 # Percentage of x-height that subscripts drop below the baseline
-SUB1 = 0.3
+SUB1 = 0.0
 # Percentage of x-height that superscripts are offset relative to the subscript
-DELTA = 0.05
+DELTA = 0.1
 
 class MathTextWarning(Warning):
 pass
@@ -991,10 +992,6 @@
 def set_link(self, other):
 self.link = other
 
- def pack(self):
- if self.link:
- self.link.pack()
-
 def shrink(self):
 """Shrinks one level smaller. There are only three levels of sizes,
 after which things will no longer get smaller."""
@@ -1062,7 +1059,10 @@
 def _update_metrics(self):
 metrics = self._metrics = self.font_output.get_metrics(
 self.font, self.c, self.fontsize, self.dpi)
- self.width = metrics.width
+ if self.c == ' ':
+ self.width = metrics.advance
+ else:
+ self.width = metrics.width
 self.height = metrics.iceberg
 self.depth = -(metrics.iceberg - metrics.height)
 
@@ -1124,7 +1124,9 @@
 elem = next
 
 def __repr__(self):
- s = '[' + self.__internal_repr__() + " <%d %d %d %d> " % (self.width, self.height, self.depth, self.shift_amount)
+ s = '[%s <%d %d %d %d> ' % (self.__internal_repr__(),
+ self.width, self.height,
+ self.depth, self.shift_amount)
 if self.list_head:
 s += ' ' + self.list_head.__repr__()
 s += ']'
@@ -1162,6 +1164,7 @@
 Box.shrink(self)
 if self.size < NUM_SIZE_LEVELS:
 self.shift_amount *= SHRINK_FACTOR
+ self.glue_set *= SHRINK_FACTOR
 
 class Hlist(List):
 """A horizontal list of boxes.
@@ -1186,12 +1189,6 @@
 kern.link = next
 elem = next
 
- def pack(self):
- if self.list_head:
- self.list_head.pack()
- self.hpack()
- Node.pack(self)
- 
 def hpack(self, w=0., m='additional'):
 """The main duty of hpack is to compute the dimensions of the
 resulting boxes, and to adjust the glue if one of those dimensions is
@@ -1265,12 +1262,6 @@
 List.__init__(self, elements)
 self.vpack()
 
- def pack(self):
- if self.list_head:
- self.list_head.pack()
- self.vpack()
- Node.pack(self)
- 
 def vpack(self, h=0., m='additional', l=float('inf')):
 """The main duty of vpack is to compute the dimensions of the
 resulting boxes, and to adjust the glue if one of those dimensions is
@@ -1386,6 +1377,13 @@
 glue_spec = glue_spec.copy()
 self.glue_spec = glue_spec
 
+ def shrink(self):
+ Node.shrink(self)
+ if self.size < NUM_SIZE_LEVELS:
+ if self.glue_spec.width != 0.:
+ self.glue_spec = self.glue_spec.copy()
+ self.glue_spec.width *= SHRINK_FACTOR
+ 
 class GlueSpec(object):
 """@150, @151"""
 def __init__(self, width=0., stretch=0., stretch_order=0, shrink=0., shrink_order=0):
@@ -1406,7 +1404,7 @@
 def factory(cls, glue_type):
 return cls._types[glue_type]
 factory = classmethod(factory)
-
+ 
 GlueSpec._types = {
 'fil': GlueSpec(0., 1., 1, 0., 0),
 'fill': GlueSpec(0., 1., 2, 0., 0),
@@ -1444,11 +1442,6 @@
 def __init__(self):
 Glue.__init__(self, 'neg_filll')
 
-class FixedGlue(Glue):
- def __init__(self, width):
- Glue.__init__(self, 'empty', copy=True)
- self.glue_spec.width = width
-
 class SsGlue(Glue):
 def __init__(self):
 Glue.__init__(self, 'ss')
@@ -1463,7 +1456,7 @@
 """A convenience class to create an Vlist whose contents are centered
 within its enclosing box."""
 def __init__(self, elements):
- Vlist.__init__(self, [Fill()] + elements + [Fill()])
+ Vlist.__init__(self, [SsGlue()] + elements + [SsGlue()])
 
 class Kern(Node):
 """A Kern node has a width field to specify a (normally negative)
@@ -1668,7 +1661,7 @@
 
 class Parser(object):
 _binary_operators = Set(r'''
- + - *
+ + *
 \pm \sqcap \rhd
 \mp \sqcup \unlhd
 \times \vee \unrhd
@@ -1711,6 +1704,16 @@
 _spaced_symbols = _binary_operators | _relation_symbols | _arrow_symbols
 
 _punctuation_symbols = Set(r', ; . ! \ldotp \cdotp'.split())
+
+ _overunder_symbols = Set(r'''
+ \sum \int \prod \coprod \oint \bigcap \bigcup \bigsqcup \bigvee
+ \bigwedge \bigodot \bigotimes \bigoplus \biguplus
+ '''.split()
+ )
+
+ _overunder_functions = Set(
+ r"lim liminf limsup sup max min".split()
+ )
 
 def __init__(self):
 # All forward declarations are here
@@ -1761,14 +1764,14 @@
 r"[a-zA-Z0-9 ]",
 r"[+\-*/]",
 r"[<>=]",
- r"[:,.;!]",
- r"[!@%&]",
- r"[[\]()]",
+ r"[:,.;!'@[()]",
 r"\\[$%{}]",
 ])
 + ")"
 ).setParseAction(self.symbol).leaveWhitespace()
 
+ rightBracket = Literal("[").setParseAction(self.symbol).leaveWhitespace()
+
 accent = Group(
 Combine(bslash + accent)
 + placeable
@@ -1800,11 +1803,30 @@
 + group
 ).setParseAction(self.frac).setName("frac")
 
+ sqrt = Group(
+ Suppress(
+ bslash
+ + Literal("sqrt")
+ )
+ + Optional(
+ Suppress(Literal("["))
+ + OneOrMore(
+ symbol
+ ^ font
+ )
+ + Suppress(Literal("]")),
+ default = None
+ )
+ + group
+ ).setParseAction(self.sqrt).setName("sqrt")
+
 placeable <<(accent
 ^ function 
 ^ symbol
+ ^ rightBracket
 ^ group
 ^ frac
+ ^ sqrt
 )
 
 simple <<(space
@@ -1939,7 +1961,10 @@
 elif c in self._punctuation_symbols:
 return [Hlist([Char(c, self.get_state()),
 self._make_space(0.3)])]
- return [Char(toks[0], self.get_state())]
+ try:
+ return [Char(toks[0], self.get_state())]
+ except:
+ raise ParseException()
 
 _accent_map = {
 r'\hat' : r'\circumflexaccent',
@@ -1971,7 +1996,7 @@
 centered.shift_amount = accent._metrics.xmin
 return Vlist([
 centered,
- FixedGlue(thickness * 2.0),
+ Vbox(0., thickness * 2.0),
 Hlist([sym])
 ])
 
@@ -1982,6 +2007,7 @@
 state.font = 'rm'
 hlist = Hlist([Char(c, state) for c in toks[0]])
 self.pop_state()
+ hlist.function_name = toks[0]
 return hlist
 
 def start_group(self, s, loc, toks):
@@ -2007,7 +2033,9 @@
 
 def is_overunder(self, nucleus):
 if isinstance(nucleus, Char):
- return overunder_symbols.has_key(nucleus.c)
+ return nucleus.c in self._overunder_symbols
+ elif isinstance(nucleus, Hlist) and hasattr(nucleus, 'function_name'):
+ return nucleus.function_name in self._overunder_functions
 return False
 
 def subsuperscript(self, s, loc, toks):
@@ -2061,24 +2089,22 @@
 width = nucleus.width
 if super is not None:
 super.shrink()
- super.pack()
 width = max(width, super.width)
 if sub is not None:
 sub.shrink()
- sub.pack()
 width = max(width, sub.width)
 
 if super is not None:
 hlist = HCentered([super])
 hlist.hpack(width, 'exactly')
- vlist.extend([hlist, FixedGlue(rule_thickness * 2.0)])
+ vlist.extend([hlist, Vbox(0., rule_thickness * 2.0)])
 hlist = HCentered([nucleus])
 hlist.hpack(width, 'exactly')
 vlist.append(hlist)
 if sub is not None:
 hlist = HCentered([sub])
 hlist.hpack(width, 'exactly')
- vlist.extend([FixedGlue(rule_thickness), hlist])
+ vlist.extend([Vbox(0., rule_thickness), hlist])
 shift = hlist.height + hlist.depth + rule_thickness * 2.0
 vlist = Vlist(vlist)
 vlist.shift_amount = shift
@@ -2086,12 +2112,12 @@
 return [result]
 
 shift_up = nucleus.height - SUBDROP * xHeight
- shift_down = nucleus.depth + SUBDROP * xHeight
+ shift_down = SUBDROP * xHeight
 if super is None:
 # @757
 sub.shrink()
 x = Hlist([sub])
- #x.width += SCRIPT_SPACE
+ x.width += SCRIPT_SPACE * xHeight
 shift_down = max(shift_down, SUB1)
 clr = x.height - (abs(xHeight * 4.0) / 5.0)
 shift_down = max(shift_down, clr)
@@ -2099,7 +2125,7 @@
 else:
 super.shrink()
 x = Hlist([super])
- #x.width += SCRIPT_SPACE
+ x.width += SCRIPT_SPACE * xHeight
 clr = SUP1 * xHeight
 shift_up = max(shift_up, clr)
 clr = x.depth + (abs(xHeight) / 4.0)
@@ -2109,13 +2135,13 @@
 else: # Both sub and superscript
 sub.shrink()
 y = Hlist([sub])
- #y.width += SCRIPT_SPACE
+ y.width += SCRIPT_SPACE * xHeight
 shift_down = max(shift_down, SUB1 * xHeight)
 clr = 4.0 * rule_thickness - ((shift_up - x.depth) - (y.height - shift_down))
 if clr > 0.:
 shift_up += clr
 shift_down += clr
- x.shift_amount = DELTA
+ x.shift_amount = DELTA * xHeight
 x = Vlist([x,
 Kern((shift_up - x.depth) - (y.height - shift_down)),
 y])
@@ -2127,33 +2153,78 @@
 def frac(self, s, loc, toks):
 assert(len(toks)==1)
 assert(len(toks[0])==2)
+ state = self.get_state()
+ thickness = state.font_output.get_underline_thickness(
+ state.font, state.fontsize, state.dpi)
+ 
 num, den = toks[0]
 num.shrink()
 den.shrink()
 cnum = HCentered([num])
 cden = HCentered([den])
- width = max(num.width, den.height)
+ width = max(num.width, den.width) + thickness * 10.
 cnum.hpack(width, 'exactly')
 cden.hpack(width, 'exactly')
- state = self.get_state()
- thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize, state.dpi)
- space = thickness * 3.0
 vlist = Vlist([cnum,
- FixedGlue(thickness * 2.0),
- Hrule(self.get_state()),
- FixedGlue(thickness * 3.0),
+ Vbox(0, thickness * 2.0),
+ Hrule(state),
+ Vbox(0, thickness * 4.0),
 cden
 ])
 
+ # Shift so the fraction line sits in the middle of the
+ # equals sign
 metrics = state.font_output.get_metrics(
 state.font, '=', state.fontsize, state.dpi)
- shift = cden.height - (metrics.ymax + metrics.ymin) / 2 + thickness * 2.5
+ shift = (cden.height -
+ (metrics.ymax + metrics.ymin) / 2 +
+ thickness * 2.5)
 vlist.shift_amount = shift
 
- hlist = Hlist([vlist, FixedGlue(thickness * 2.)])
+ hlist = Hlist([vlist, Hbox(thickness * 2.)])
 return [hlist]
 
+ def sqrt(self, s, loc, toks):
+ #~ print "sqrt", toks
+ root, body = toks[0]
+ state = self.get_state()
+ thickness = state.font_output.get_underline_thickness(
+ state.font, state.fontsize, state.dpi)
+
+ if root is None:
+ root = Box()
+ else:
+ root.shrink()
+ root.shrink()
+
+ # Add a little extra to the height so the body
+ # doesn't seem cramped
+ height = body.height - body.shift_amount + thickness * 5.0
+ depth = body.depth + body.shift_amount
+ check = AutoSizedDelim(r'\sqrt', height, depth, state)
+
+ height = check.height - check.shift_amount
+ depth = check.depth + check.shift_amount
+ rightside = Vlist([Hrule(state),
+ Fill(),
+ # Pack a little extra to the left and right
+ # of the body
+ Hlist([Hbox(thickness * 2.0),
+ body,
+ Hbox(thickness * 2.0)])])
+ # Stretch the glue between the hrule and the body
+ rightside.vpack(height + 1.0, depth, 'exactly')
+
+ root_vlist = Vlist([Hlist([root])])
+ root_vlist.shift_amount = -height * 0.5
+ 
+ hlist = Hlist([root_vlist,
+ Kern(-check.width * 0.5),
+ check,
+ Kern(-thickness * 0.5),
+ rightside])
+ return [hlist]
+ 
 def auto_sized_delimiter(self, s, loc, toks):
 #~ print "auto_sized_delimiter", toks
 front, middle, back = toks
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3619
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3619&view=rev
Author: mdboom
Date: 2007年07月26日 11:40:36 -0700 (2007年7月26日)
Log Message:
-----------
Fix bug in pdf backend (numpy.inf not numpy.infinity)
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2007年07月26日 14:47:27 UTC (rev 3618)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2007年07月26日 18:40:36 UTC (rev 3619)
@@ -112,7 +112,7 @@
 # need to use %f with some precision. Perhaps the precision
 # should adapt to the magnitude of the number?
 elif isinstance(obj, float):
- if npy.isnan(obj) or obj in (-npy.infinity, npy.infinity):
+ if npy.isnan(obj) or obj in (-npy.inf, npy.inf):
 raise ValueError, "Can only output finite numbers in PDF"
 r = "%.10f" % obj
 return r.rstrip('0').rstrip('.')
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年07月26日 14:47:28
Revision: 3618
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3618&view=rev
Author: mdboom
Date: 2007年07月26日 07:47:27 -0700 (2007年7月26日)
Log Message:
-----------
Update information about mathtext improvements.
Modified Paths:
--------------
 trunk/matplotlib/API_CHANGES
 trunk/matplotlib/CHANGELOG
Modified: trunk/matplotlib/API_CHANGES
===================================================================
--- trunk/matplotlib/API_CHANGES	2007年07月26日 14:45:57 UTC (rev 3617)
+++ trunk/matplotlib/API_CHANGES	2007年07月26日 14:47:27 UTC (rev 3618)
@@ -1,3 +1,10 @@
+ The mathtext font commands (\cal, \rm, \it, \tt) now behave as TeX
+ does: they are in effect until the next font change command or the
+ end of the grouping. Therefore uses of $\cal{R}$ should be
+ changed to ${\cal R}$. Alternatively, you may use the new
+ LaTeX-style font commands (\mathcal, \mathrm, \mathit, \mathtt)
+ which do affect the following group, eg. $\mathcal{R}$.
+
 Text creation commands have a new default linespacing and
 a new linespacing kwarg, which is a multiple of the maximum
 vertical extent of a line of ordinary text. The default is
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG	2007年07月26日 14:45:57 UTC (rev 3617)
+++ trunk/matplotlib/CHANGELOG	2007年07月26日 14:47:27 UTC (rev 3618)
@@ -1,3 +1,52 @@
+2007年07月26日 Major rewrite of mathtext.py, using the TeX box layout model.
+
+	 There is one (known) backward incompatible change. The
+	 font commands (\cal, \rm, \it, \tt) now behave as TeX does:
+	 they are in effect until the next font change command or
+	 the end of the grouping. Therefore uses of $\cal{R}$
+	 should be changed to ${\cal R}$. Alternatively, you may
+	 use the new LaTeX-style font commands (\mathcal, \mathrm,
+	 \mathit, \mathtt) which do affect the following group,
+	 eg. $\mathcal{R}$.
+
+	 Other new features include:
+
+	 - Math may be interspersed with non-math text. Any text
+ with an even number of $'s (non-escaped) will be sent to
+	 the mathtext parser for layout.
+
+	 - Sub/superscripts are less likely to accidentally overlap.
+
+	 - Support for sub/superscripts in either order, eg. $x^i_j$
+ and $x_j^i$ are equivalent.
+
+	 - Double sub/superscripts (eg. $x_i_j$) are considered
+ ambiguous and raise an exception. Use braces to disambiguate.
+
+	 - $\frac{x}{y}$ can be used for displaying fractions
+
+	 - $\left(\frac{x}{y}\right)$ may be used to create
+ parentheses and other delimiters that automatically
+ resize to the height of their contents.
+
+	 - Spacing around operators etc. is now generally more like
+ TeX.
+
+ 	 - Added support (and fonts) for boldface (\bf) and
+ sans-serif (\sf) symbols.
+
+	 - Log-like function name shortcuts are supported. For
+ example, $\sin(x)$ may be used instead of ${\rm sin}(x)$
+
+	 - Limited use of kerning for the easy case (same font)
+
+	 Behind the scenes, the pyparsing.py module used for doing
+	 the math parsing was updated to the latest stable version
+	 (1.4.6). A lot of duplicate code was refactored out of the
+	 Font classes.
+
+	 - MGD
+
 2007年07月19日 completed numpification of most trivial cases - NN
 
 2007年07月19日 converted non-numpy relicts troughout the code - NN
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年07月26日 14:45:59
Revision: 3617
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3617&view=rev
Author: mdboom
Date: 2007年07月26日 07:45:57 -0700 (2007年7月26日)
Log Message:
-----------
Merging mathtext changes into trunk.
Modified Paths:
--------------
 trunk/matplotlib/examples/mathtext_demo.py
 trunk/matplotlib/lib/matplotlib/_mathtext_data.py
 trunk/matplotlib/lib/matplotlib/afm.py
 trunk/matplotlib/lib/matplotlib/backends/backend_agg.py
 trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py
 trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py
 trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
 trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
 trunk/matplotlib/lib/matplotlib/backends/backend_svg.py
 trunk/matplotlib/lib/matplotlib/mathtext.py
 trunk/matplotlib/lib/matplotlib/pyparsing.py
 trunk/matplotlib/lib/matplotlib/text.py
 trunk/matplotlib/src/ft2font.cpp
 trunk/matplotlib/src/mplutils.h
Added Paths:
-----------
 trunk/matplotlib/examples/mathtext_examples.py
 trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/cmb10.ttf
 trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/cmss10.ttf
Modified: trunk/matplotlib/examples/mathtext_demo.py
===================================================================
--- trunk/matplotlib/examples/mathtext_demo.py	2007年07月26日 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/examples/mathtext_demo.py	2007年07月26日 14:45:57 UTC (rev 3617)
@@ -1,28 +1,25 @@
 #!/usr/bin/env python
 """
+Use matplotlib's internal LaTex parser and layout engine. For true
+latex rendering, see the text.usetex option
+"""
+import numpy as npy
+from pylab import figure, show
+fig = figure()
+fig.subplots_adjust(bottom=0.2)
 
-In order to use mathtext, you must build matplotlib.ft2font. This is
-built by default in the windows installer.
+ax = fig.add_subplot(111, axisbg='y')
+ax.plot([1,2,3], 'r')
+x = npy.arange(0.0, 3.0, 0.1)
 
-For other platforms, edit setup.py and set
+ax.grid(True)
+ax.set_xlabel(r'$\Delta_i^j$', fontsize=20)
+ax.set_ylabel(r'$\Delta_{i+1}^j$', fontsize=20)
+tex = r'$\mathcal{R}\prod_{i=\alpha_{i+1}}^\infty a_i\sin(2 \pi f x_i)$'
 
-BUILD_FT2FONT = True
+ax.text(1, 1.6, tex, fontsize=20, va='bottom')
 
-"""
-from pylab import *
-subplot(111, axisbg='y')
-plot([1,2,3], 'r')
-x = arange(0.0, 3.0, 0.1)
-
-grid(True)
-xlabel(r'$\Delta_i^j$', fontsize=20)
-ylabel(r'$\Delta_{i+1}^j$', fontsize=20)
-tex = r'$\cal{R}\prod_{i=\alpha_{i+1}}^\infty a_i\rm{sin}(2 \pi f x_i)$'
-text(1, 1.6, tex, fontsize=20)
-
 #title(r'$\Delta_i^j \hspace{0.4} \rm{versus} \hspace{0.4} \Delta_{i+1}^j$', fontsize=20)
-savefig('mathtext_demo')
+fig.savefig('mathtext_demo')
 
-
-
 show()
Copied: trunk/matplotlib/examples/mathtext_examples.py (from rev 3616, branches/mathtext_mgd/examples/mathtext_examples.py)
===================================================================
--- trunk/matplotlib/examples/mathtext_examples.py	 (rev 0)
+++ trunk/matplotlib/examples/mathtext_examples.py	2007年07月26日 14:45:57 UTC (rev 3617)
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+import os, sys
+
+stests = [
+ r'Kerning: AVA $AVA$',
+ r'$x y$',
+ r'$x+y\ x=y\ x<y\ x:y\ x,y\ x@y$',
+ r'100ドル\%y\ x*y\ x/y x\$y$',
+ r'$x\leftarrow y\ x\forall y$',
+ r'$x \sf x \bf x {\cal X} \rm x$',
+ r'$\{ \rm braces \}$',
+ r'$\left[\left\lfloor\frac{5}{\frac{\left(3\right)}{4}} y\right)\right]$',
+ r'$\left(x\right)$',
+ r'$\sin(x)$',
+ r'$x_2$',
+ r'$x^2$',
+ r'$x^2_y$',
+ r'$x_y^2$',
+ r'$\prod_{i=\alpha_{i+1}}^\infty$',
+ r'$x = \frac{x+\frac{5}{2}}{\frac{y+3}{8}}$',
+ r'$dz/dt \/ = \/ \gamma x^2 \/ + \/ {\rm sin}(2\pi y+\phi)$',
+ r'Foo: $\alpha_{i+1}^j \/ = \/ {\rm sin}(2\pi f_j t_i) e^{-5 t_i/\tau}$',
+ r'$\mathcal{R}\prod_{i=\alpha_{i+1}}^\infty a_i \sin(2 \pi f x_i)$',
+# r'$\bigodot \bigoplus {\sf R} a_i{\rm sin}(2 \pi f x_i)$',
+ r'Variable $i$ is good',
+ r'$\Delta_i^j$',
+ r'$\Delta^j_{i+1}$',
+ r'$\ddot{o}\acute{e}\grave{e}\hat{O}\breve{\imath}\tilde{n}\vec{q}$',
+ r'$_i$',
+ r"$\arccos((x^i))$",
+ r"$\gamma = \frac{x=\frac{6}{8}}{y} \delta$",
+ r'$\"o\ddot o \'e\`e\~n\.x\^y$',
+ 
+ ]
+
+from pylab import *
+
+if '--latex' in sys.argv:
+ fd = open("mathtext_examples.ltx", "w")
+ fd.write("\\documentclass{article}\n")
+ fd.write("\\begin{document}\n")
+ fd.write("\\begin{enumerate}\n")
+
+ for i, s in enumerate(stests):
+ fd.write("\\item %s\n" % s)
+
+ fd.write("\\end{enumerate}\n")
+ fd.write("\\end{document}\n")
+ fd.close()
+
+ os.system("pdflatex mathtext_examples.ltx")
+else:
+ for i, s in enumerate(stests):
+ print "%02d: %s" % (i, s)
+ plot([1,2,3], 'r')
+ x = arange(0.0, 3.0, 0.1)
+
+ grid(True)
+ text(1, 1.6, s, fontsize=20)
+
+ savefig('mathtext_example%02d' % i)
+ figure()
+
Property changes on: trunk/matplotlib/examples/mathtext_examples.py
___________________________________________________________________
Name: svn:executable
 + *
Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/_mathtext_data.py	2007年07月26日 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py	2007年07月26日 14:45:57 UTC (rev 3617)
@@ -38,8 +38,10 @@
 r'\SQRT' : ('cmex10', 53),
 r'\leftbrace' : ('cmex10', 92),
 r'{' : ('cmex10', 92),
+ r'\{' : ('cmex10', 92),
 r'\rightbrace' : ('cmex10', 130),
 r'}' : ('cmex10', 130),
+ r'\}' : ('cmex10', 130),
 r'\leftangle' : ('cmex10', 97),
 r'\rightangle' : ('cmex10', 64),
 r'\Leftparen' : ('cmex10', 112),
@@ -112,7 +114,7 @@
 r'\phi' : ('cmmi10', 42),
 r'\chi' : ('cmmi10', 17),
 r'\psi' : ('cmmi10', 31),
-
+ 
 r'(' : ('cmr10', 119),
 r'\leftparen' : ('cmr10', 119),
 r'\rightparen' : ('cmr10', 68),
@@ -135,7 +137,11 @@
 r'[' : ('cmr10', 62),
 r'\rightbracket' : ('cmr10', 72),
 r']' : ('cmr10', 72),
-
+ r'\%' : ('cmr10', 48),
+ r'%' : ('cmr10', 48),
+ r'\$' : ('cmr10', 99),
+ r'@' : ('cmr10', 111),
+ 
 # these are mathml names, I think. I'm just using them for the
 # tex methods noted
 r'\circumflexaccent' : ('cmr10', 124), # for \hat
@@ -749,7 +755,17 @@
 r'\langle' : ('psyr', 225),
 r'\Sigma' : ('psyr', 229),
 r'\sum' : ('psyr', 229),
-
+ # these are mathml names, I think. I'm just using them for the
+ # tex methods noted
+ r'\circumflexaccent' : ('pncri8a', 124), # for \hat
+ r'\combiningbreve' : ('pncri8a', 81), # for \breve
+ r'\combininggraveaccent' : ('pncri8a', 114), # for \grave
+ r'\combiningacuteaccent' : ('pncri8a', 63), # for \accute
+ r'\combiningdiaeresis' : ('pncri8a', 91), # for \ddot
+ r'\combiningtilde' : ('pncri8a', 75), # for \tilde
+ r'\combiningrightarrowabove' : ('pncri8a', 110), # for \vec
+ r'\combiningdotabove' : ('pncri8a', 26), # for \dot
+ r'\imath' : ('pncri8a', 105)
 }
 
 # Automatically generated.
Modified: trunk/matplotlib/lib/matplotlib/afm.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/afm.py	2007年07月26日 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/afm.py	2007年07月26日 14:45:57 UTC (rev 3617)
@@ -394,7 +394,14 @@
 "Return the fontangle as float"
 return self._header['ItalicAngle']
 
+ def get_xheight(self):
+ "Return the xheight as float"
+ return self._header['XHeight']
 
+ def get_underline_thickness(self):
+ "Return the underline thickness as float"
+ return self._header['UnderlineThickness']
+ 
 
 if __name__=='__main__':
 #pathname = '/usr/local/lib/R/afm/'
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_agg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_agg.py	2007年07月26日 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_agg.py	2007年07月26日 14:45:57 UTC (rev 3617)
@@ -173,10 +173,9 @@
 """
 if __debug__: verbose.report('RendererAgg.draw_mathtext',
 'debug-annoying')
- size = prop.get_size_in_points()
- width, height, fonts = math_parse_s_ft2font(
- s, self.dpi.get(), size, angle)
-
+ width, height, fonts, used_characters = math_parse_s_ft2font(
+ s, self.dpi.get(), prop, angle)
+ 
 if angle == 90:
 width, height = height, width
 for font in fonts:
@@ -225,7 +224,6 @@
 # texmanager more efficient. It is not meant to be used
 # outside the backend
 """
-
 if ismath=='TeX':
 # todo: handle props
 size = prop.get_size_in_points()
@@ -235,8 +233,8 @@
 return n,m
 
 if ismath:
- width, height, fonts = math_parse_s_ft2font(
- s, self.dpi.get(), prop.get_size_in_points())
+ width, height, fonts, used_characters = math_parse_s_ft2font(
+ s, self.dpi.get(), prop)
 return width, height
 font = self._get_agg_font(prop)
 font.set_text(s, 0.0) # the width and height of unrotated string
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py	2007年07月26日 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py	2007年07月26日 14:45:57 UTC (rev 3617)
@@ -314,9 +314,8 @@
 # "_draw_mathtext()")
 # return
 
- size = prop.get_size_in_points()
- width, height, fonts = math_parse_s_ft2font(
- s, self.dpi.get(), size)
+ width, height, fonts, used_characters = math_parse_s_ft2font(
+ s, self.dpi.get(), prop)
 
 if angle==90:
 width, height = height, width
@@ -372,8 +371,8 @@
 def get_text_width_height(self, s, prop, ismath):
 if _debug: print '%s.%s()' % (self.__class__.__name__, _fn_name())
 if ismath:
- width, height, fonts = math_parse_s_ft2font(
- s, self.dpi.get(), prop.get_size_in_points())
+ width, height, fonts, used_characters = math_parse_s_ft2font(
+ s, self.dpi.get(), prop)
 return width, height
 
 ctx = self.text_ctx
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py	2007年07月26日 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py	2007年07月26日 14:45:57 UTC (rev 3617)
@@ -198,9 +198,8 @@
 
 
 def _draw_mathtext(self, gc, x, y, s, prop, angle):
- size = prop.get_size_in_points()
- width, height, fonts = math_parse_s_ft2font(
- s, self.dpi.get(), size)
+ width, height, fonts, used_characters = math_parse_s_ft2font(
+ s, self.dpi.get(), prop)
 
 if angle==90:
 width, height = height, width
@@ -342,8 +341,8 @@
 
 def get_text_width_height(self, s, prop, ismath):
 if ismath:
- width, height, fonts = math_parse_s_ft2font(
- s, self.dpi.get(), prop.get_size_in_points())
+ width, height, fonts, used_characters = math_parse_s_ft2font(
+ s, self.dpi.get(), prop)
 return width, height
 
 layout, inkRect, logicalRect = self._get_pango_layout(s, prop)
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2007年07月26日 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2007年07月26日 14:45:57 UTC (rev 3617)
@@ -457,8 +457,9 @@
 fontdictObject = self._write_afm_font(filename)
 else:
 realpath, stat_key = get_realpath_and_stat(filename)
- fontdictObject = self.embedTTF(
- *self.used_characters[stat_key])
+ chars = self.used_characters.get(stat_key)
+ if chars is not None and len(chars[1]):
+ fontdictObject = self.embedTTF(realpath, chars[1])
 fonts[Fx] = fontdictObject
 #print >>sys.stderr, filename
 self.writeObject(self.fontObject, fonts)
@@ -1092,37 +1093,36 @@
 
 def draw_mathtext(self, gc, x, y, s, prop, angle):
 # TODO: fix positioning and encoding
- fontsize = prop.get_size_in_points()
 width, height, pswriter, used_characters = \
- math_parse_s_pdf(s, 72, fontsize, 0)
+ math_parse_s_pdf(s, 72, prop, 0)
 self.merge_used_characters(used_characters)
- 
+
 self.check_gc(gc, gc._rgb)
 self.file.output(Op.begin_text)
 prev_font = None, None
 oldx, oldy = 0, 0
- for ox, oy, fontname, fontsize, glyph in pswriter:
- #print ox, oy, glyph
- fontname = fontname.lower()
- a = angle / 180.0 * pi
- newx = x + cos(a)*ox - sin(a)*oy
- newy = y + sin(a)*ox + cos(a)*oy
- self._setup_textpos(newx, newy, angle, oldx, oldy)
- oldx, oldy = newx, newy
- if (fontname, fontsize) != prev_font:
- self.file.output(self.file.fontName(fontname), fontsize,
- Op.selectfont)
- prev_font = fontname, fontsize
+ for record in pswriter:
+ if record[0] == 'glyph':
+ rec_type, ox, oy, fontname, fontsize, glyph = record
+ a = angle / 180.0 * pi
+ newx = x + cos(a)*ox - sin(a)*oy
+ newy = y + sin(a)*ox + cos(a)*oy
+ self._setup_textpos(newx, newy, angle, oldx, oldy)
+ oldx, oldy = newx, newy
+ if (fontname, fontsize) != prev_font:
+ self.file.output(self.file.fontName(fontname), fontsize,
+ Op.selectfont)
+ prev_font = fontname, fontsize
 
- #if fontname.endswith('cmsy10.ttf') or \
- #fontname.endswith('cmmi10.ttf') or \
- #fontname.endswith('cmex10.ttf'):
- # string = '0円' + chr(glyph)
-
- string = chr(glyph)
- self.file.output(string, Op.show)
+ string = chr(glyph)
+ self.file.output(string, Op.show)
 self.file.output(Op.end_text)
 
+ for record in pswriter:
+ if record[0] == 'rect':
+ rec_type, ox, oy, width, height = record
+ self.file.output(Op.gsave, x + ox, y + oy, width, height, Op.rectangle, Op.fill, Op.grestore)
+
 def _draw_tex(self, gc, x, y, s, prop, angle):
 # Rename to draw_tex to enable, but note the following:
 # TODO:
@@ -1208,9 +1208,7 @@
 s = s.encode('cp1252', 'replace')
 
 if ismath:
- fontsize = prop.get_size_in_points()
- w, h, pswriter, used_characters = math_parse_s_pdf(
- s, 72, fontsize, 0)
+ w, h, pswriter, used_characters = math_parse_s_pdf(s, 72, prop, 0)
 
 elif rcParams['pdf.use14corefonts']:
 font = self._get_font_afm(prop)
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py	2007年07月26日 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py	2007年07月26日 14:45:57 UTC (rev 3617)
@@ -278,7 +278,7 @@
 
 if ismath:
 width, height, pswriter, used_characters = math_parse_s_ps(
- s, 72, prop.get_size_in_points(), 0)
+ s, 72, prop, 0)
 return width, height
 
 if rcParams['ps.useafm']:
@@ -813,11 +813,9 @@
 if debugPS:
 self._pswriter.write("% mathtext\n")
 
- fontsize = prop.get_size_in_points()
 width, height, pswriter, used_characters = \
- math_parse_s_ps(s, 72, fontsize, angle)
+ math_parse_s_ps(s, 72, prop, angle)
 self.merge_used_characters(used_characters)
-
 self.set_color(*gc.get_rgb())
 thetext = pswriter.getvalue()
 ps = """gsave
@@ -1038,13 +1036,14 @@
 print >>fh, l.strip()
 if not rcParams['ps.useafm']:
 for font_filename, chars in renderer.used_characters.values():
- font = FT2Font(font_filename)
- cmap = font.get_charmap()
- glyph_ids = []
- for c in chars:
- gind = cmap.get(ord(c)) or 0
- glyph_ids.append(gind)
- convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids)
+ if len(chars):
+ font = FT2Font(font_filename)
+ cmap = font.get_charmap()
+ glyph_ids = []
+ for c in chars:
+ gind = cmap.get(ord(c)) or 0
+ glyph_ids.append(gind)
+ convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids)
 print >>fh, "end"
 print >>fh, "%%EndProlog"
 
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py	2007年07月26日 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py	2007年07月26日 14:45:57 UTC (rev 3617)
@@ -291,9 +291,12 @@
 self._svgwriter.write (svg)
 
 def _add_char_def(self, prop, char):
- newprop = prop.copy()
- newprop.set_size(self.FONT_SCALE)
- font = self._get_font(newprop)
+ if isinstance(prop, FontProperties):
+ newprop = prop.copy()
+ font = self._get_font(newprop)
+ else:
+ font = prop
+ font.set_size(self.FONT_SCALE, 72)
 ps_name = font.get_sfnt()[(1,0,0,6)]
 char_id = urllib.quote('%s-%d' % (ps_name, ord(char)))
 if char_id in self._char_defs:
@@ -332,10 +335,10 @@
 """
 Draw math text using matplotlib.mathtext
 """
- fontsize = prop.get_size_in_points()
- width, height, svg_elements = math_parse_s_ft2font_svg(s, 72, fontsize)
+ width, height, svg_elements, used_characters = \
+ math_parse_s_ft2font_svg(s, 72, prop)
 svg_glyphs = svg_elements.svg_glyphs
- svg_lines = svg_elements.svg_lines
+ svg_rects = svg_elements.svg_rects
 color = rgb2hex(gc.get_rgb())
 
 self.open_group("mathtext")
@@ -349,10 +352,9 @@
 svg.append('translate(%f,%f)' % (x, y))
 svg.append('">\n')
 
- for fontname, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs:
- prop = FontProperties(family=fontname, size=fontsize)
- charid = self._add_char_def(prop, thetext)
-
+ for font, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs:
+ charid = self._add_char_def(font, thetext)
+ 
 svg.append('<use xlink:href="#%s" transform="translate(%s, %s) scale(%s)"/>\n' % 
 (charid, new_x, -new_y_mtc, fontsize / self.FONT_SCALE))
 svg.append('</g>\n')
@@ -366,7 +368,7 @@
 
 curr_x,curr_y = 0.0,0.0
 
- for fontname, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs:
+ for font, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs:
 if rcParams["mathtext.mathtext2"]:
 new_y = new_y_mtc - height
 else:
@@ -392,13 +394,20 @@
 
 svg.append('</text>\n')
 
+ if len(svg_rects):
+ svg.append('<g style="fill: black; stroke: none" transform="')
+ if angle != 0:
+ svg.append('translate(%f,%f) rotate(%1.1f)'
+ % (x,y,-angle) )
+ else:
+ svg.append('translate(%f,%f)' % (x, y))
+ svg.append('">\n')
+
+ for x, y, width, height in svg_rects:
+ svg.append('<rect x="%s" y="%s" width="%s" height="%s" fill="black" stroke="none" />' % (x, -y + height, width, height))
+ svg.append("</g>")
+ 
 self._svgwriter.write (''.join(svg))
- rgbFace = gc.get_rgb()
- for xmin, ymin, xmax, ymax in svg_lines:
- newx, newy = x + xmin, y + height - ymax#-(ymax-ymin)/2#-height
- self.draw_rectangle(gc, rgbFace, newx, newy, xmax-xmin, ymax-ymin)
- #~ self.draw_line(gc, x + xmin, y + ymin,# - height,
- #~ x + xmax, y + ymax)# - height)
 self.close_group("mathtext")
 
 def finish(self):
@@ -417,8 +426,8 @@
 
 def get_text_width_height(self, s, prop, ismath):
 if ismath:
- width, height, trash = math_parse_s_ft2font_svg(
- s, 72, prop.get_size_in_points())
+ width, height, trash, used_characters = \
+ math_parse_s_ft2font_svg(s, 72, prop)
 return width, height
 font = self._get_font(prop)
 font.set_text(s, 0.0)
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py	2007年07月26日 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py	2007年07月26日 14:45:57 UTC (rev 3617)
@@ -14,7 +14,7 @@
 handle fairly complex TeX expressions Eg, the following renders
 correctly
 
- s = r'$\cal{R}\prod_{i=\alpha\cal{B}}^\infty a_i\rm{sin}(2 \pi f x_i)$'
+ s = r'$\mathcal{R}\prod_{i=\alpha\mathcal{B}}^\infty a_i\sin(2 \pi f x_i)$'
 
 The fonts \cal, \rm, \it, and \tt are allowed.
 
@@ -59,17 +59,10 @@
 ^
 use raw strings
 
- The $ symbols must be the first and last symbols in the string. Eg,
- you cannot do
+ Math and non-math can be interpresed in the same string. E.g.,
 
 r'My label $x_i$'.
 
- but you can change fonts, as in
-
- r'$\rm{My label} x_i$'
-
- to achieve the same effect.
-
 A large set of the TeX symbols are provided. Subscripting and
 superscripting are supported, as well as the over/under style of
 subscripting with \sum, \int, etc.
@@ -77,6 +70,8 @@
 
 Allowed TeX symbols:
 
+ [MGDTODO: This list is no longer exhaustive and needs to be updated]
+ 
 \/ \Delta \Downarrow \Gamma \Im \LEFTangle \LEFTbrace \LEFTbracket
 \LEFTparen \Lambda \Leftarrow \Leftbrace \Leftbracket \Leftparen
 \Leftrightarrow \Omega \P \Phi \Pi \Psi \RIGHTangle \RIGHTbrace
@@ -119,11 +114,16 @@
 
 KNOWN ISSUES:
 
- - nested subscripts, eg, x_i_j not working; but you can do x_{i_j}
- - nesting fonts changes in sub/superscript groups not parsing
- - I would also like to add a few more layout commands, like \frac.
+ - Certainly there are some...
 
+STATUS:
+ The *Unicode* classes were incomplete when I found them, and have
+ not been refactored to support intermingling of regular text and
+ math text yet. They are most likely broken. -- Michael Droettboom, July 2007
+ 
 Author : John Hunter <jdh...@ac...>
+ Michael Droettboom <md...@st...>
+ (rewrite based on TeX box layout algorithms)
 Copyright : John Hunter (2004,2005)
 License : matplotlib license (PSF compatible)
 
@@ -132,26 +132,32 @@
 import os, sys
 from cStringIO import StringIO
 from sets import Set
+from warnings import warn
 
 from matplotlib import verbose
 from matplotlib.pyparsing import Literal, Word, OneOrMore, ZeroOrMore, \
 Combine, Group, Optional, Forward, NotAny, alphas, nums, alphanums, \
- StringStart, StringEnd, ParseException, FollowedBy, Regex
+ StringStart, StringEnd, ParseFatalException, FollowedBy, Regex, \
+ operatorPrecedence, opAssoc, ParseResults, Or, Suppress, oneOf
 
 from matplotlib.afm import AFM
-from matplotlib.cbook import enumerate, iterable, Bunch, get_realpath_and_stat
-from matplotlib.ft2font import FT2Font
+from matplotlib.cbook import enumerate, iterable, Bunch, get_realpath_and_stat, \
+ is_string_like
+from matplotlib.ft2font import FT2Font, KERNING_UNFITTED
 from matplotlib.font_manager import fontManager, FontProperties
 from matplotlib._mathtext_data import latex_to_bakoma, cmkern, \
 latex_to_standard, tex2uni, type12uni, tex2type1, uni2type1
 from matplotlib import get_data_path, rcParams
 
+####################
+
 # symbols that have the sub and superscripts over/under
-overunder = { r'\sum' : 1,
- r'\int' : 1,
- r'\prod' : 1,
- r'\coprod' : 1,
- }
+overunder_symbols = {
+ r'\sum' : 1,
+ r'\int' : 1,
+ r'\prod' : 1,
+ r'\coprod' : 1,
+ }
 # a character over another character
 charOverChars = {
 # The first 2 entires in the tuple are (font, char, sizescale) for
@@ -160,6 +166,8 @@
 r'\angstrom' : ( ('rm', 'A', 1.0), (None, '\circ', 0.5), 0.0 ),
 }
 
+##############################################################################
+# FONTS
 
 def font_open(filename):
 ext = filename.rsplit('.',1)[1]
@@ -224,7 +232,7 @@
 The class must be able to take symbol keys and font file names and
 return the character metrics as well as do the drawing
 """
-
+ 
 def get_kern(self, facename, symleft, symright, fontsize, dpi):
 """
 Get the kerning distance for font between symleft and symright.
@@ -264,7 +272,13 @@
 def render(self, ox, oy, facename, sym, fontsize, dpi):
 pass
 
-
+ def render_rect_filled(self, x1, y1, x2, y2):
+ pass
+ 
+ def get_used_characters(self):
+ return {}
+ 
+ 
 class DummyFonts(Fonts):
 'dummy class for debugging parser'
 def get_metrics(self, font, sym, fontsize, dpi):
@@ -475,6 +489,8 @@
 'rm' : 'cmr10.ttf',
 'tt' : 'cmtt10.ttf',
 'it' : 'cmmi10.ttf',
+ 'bf' : 'cmb10.ttf',
+ 'sf' : 'cmss10.ttf',
 None : 'cmmi10.ttf',
 }
 
@@ -542,78 +558,108 @@
 
 # Old classes
 
-class BakomaTrueTypeFonts(Fonts):
+class BakomaFonts(Fonts):
 """
 Use the Bakoma true type fonts for rendering
 """
- fnames = ('cmmi10', 'cmsy10', 'cmex10',
- 'cmtt10', 'cmr10')
 # allocate a new set of fonts
 basepath = os.path.join( get_data_path(), 'fonts', 'ttf' )
 
- fontmap = { 'cal' : 'cmsy10',
- 'rm' : 'cmr10',
- 'tt' : 'cmtt10',
- 'it' : 'cmmi10',
- None : 'cmmi10',
+ fontmap = { 'cal' : 'Cmsy10',
+ 'rm' : 'Cmr10',
+ 'tt' : 'Cmtt10',
+ 'it' : 'Cmmi10',
+ 'bf' : 'Cmb10',
+ 'sf' : 'Cmss10',
+ None : 'Cmmi10',
+ 'ex' : 'Cmex10'
 }
 
- def __init__(self, useSVG=False):
- self.glyphd = {}
- self.fonts = dict(
- [ (name, FT2Font(os.path.join(self.basepath, name) + '.ttf'))
- for name in self.fnames])
+ class CachedFont:
+ def __init__(self, font):
+ self.font = font
+ self.charmap = font.get_charmap()
+ self.glyphmap = dict(
+ [(glyphind, ccode) for ccode, glyphind in self.charmap.items()])
+ 
+ def __init__(self):
+ self.glyphd = {}
+ self.fonts = {}
+ self.used_characters = {}
 
- self.charmaps = dict(
- [ (name, self.fonts[name].get_charmap()) for name in self.fnames])
- # glyphmaps is a dict names to a dict of glyphindex -> charcode
- self.glyphmaps = {}
- for name in self.fnames:
- cmap = self.charmaps[name]
- self.glyphmaps[name] = dict([(glyphind, ccode) for ccode, glyphind in cmap.items()])
+ def _get_font(self, font):
+ """Looks up a CachedFont with its charmap and inverse charmap.
+ font may be a TeX font name (cal, rm, it etc.), a Computer Modern
+ font name (cmtt10, cmr10, etc.) or an FT2Font object."""
+ if isinstance(font, str):
+ if font not in self.fontmap.values():
+ basename = self.fontmap[font]
+ else:
+ basename = font
+ else:
+ basename = font.postscript_name
 
- for font in self.fonts.values():
- font.clear()
- if useSVG:
- self.svg_glyphs=[] # a list of "glyphs" we need to render this thing in SVG
- else: pass
- self.usingSVG = useSVG
+ cached_font = self.fonts.get(basename)
+ if cached_font is None:
+ if isinstance(font, str):
+ font = FT2Font(os.path.join(self.basepath, basename.lower() + ".ttf"))
+ basename = font.postscript_name
+ cached_font = self.CachedFont(font)
+ self.fonts[basename] = cached_font
+ return basename, cached_font
 
+ def get_font(self, font):
+ return self._get_font(font)[1].font
+ 
+ def get_fonts(self):
+ return [x.font for x in self.fonts.values()]
+ 
 def get_metrics(self, font, sym, fontsize, dpi):
- cmfont, metrics, glyph, offset = \
+ basename, font, metrics, symbol_name, num, glyph, offset = \
 self._get_info(font, sym, fontsize, dpi)
 return metrics
 
+ def _get_offset(self, basename, cached_font, glyph, fontsize, dpi):
+ if basename.lower() == 'cmex10':
+ return glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
+ return 0.
+ 
 def _get_info (self, font, sym, fontsize, dpi):
 'load the cmfont, metrics and glyph with caching'
- key = font, sym, fontsize, dpi
+ if hasattr(font, 'postscript_name'):
+ fontname = font.postscript_name
+ else:
+ fontname = font
+ 
+ key = fontname, sym, fontsize, dpi
 tup = self.glyphd.get(key)
 
 if tup is not None: return tup
-
- basename = self.fontmap[font]
-
- if latex_to_bakoma.has_key(sym):
+ 
+ if font in self.fontmap and latex_to_bakoma.has_key(sym):
 basename, num = latex_to_bakoma[sym]
- num = self.glyphmaps[basename][num]
+ basename, cached_font = self._get_font(basename.capitalize())
+ symbol_name = cached_font.font.get_glyph_name(num)
+ num = cached_font.glyphmap[num]
 elif len(sym) == 1:
+ basename, cached_font = self._get_font(font)
 num = ord(sym)
+ symbol_name = cached_font.font.get_glyph_name(cached_font.charmap[num])
 else:
 num = 0
 raise ValueError('unrecognized symbol "%s"' % sym)
 
- #print sym, basename, num
- cmfont = self.fonts[basename]
- cmfont.set_size(fontsize, dpi)
- head = cmfont.get_sfnt_table('head')
- glyph = cmfont.load_char(num)
+ font = cached_font.font
+ font.set_size(fontsize, dpi)
+ glyph = font.load_char(num)
 
+ realpath, stat_key = get_realpath_and_stat(font.fname)
+ used_characters = self.used_characters.setdefault(
+ stat_key, (realpath, Set()))
+ used_characters[1].update(unichr(num))
+ 
 xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- if basename == 'cmex10':
- offset = glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
- #offset = -(head['yMin']+512)/head['unitsPerEm']*10.
- else:
- offset = 0.
+ offset = self._get_offset(basename, cached_font, glyph, fontsize, dpi)
 metrics = Bunch(
 advance = glyph.linearHoriAdvance/65536.0,
 height = glyph.height/64.0,
@@ -622,211 +668,120 @@
 xmax = xmax,
 ymin = ymin+offset,
 ymax = ymax+offset,
+ # iceberg is the equivalent of TeX's "height"
+ iceberg = glyph.horiBearingY/64.0 + offset
 )
 
- self.glyphd[key] = cmfont, metrics, glyph, offset
+ self.glyphd[key] = basename, font, metrics, symbol_name, num, glyph, offset
 return self.glyphd[key]
 
 def set_canvas_size(self, w, h):
 'Dimension the drawing canvas; may be a noop'
 self.width = int(w)
 self.height = int(h)
- for font in self.fonts.values():
- font.set_bitmap_size(int(w), int(h))
+ for cached_font in self.fonts.values():
+ cached_font.font.set_bitmap_size(int(w), int(h))
 
 def render(self, ox, oy, font, sym, fontsize, dpi):
- cmfont, metrics, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
+ basename, font, metrics, symbol_name, num, glyph, offset = \
+ self._get_info(font, sym, fontsize, dpi)
 
- if not self.usingSVG:
- cmfont.draw_glyph_to_bitmap(
- int(ox), int(self.height - oy - metrics.ymax), glyph)
- else:
- oy += offset - 512/2048.*10.
- basename = self.fontmap[font]
- if latex_to_bakoma.has_key(sym):
- basename, num = latex_to_bakoma[sym]
- num = self.glyphmaps[basename][num]
- elif len(sym) == 1:
- num = ord(sym)
- else:
- num = 0
- print >>sys.stderr, 'unrecognized symbol "%s"' % sym
- thetext = unichr(num)
- thetext.encode('utf-8')
- self.svg_glyphs.append((basename, fontsize, thetext, ox, oy, metrics))
+ font.draw_glyph_to_bitmap(
+ int(ox), int(oy - metrics.ymax), glyph)
 
+ def render_rect_filled(self, x1, y1, x2, y2):
+ assert len(self.fonts)
+ font = self.fonts.values()[0]
+ font.font.draw_rect_filled(x1, y1, max(x2 - 1, x1), max(y2 - 1, y1))
+ 
+ def get_used_characters(self):
+ return self.used_characters
 
- def _old_get_kern(self, font, symleft, symright, fontsize, dpi):
- """
- Get the kerning distance for font between symleft and symright.
+ def get_xheight(self, font, fontsize, dpi):
+ basename, cached_font = self._get_font(font)
+ cached_font.font.set_size(fontsize, dpi)
+ pclt = cached_font.font.get_sfnt_table('pclt')
+ xHeight = pclt['xHeight'] / 64.0
+ return xHeight
 
- font is one of tt, it, rm, cal or None
+ def get_underline_thickness(self, font, fontsize, dpi):
+ basename, cached_font = self._get_font(font)
+ cached_font.font.set_size(fontsize, dpi)
+ return max(1.0, cached_font.font.underline_thickness / 64.0)
 
- sym is a single symbol(alphanum, punct) or a special symbol
- like \sigma.
-
- """
- basename = self.fontmap[font]
- cmfont = self.fonts[basename]
- cmfont.set_size(fontsize, dpi)
- kernd = cmkern[basename]
- key = symleft, symright
- kern = kernd.get(key,0)
- #print basename, symleft, symright, key, kern
- return kern
-
- def _get_num(self, font, sym):
- 'get charcode for sym'
- basename = self.fontmap[font]
- if latex_to_bakoma.has_key(sym):
- basename, num = latex_to_bakoma[sym]
- num = self.glyphmaps[basename][num]
- elif len(sym) == 1:
- num = ord(sym)
- else:
- num = 0
- return num
-
-
-class BakomaPSFonts(Fonts):
+ def get_kern(self, fontleft, symleft, fontsizeleft,
+ fontright, symright, fontsizeright, dpi):
+ if fontsizeleft == fontsizeright:
+ basename, font1, metrics, symbol_name, num1, glyph1, offset = \
+ self._get_info(fontleft, symleft, fontsizeleft, dpi)
+ basename, font2, metrics, symbol_name, num2, glyph2, offset = \
+ self._get_info(fontright, symright, fontsizeright, dpi)
+ if font1 == font2:
+ basename, font = self._get_font(font1)
+ return font.font.get_kerning(num1, num2, KERNING_UNFITTED) / 64.0
+ return 0.0
+ 
+class BakomaPSFonts(BakomaFonts):
 """
 Use the Bakoma postscript fonts for rendering to backend_ps
 """
- facenames = ('cmmi10', 'cmsy10', 'cmex10',
- 'cmtt10', 'cmr10')
- # allocate a new set of fonts
- basepath = os.path.join( get_data_path(), 'fonts', 'ttf' )
 
- fontmap = { 'cal' : 'cmsy10',
- 'rm' : 'cmr10',
- 'tt' : 'cmtt10',
- 'it' : 'cmmi10',
- None : 'cmmi10',
- }
-
- def __init__(self):
- self.glyphd = {}
- self.fonts = dict(
- [ (name, FT2Font(os.path.join(self.basepath, name) + '.ttf'))
- for name in self.facenames])
-
- self.glyphmaps = {}
- for facename in self.facenames:
- charmap = self.fonts[facename].get_charmap()
- self.glyphmaps[facename] = dict([(glyphind, charcode)
- for charcode, glyphind in charmap.items()])
- for font in self.fonts.values():
- font.clear()
-
- self.used_characters = {}
- 
- def _get_info (self, font, sym, fontsize, dpi):
- 'load the cmfont, metrics and glyph with caching'
- key = font, sym, fontsize, dpi
- tup = self.glyphd.get(key)
-
- if tup is not None:
- return tup
-
- basename = self.fontmap[font]
-
- if latex_to_bakoma.has_key(sym):
- basename, num = latex_to_bakoma[sym]
- sym = self.fonts[basename].get_glyph_name(num)
- num = self.glyphmaps[basename][num]
- elif len(sym) == 1:
- num = ord(sym)
- else:
- num = 0
- #sym = '.notdef'
- raise ValueError('unrecognized symbol "%s, %d"' % (sym, num))
-
- cmfont = self.fonts[basename]
- cmfont.set_size(fontsize, dpi)
- head = cmfont.get_sfnt_table('head')
- glyph = cmfont.load_char(num)
-
- realpath, stat_key = get_realpath_and_stat(cmfont.fname)
- used_characters = self.used_characters.setdefault(
- stat_key, (realpath, Set()))
- used_characters[1].update(unichr(num))
-
- xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- if basename == 'cmex10':
- offset = -(head['yMin']+512)/head['unitsPerEm']*10.
- else:
- offset = 0.
- metrics = Bunch(
- advance = glyph.linearHoriAdvance/65536.0,
- height = glyph.height/64.0,
- width = glyph.width/64.0,
- xmin = xmin,
- xmax = xmax,
- ymin = ymin+offset,
- ymax = ymax+offset
- )
-
- self.glyphd[key] = basename, metrics, sym, offset
- return basename, metrics, '/'+sym, offset
-
 def set_canvas_size(self, w, h, pswriter):
 'Dimension the drawing canvas; may be a noop'
 self.width = w
 self.height = h
 self.pswriter = pswriter
 
-
 def render(self, ox, oy, font, sym, fontsize, dpi):
- fontname, metrics, glyphname, offset = \
+ basename, font, metrics, symbol_name, num, glyph, offset = \
 self._get_info(font, sym, fontsize, dpi)
- fontname = fontname.capitalize()
- if fontname == 'Cmex10':
- oy += offset - 512/2048.*10.
-
- ps = """/%(fontname)s findfont
+ oy = self.height - oy + offset
+ 
+ ps = """/%(basename)s findfont
 %(fontsize)s scalefont
 setfont
 %(ox)f %(oy)f moveto
-/%(glyphname)s glyphshow
+/%(symbol_name)s glyphshow
 """ % locals()
 self.pswriter.write(ps)
 
-
- def get_metrics(self, font, sym, fontsize, dpi):
- basename, metrics, sym, offset = \
- self._get_info(font, sym, fontsize, dpi)
- return metrics
-
+ def render_rect_filled(self, x1, y1, x2, y2):
+ ps = "%f %f %f %f rectfill" % (x1, self.height - y2, x2 - x1, y2 - y1)
+ self.pswriter.write(ps)
+ 
 class BakomaPDFFonts(BakomaPSFonts):
 """Hack of BakomaPSFonts for PDF support."""
 
- def _get_filename_and_num (self, font, sym, fontsize, dpi):
- 'should be part of _get_info'
- basename = self.fontmap[font]
+ def render(self, ox, oy, font, sym, fontsize, dpi):
+ basename, font, metrics, symbol_name, num, glyph, offset = \
+ self._get_info(font, sym, fontsize, dpi)
+ filename = font.fname
+ oy = self.height - oy + offset
 
- if latex_to_bakoma.has_key(sym):
- basename, num = latex_to_bakoma[sym]
- sym = self.fonts[basename].get_glyph_name(num)
- num = self.glyphmaps[basename][num]
- elif len(sym) == 1:
- num = ord(sym)
- else:
- num = 0
- raise ValueError('unrecognized symbol "%s"' % (sym,))
+ self.pswriter.append(('glyph', ox, oy, filename, fontsize, num))
 
- return os.path.join(self.basepath, basename) + '.ttf', num
-
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.pswriter.append(('rect', x1, self.height - y2, x2 - x1, y2 - y1))
+ 
+class BakomaSVGFonts(BakomaFonts):
+ """Hack of BakomaFonts for SVG support."""
+ def __init__(self):
+ BakomaFonts.__init__(self)
+ self.svg_glyphs = []
+ self.svg_rects = []
+ 
 def render(self, ox, oy, font, sym, fontsize, dpi):
- fontname, metrics, glyphname, offset = \
+ basename, font, metrics, symbol_name, num, glyph, offset = \
 self._get_info(font, sym, fontsize, dpi)
- filename, num = self._get_filename_and_num(font, sym, fontsize, dpi)
- if fontname.lower() == 'cmex10':
- oy += offset - 512/2048.*10.
 
- self.pswriter.append((ox, oy, filename, fontsize, num))
+ oy = self.height - oy + offset
+ thetext = unichr(num)
+ thetext.encode('utf-8')
+ self.svg_glyphs.append((font, fontsize, thetext, ox, oy, metrics))
 
-
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.svg_rects.append((x1, self.height - y2, x2 - x1, y2 - y1))
+ 
 class StandardPSFonts(Fonts):
 """
 Use the standard postscript fonts for rendering to backend_ps
@@ -835,21 +790,51 @@
 # allocate a new set of fonts
 basepath = os.path.join( get_data_path(), 'fonts', 'afm' )
 
- fontmap = { 'cal' : 'pzcmi8a',
- 'rm' : 'pncr8a',
- 'tt' : 'pcrr8a',
- 'it' : 'pncri8a',
+ fontmap = { 'cal' : 'pzcmi8a', # Zapf Chancery
+ 'rm' : 'pncr8a', # New Century Schoolbook
+ 'tt' : 'pcrr8a', # Courier 
+ 'it' : 'pncri8a', # New Century Schoolbook Italic
+ 'sf' : 'phvr8a', # Helvetica
+ 'bf' : 'pncb8a', # New Century Schoolbook Bold
+ None : 'psyr' # Symbol
 }
 
 def __init__(self):
 self.glyphd = {}
- self.fonts = dict(
- [ (name, AFM(file(os.path.join(self.basepath, name) + '.afm')))
- for name in self.fnames])
+ self.fonts = {}
 
+ def _get_font(self, font):
+ if isinstance(font, str):
+ if font not in self.fontmap.values():
+ basename = self.fontmap[font]
+ else:
+ basename = font
+ else:
+ basename = font.get_fontname()
+
+ cached_font = self.fonts.get(basename)
+ if cached_font is None:
+ if isinstance(font, str):
+ fname = os.path.join(self.basepath, basename + ".afm")
+ cached_font = AFM(file(fname, 'r'))
+ cached_font.fname = fname
+ basename = cached_font.get_fontname()
+ else:
+ cached_font = font
+ self.fonts[basename] = cached_font
+ return basename, cached_font
+
+ def get_fonts(self):
+ return [x.font for x in self.fonts.values()]
+ 
 def _get_info (self, font, sym, fontsize, dpi):
 'load the cmfont, metrics and glyph with caching'
- key = font, sym, fontsize, dpi
+ if hasattr(font, 'get_fontname'):
+ fontname = font.get_fontname()
+ else:
+ fontname = font
+
+ key = fontname, sym, fontsize, dpi
 tup = self.glyphd.get(key)
 
 if tup is not None:
@@ -857,41 +842,42 @@
 
 if sym in "0123456789()" and font == 'it':
 font = 'rm'
- basename = self.fontmap[font]
 
 if latex_to_standard.has_key(sym):
- basename, num = latex_to_standard[sym]
- char = chr(num)
+ font, num = latex_to_standard[sym]
+ glyph = chr(num)
 elif len(sym) == 1:
- char = sym
+ glyph = sym
+ num = ord(glyph)
 else:
 raise ValueError('unrecognized symbol "%s"' % (sym))
-
+ basename, font = self._get_font(font) 
+ 
 try:
- sym = self.fonts[basename].get_name_char(char)
+ symbol_name = font.get_name_char(glyph)
 except KeyError:
 raise ValueError('unrecognized symbol "%s"' % (sym))
 
 offset = 0
- cmfont = self.fonts[basename]
- fontname = cmfont.get_fontname()
 
 scale = 0.001 * fontsize
 
 xmin, ymin, xmax, ymax = [val * scale
- for val in cmfont.get_bbox_char(char)]
+ for val in font.get_bbox_char(glyph)]
 metrics = Bunch(
 advance = (xmax-xmin),
- width = cmfont.get_width_char(char) * scale,
- height = cmfont.get_width_char(char) * scale,
+ width = font.get_width_char(glyph) * scale,
+ height = font.get_height_char(glyph) * scale,
 xmin = xmin,
 xmax = xmax,
 ymin = ymin+offset,
- ymax = ymax+offset
+ ymax = ymax+offset,
+ # iceberg is the equivalent of TeX's "height"
+ iceberg = ymax + offset
 )
 
- self.glyphd[key] = fontname, basename, metrics, sym, offset, char
- return fontname, basename, metrics, '/'+sym, offset, char
+ self.glyphd[key] = basename, font, metrics, symbol_name, num, glyph, offset
+ return self.glyphd[key]
 
 def set_canvas_size(self, w, h, pswriter):
 'Dimension the drawing canvas; may be a noop'
@@ -899,637 +885,1292 @@
 self.height = h
 self.pswriter = pswriter
 
-
 def render(self, ox, oy, font, sym, fontsize, dpi):
- fontname, basename, metrics, glyphname, offset, char = \
+ basename, font, metrics, symbol_name, num, glyph, offset = \
 self._get_info(font, sym, fontsize, dpi)
- ps = """/%(fontname)s findfont
+ oy = self.height - oy
+ ps = """/%(basename)s findfont
 %(fontsize)s scalefont
 setfont
 %(ox)f %(oy)f moveto
-/%(glyphname)s glyphshow
+/%(symbol_name)s glyphshow
 """ % locals()
 self.pswriter.write(ps)
 
 
 def get_metrics(self, font, sym, fontsize, dpi):
- fontname, basename, metrics, sym, offset, char = \
+ basename, font, metrics, symbol_name, num, glyph, offset = \
 self._get_info(font, sym, fontsize, dpi)
 return metrics
 
- def get_kern(self, font, symleft, symright, fontsize, dpi):
- fontname, basename, metrics, sym, offset, char1 = \
- self._get_info(font, symleft, fontsize, dpi)
- fontname, basename, metrics, sym, offset, char2 = \
- self._get_info(font, symright, fontsize, dpi)
- cmfont = self.fonts[basename]
- return cmfont.get_kern_dist(char1, char2) * 0.001 * fontsize
+ def get_kern(self, fontleft, symleft, fontsizeleft,
+ fontright, symright, fontsizeright, dpi):
+ if fontsizeleft == fontsizeright:
+ basename, font1, metrics, symbol_name, num, glyph1, offset = \
+ self._get_info(fontleft, symleft, fontsizeleft, dpi)
+ basename, font2, metrics, symbol_name, num, glyph2, offset = \
+ self._get_info(fontright, symright, fontsizeright, dpi)
+ if font1.get_fontname() == font2.get_fontname():
+ basename, font = self._get_font(font1)
+ return font.get_kern_dist(glyph1, glyph2) * 0.001 * fontsizeleft
+ return 0.0
 
-class Element:
- fontsize = 12
- dpi = 72
- font = 'it'
- _padx, _pady = 2, 2 # the x and y padding in points
- _scale = 1.0
+ def render_rect_filled(self, x1, y1, x2, y2):
+ ps = "%f %f %f %f rectfill" % (x1, self.height - y2, x2 - x1, y2 - y1)
+ self.pswriter.write(ps)
 
- def __init__(self):
- # a dict mapping the keys above, below, subscript,
- # superscript, right to Elements in that position
- self.neighbors = {}
- self.ox, self.oy = 0, 0
+ def get_xheight(self, font, fontsize, dpi):
+ basename, cached_font = self._get_font(font)
+ return cached_font.get_xheight() * 0.001 * fontsize
 
- def advance(self):
- 'get the horiz advance'
- raise NotImplementedError('derived must override')
+ def get_underline_thickness(self, font, fontsize, dpi):
+ basename, cached_font = self._get_font(font)
+ return cached_font.get_underline_thickness() * 0.001 * fontsize
+ 
+##############################################################################
+# TeX-LIKE BOX MODEL
 
- def height(self):
- 'get the element height: ymax-ymin'
- raise NotImplementedError('derived must override')
+# The following is based directly on the document 'woven' from the
+# TeX82 source code. This information is also available in printed
+# form:
+#
+# Knuth, Donald E.. 1986. Computers and Typesetting, Volume B:
+# TeX: The Program. Addison-Wesley Professional.
+#
+# The most relevant "chapters" are:
+# Data structures for boxes and their friends
+# Shipping pages out (Ship class)
+# Packaging (hpack and vpack)
+# Data structures for math mode
+# Subroutines for math mode
+# Typesetting math formulas
+#
+# Many of the docstrings below refer to a numbered "node" in that
+# book, e.g. @123
+#
+# Note that (as TeX) y increases downward, unlike many other parts of
+# matplotlib.
 
- def width(self):
- 'get the element width: xmax-xmin'
- raise NotImplementedError('derived must override')
+# How much text shrinks when going to the next-smallest level
+SHRINK_FACTOR = 0.7
+# The number of different sizes of chars to use, beyond which they will not
+# get any smaller
+NUM_SIZE_LEVELS = 3
+# Percentage of x-height that subscripts drop below the baseline
+SUBDROP = 0.05
+# Percentage of x-height that superscripts drop below the baseline
+SUP1 = 0.2
+# Percentage of x-height that subscripts drop below the baseline
+SUB1 = 0.3
+# Percentage of x-height that superscripts are offset relative to the subscript
+DELTA = 0.05
+ 
+class MathTextWarning(Warning):
+ pass
+ 
+class Node(object):
+ """A node in a linked list.
+ @133
+ """
+ def __init__(self):
+ self.link = None
+ self.size = 0
+ 
+ def __repr__(self):
+ s = self.__internal_repr__()
+ if self.link:
+ s += ' ' + self.link.__repr__()
+ return s
 
- def xmin(self):
- 'get the xmin of ink rect'
- raise NotImplementedError('derived must override')
+ def __internal_repr__(self):
+ return self.__class__.__name__
 
- def xmax(self):
- 'get the xmax of ink rect'
- raise NotImplementedError('derived must override')
+ def get_kerning(self, next):
+ return 0.0
 
- def ymin(self):
- 'get the ymin of ink rect'
- raise NotImplementedError('derived must override')
+ def set_link(self, other):
+ self.link = other
 
- def ymax(self):
- 'get the ymax of ink rect'
- raise NotImplementedError('derived must override')
+ def pack(self):
+ if self.link:
+ self.link.pack()
 
- def set_font(self, font):
- 'set the font (one of tt, it, rm , cal)'
- raise NotImplementedError('derived must override')
+ def shrink(self):
+ """Shrinks one level smaller. There are only three levels of sizes,
+ after which things will no longer get smaller."""
+ if self.link:
+ self.link.shrink()
+ self.size += 1
+ 
+ def render(self, x, y):
+ pass
 
- def render(self):
- 'render to the fonts canvas'
- for element in self.neighbors.values():
- element.render()
+class Box(Node):
+ """Represents any node with a physical location.
+ @135"""
+ def __init__(self, width, height, depth):
+ Node.__init__(self)
+ self.width = width
+ self.height = height
+ self.depth = depth
 
- def set_origin(self, ox, oy):
- self.ox, self.oy = ox, oy
+ def shrink(self):
+ Node.shrink(self)
+ if self.size < NUM_SIZE_LEVELS:
+ if self.width is not None:
+ self.width *= SHRINK_FACTOR
+ if self.height is not None:
+ self.height *= SHRINK_FACTOR
+ if self.depth is not None:
+ self.depth *= SHRINK_FACTOR
 
- # order matters! right needs to be evaled last
- keys = ('above', 'below', 'subscript', 'superscript', 'right')
- for loc in keys:
- element = self.neighbors.get(loc)
- if element is None: continue
+ def render(self, x1, y1, x2, y2):
+ pass
 
- if loc=='above':
- nx = self.centerx() - element.width()/2.0
- ny = self.ymax() + self.pady() + (element.oy - element.ymax() + element.height())
- #print element, self.ymax(), element.height(), element.ymax(), element.ymin(), ny
- elif loc=='below':
- nx = self.centerx() - element.width()/2.0
- ny = self.ymin() - self.pady() - element.height()
- elif loc=='superscript':
- nx = self.xmax()
- ny = self.ymax() - self.pady()
- elif loc=='subscript':
- nx = self.xmax()
- ny = self.oy - 0.5*element.height()
- elif loc=='right':
- nx = self.ox + self.advance()
- if self.neighbors.has_key('subscript'):
- o = self.neighbors['subscript']
- nx = max(nx, o.ox + o.advance())
- if self.neighbors.has_key('superscript'):
- o = self.neighbors['superscript']
- nx = max(nx, o.ox + o.advance())
+class Vbox(Box):
+ def __init__(self, height, depth):
+ Box.__init__(self, 0., height, depth)
 
- ny = self.oy
- element.set_origin(nx, ny)
+class Hbox(Box):
+ def __init__(self, width):
+ Box.__init__(self, width, 0., 0.)
+ 
+class Char(Node):
+ """Represents a single character. Unlike TeX, the font
+ information and metrics are stored with each Char to make it
+ easier to lookup the font metrics when needed. Note that TeX
+ boxes have a width, height, and depth, unlike Type1 and Truetype
+ which use a full bounding box and an advance in the x-direction.
+ The metrics must be converted to the TeX way, and the advance (if
+ different from width) must be converted into a Kern node when the
+ Char is added to its parent Hlist.
+ @134"""
+ def __init__(self, c, state):
+ Node.__init__(self)
+ self.c = c
+ self.font_output = state.font_output
+ self.font = state.font
+ self.fontsize = state.fontsize
+ self.dpi = state.dpi
+ # The real width, height and depth will be set during the
+ # pack phase, after we know the real fontsize
+ self._update_metrics()
+ 
+ def __internal_repr__(self):
+ return '`%s`' % self.c
 
- def set_size_info(self, fontsize, dpi):
- self.fontsize = self._scale*fontsize
- self.dpi = dpi
- for loc, element in self.neighbors.items():
- if loc in ('subscript', 'superscript'):
- element.set_size_info(0.7*self.fontsize, dpi)
- else:
- element.set_size_info(self.fontsize, dpi)
+ def _update_metrics(self):
+ metrics = self._metrics = self.font_output.get_metrics(
+ self.font, self.c, self.fontsize, self.dpi)
+ self.width = metrics.width
+ self.height = metrics.iceberg
+ self.depth = -(metrics.iceberg - metrics.height)
+ 
+ def get_kerning(self, next):
+ """Return the amount of kerning between this and the given
+ character. Called when characters are strung together into
+ Hlists to create Kern nodes."""
+ advance = self._metrics.advance - self.width
+ kern = 0.
+ if isinstance(next, Char):
+ kern = self.font_output.get_kern(self.font, self.c, self.fontsize, next.font, next.c, next.fontsize, self.dpi)
+ return advance + kern
+ 
+ def render(self, x, y):
+ """Render the character to the canvas"""
+ self.font_output.render(
+ x, y,
+ self.font, self.c, self.fontsize, self.dpi)
 
- def pady(self):
- return self.dpi/72.0*self._pady
+ def shrink(self):
+ Node.shrink(self)
+ if self.size < NUM_SIZE_LEVELS:
+ self.fontsize *= SHRINK_FACTOR
+ self._update_metrics()
 
- def padx(self):
- return self.dpi/72.0*self._padx
+class Accent(Char):
+ """The font metrics need to be dealt with differently for accents, since they
+ are already offset correctly from the baseline in TrueType fonts."""
+ def _update_metrics(self):
+ metrics = self._metrics = self.font_output.get_metrics(
+ self.font, self.c, self.fontsize, self.dpi)
+ self.width = metrics.width
+ self.height = metrics.ymax - metrics.ymin
+ self.depth = 0
 
- def set_padx(self, pad):
- 'set the y padding in points'
- self._padx = pad
+ def render(self, x, y):
+ """Render the character to the canvas"""
+ self.font_output.render(
+ x, y + (self._metrics.ymax - self.height),
+ self.font, self.c, self.fontsize, self.dpi)
+ 
+class List(Box):
+ """A list of nodes (either horizontal or vertical).
+ @135"""
+ def __init__(self, elements):
+ Box.__init__(self, 0., 0., 0.)
+ self.shift_amount = 0. # An arbitrary offset
+ self.list_head = None # The head of a linked list of Nodes in this box
+ # The following parameters are set in the vpack and hpack functions
+ self.glue_set = 0. # The glue setting of this list
+ self.glue_sign = 0 # 0: normal, -1: shrinking, 1: stretching
+ self.glue_order = 0 # The order of infinity (0 - 3) for the glue
+ 
+ # Convert the Python list to a linked list
+ if len(elements):
+ elem = self.list_head = elements[0]
+ for next in elements[1:]:
+ elem.set_link(next)
+ elem = next
 
- def set_pady(self, pad):
- 'set the y padding in points'
- self._pady = pad
+ def ...
 
[truncated message content]
From: <md...@us...> - 2007年07月26日 13:46:59
Revision: 3616
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3616&view=rev
Author: mdboom
Date: 2007年07月26日 06:46:56 -0700 (2007年7月26日)
Log Message:
-----------
Committing in preparation for merge
Modified Paths:
--------------
 branches/mathtext_mgd/examples/mathtext_examples.py
 branches/mathtext_mgd/lib/matplotlib/mathtext.py
Modified: branches/mathtext_mgd/examples/mathtext_examples.py
===================================================================
--- branches/mathtext_mgd/examples/mathtext_examples.py	2007年07月26日 13:26:26 UTC (rev 3615)
+++ branches/mathtext_mgd/examples/mathtext_examples.py	2007年07月26日 13:46:56 UTC (rev 3616)
@@ -10,7 +10,7 @@
 r'$x\leftarrow y\ x\forall y$',
 r'$x \sf x \bf x {\cal X} \rm x$',
 r'$\{ \rm braces \}$',
- r'$\left[\left\lfloor\frac{5}{\frac{3}{4}} y\right)\right]$',
+ r'$\left[\left\lfloor\frac{5}{\frac{\left(3\right)}{4}} y\right)\right]$',
 r'$\left(x\right)$',
 r'$\sin(x)$',
 r'$x_2$',
Modified: branches/mathtext_mgd/lib/matplotlib/mathtext.py
===================================================================
--- branches/mathtext_mgd/lib/matplotlib/mathtext.py	2007年07月26日 13:26:26 UTC (rev 3615)
+++ branches/mathtext_mgd/lib/matplotlib/mathtext.py	2007年07月26日 13:46:56 UTC (rev 3616)
@@ -1728,24 +1728,16 @@
 
 bslash = Literal('\\')
 
- accent = oneOf("hat check dot breve acute ddot grave tilde bar vec "
- "\" ` ' ~ . ^")
+ accent = oneOf("hat check dot breve acute ddot grave tilde bar "
+ "vec \" ` ' ~ . ^")
 
- function = oneOf("arccos csc ker min arcsin deg lg Pr arctan det lim sec "
- "arg dim liminf sin cos exp limsup sinh cosh gcd ln sup "
- "cot hom log tan coth inf max tanh")
+ function = oneOf("arccos csc ker min arcsin deg lg Pr arctan det "
+ "lim sec arg dim liminf sin cos exp limsup sinh "
+ "cosh gcd ln sup cot hom log tan coth inf max "
+ "tanh")
 
 number = Combine(Word(nums) + Optional(Literal('.')) + Optional( Word(nums) ))
 
- plus = Literal('+')
- minus = Literal('-')
- times = Literal('*')
- div = Literal('/')
- binop =(plus 
- | minus
- | times
- | div)
-
 fontname = oneOf("rm cal it tt sf bf")
 latex2efont = oneOf("mathrm mathcal mathit mathtt mathsf mathbf")
 
@@ -1784,7 +1776,9 @@
 
 group = Group(
 start_group
- + OneOrMore(simple)
+ + OneOrMore(
+ autoDelim
+ | simple)
 + end_group
 ).setParseAction(self.group).setName("group")
 
@@ -1833,8 +1827,7 @@
 \updownarrow \Uparrow \Downarrow
 \Updownarrow""")
 leftDelim = oneOf(r"( [ { \lfloor \langle \lceil")
- rightDelim = oneOf(r") ] } \rfloot \rangle \rceil")
-
+ rightDelim = oneOf(r") ] } \rfloor \rangle \rceil")
 autoDelim <<(Suppress(Literal(r"\left"))
 + (leftDelim | ambiDelim)
 + Group(
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年07月26日 13:26:29
Revision: 3615
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3615&view=rev
Author: mdboom
Date: 2007年07月26日 06:26:26 -0700 (2007年7月26日)
Log Message:
-----------
Important bugfix (many expressions were silently failing)
Modified Paths:
--------------
 branches/mathtext_mgd/examples/mathtext_examples.py
 branches/mathtext_mgd/lib/matplotlib/_mathtext_data.py
 branches/mathtext_mgd/lib/matplotlib/mathtext.py
Modified: branches/mathtext_mgd/examples/mathtext_examples.py
===================================================================
--- branches/mathtext_mgd/examples/mathtext_examples.py	2007年07月25日 20:19:25 UTC (rev 3614)
+++ branches/mathtext_mgd/examples/mathtext_examples.py	2007年07月26日 13:26:26 UTC (rev 3615)
@@ -52,7 +52,7 @@
 os.system("pdflatex mathtext_examples.ltx")
 else:
 for i, s in enumerate(stests):
- print s
+ print "%02d: %s" % (i, s)
 plot([1,2,3], 'r')
 x = arange(0.0, 3.0, 0.1)
 
Modified: branches/mathtext_mgd/lib/matplotlib/_mathtext_data.py
===================================================================
--- branches/mathtext_mgd/lib/matplotlib/_mathtext_data.py	2007年07月25日 20:19:25 UTC (rev 3614)
+++ branches/mathtext_mgd/lib/matplotlib/_mathtext_data.py	2007年07月26日 13:26:26 UTC (rev 3615)
@@ -38,8 +38,10 @@
 r'\SQRT' : ('cmex10', 53),
 r'\leftbrace' : ('cmex10', 92),
 r'{' : ('cmex10', 92),
+ r'\{' : ('cmex10', 92),
 r'\rightbrace' : ('cmex10', 130),
 r'}' : ('cmex10', 130),
+ r'\}' : ('cmex10', 130),
 r'\leftangle' : ('cmex10', 97),
 r'\rightangle' : ('cmex10', 64),
 r'\Leftparen' : ('cmex10', 112),
Modified: branches/mathtext_mgd/lib/matplotlib/mathtext.py
===================================================================
--- branches/mathtext_mgd/lib/matplotlib/mathtext.py	2007年07月25日 20:19:25 UTC (rev 3614)
+++ branches/mathtext_mgd/lib/matplotlib/mathtext.py	2007年07月26日 13:26:26 UTC (rev 3615)
@@ -59,17 +59,10 @@
 ^
 use raw strings
 
- The $ symbols must be the first and last symbols in the string. Eg,
- you cannot do
+ Math and non-math can be interpresed in the same string. E.g.,
 
 r'My label $x_i$'.
 
- but you can change fonts, as in
-
- r'$\rm{My label} x_i$'
-
- to achieve the same effect.
-
 A large set of the TeX symbols are provided. Subscripting and
 superscripting are supported, as well as the over/under style of
 subscripting with \sum, \int, etc.
@@ -1714,7 +1707,7 @@
 
 _spaced_symbols = _binary_operators | _relation_symbols | _arrow_symbols
 
- _punctuation_symbols = Set(r', ; . !'.split())
+ _punctuation_symbols = Set(r', ; . ! \ldotp \cdotp'.split())
 
 def __init__(self):
 # All forward declarations are here
@@ -1769,15 +1762,14 @@
 
 symbol = Regex("(" + ")|(".join(
 [
- r"\\(?!right)(?!left)[a-zA-Z0-9]+(?!{)",
+ r"\\(?!left[^a-z])(?!right[^a-z])[a-zA-Z0-9]+(?!{)",
 r"[a-zA-Z0-9 ]",
 r"[+\-*/]",
 r"[<>=]",
 r"[:,.;!]",
 r"[!@%&]",
 r"[[\]()]",
- r"\\\$",
- r"\\\%"
+ r"\\[$%{}]",
 ])
 + ")"
 ).setParseAction(self.symbol).leaveWhitespace()
@@ -1828,7 +1820,7 @@
 ) 
 
 subsuper << Group(
- ( placeable
+ ( Optional(placeable)
 + OneOrMore(
 subsuperop
 + placeable
@@ -1837,7 +1829,9 @@
 | placeable
 )
 
- ambiDelim = oneOf(r"| \| / \backslash \uparrow \downarrow \updownarrow \Uparrow \Downarrow \Updownarrow")
+ ambiDelim = oneOf(r"""| \| / \backslash \uparrow \downarrow
+ \updownarrow \Uparrow \Downarrow
+ \Updownarrow""")
 leftDelim = oneOf(r"( [ { \lfloor \langle \lceil")
 rightDelim = oneOf(r") ] } \rfloot \rangle \rceil")
 
@@ -1861,9 +1855,9 @@
 non_math = Regex(r"(?:[^$]|(?:\\\$))*"
 ).setParseAction(self.non_math).setName("non_math").leaveWhitespace()
 
- self._expression <<(
+ self._expression <<(
 non_math
- + ZeroOrMore(
+ + OneOrMore(
 Suppress(math_delim)
 + math
 + Suppress(math_delim)
@@ -1908,6 +1902,7 @@
 return [self._expr]
 
 def math(self, s, loc, toks):
+ #~ print "math", toks
 hlist = Hlist(toks)
 self.pop_state()
 return [hlist]
@@ -2164,6 +2159,7 @@
 return [hlist]
 
 def auto_sized_delimiter(self, s, loc, toks):
+ #~ print "auto_sized_delimiter", toks
 front, middle, back = toks
 state = self.get_state()
 height = max([x.height for x in middle])
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年07月25日 20:19:29
Revision: 3614
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3614&view=rev
Author: mdboom
Date: 2007年07月25日 13:19:25 -0700 (2007年7月25日)
Log Message:
-----------
Support auto-sized delimiters (e.g. \left(\frac{3}{2}\right)).
Commit mathtext_examples.py
Modified Paths:
--------------
 branches/mathtext_mgd/lib/matplotlib/mathtext.py
Added Paths:
-----------
 branches/mathtext_mgd/examples/mathtext_examples.py
Added: branches/mathtext_mgd/examples/mathtext_examples.py
===================================================================
--- branches/mathtext_mgd/examples/mathtext_examples.py	 (rev 0)
+++ branches/mathtext_mgd/examples/mathtext_examples.py	2007年07月25日 20:19:25 UTC (rev 3614)
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+import os, sys
+
+stests = [
+ r'Kerning: AVA $AVA$',
+ r'$x y$',
+ r'$x+y\ x=y\ x<y\ x:y\ x,y\ x@y$',
+ r'100ドル\%y\ x*y\ x/y x\$y$',
+ r'$x\leftarrow y\ x\forall y$',
+ r'$x \sf x \bf x {\cal X} \rm x$',
+ r'$\{ \rm braces \}$',
+ r'$\left[\left\lfloor\frac{5}{\frac{3}{4}} y\right)\right]$',
+ r'$\left(x\right)$',
+ r'$\sin(x)$',
+ r'$x_2$',
+ r'$x^2$',
+ r'$x^2_y$',
+ r'$x_y^2$',
+ r'$\prod_{i=\alpha_{i+1}}^\infty$',
+ r'$x = \frac{x+\frac{5}{2}}{\frac{y+3}{8}}$',
+ r'$dz/dt \/ = \/ \gamma x^2 \/ + \/ {\rm sin}(2\pi y+\phi)$',
+ r'Foo: $\alpha_{i+1}^j \/ = \/ {\rm sin}(2\pi f_j t_i) e^{-5 t_i/\tau}$',
+ r'$\mathcal{R}\prod_{i=\alpha_{i+1}}^\infty a_i \sin(2 \pi f x_i)$',
+# r'$\bigodot \bigoplus {\sf R} a_i{\rm sin}(2 \pi f x_i)$',
+ r'Variable $i$ is good',
+ r'$\Delta_i^j$',
+ r'$\Delta^j_{i+1}$',
+ r'$\ddot{o}\acute{e}\grave{e}\hat{O}\breve{\imath}\tilde{n}\vec{q}$',
+ r'$_i$',
+ r"$\arccos((x^i))$",
+ r"$\gamma = \frac{x=\frac{6}{8}}{y} \delta$",
+ r'$\"o\ddot o \'e\`e\~n\.x\^y$',
+ 
+ ]
+
+from pylab import *
+
+if '--latex' in sys.argv:
+ fd = open("mathtext_examples.ltx", "w")
+ fd.write("\\documentclass{article}\n")
+ fd.write("\\begin{document}\n")
+ fd.write("\\begin{enumerate}\n")
+
+ for i, s in enumerate(stests):
+ fd.write("\\item %s\n" % s)
+
+ fd.write("\\end{enumerate}\n")
+ fd.write("\\end{document}\n")
+ fd.close()
+
+ os.system("pdflatex mathtext_examples.ltx")
+else:
+ for i, s in enumerate(stests):
+ print s
+ plot([1,2,3], 'r')
+ x = arange(0.0, 3.0, 0.1)
+
+ grid(True)
+ text(1, 1.6, s, fontsize=20)
+
+ savefig('mathtext_example%02d' % i)
+ figure()
+
Property changes on: branches/mathtext_mgd/examples/mathtext_examples.py
___________________________________________________________________
Name: svn:executable
 + *
Modified: branches/mathtext_mgd/lib/matplotlib/mathtext.py
===================================================================
--- branches/mathtext_mgd/lib/matplotlib/mathtext.py	2007年07月25日 16:17:22 UTC (rev 3613)
+++ branches/mathtext_mgd/lib/matplotlib/mathtext.py	2007年07月25日 20:19:25 UTC (rev 3614)
@@ -739,12 +739,6 @@
 Use the Bakoma postscript fonts for rendering to backend_ps
 """
 
- def _get_offset(self, basename, cached_font, glyph, fontsize, dpi):
- head = cached_font.font.get_sfnt_table("head")
- if basename.lower() == 'cmex10':
- return -(head['yMin']+512)/head['unitsPerEm']*10.
- return 0.
- 
 def set_canvas_size(self, w, h, pswriter):
 'Dimension the drawing canvas; may be a noop'
 self.width = w
@@ -756,7 +750,7 @@
 self._get_info(font, sym, fontsize, dpi)
 oy = self.height - oy
 if basename.lower() == 'cmex10':
- oy += offset - 512/2048.*10.
+ oy += offset
 
 ps = """/%(basename)s findfont
 %(fontsize)s scalefont
@@ -1067,7 +1061,7 @@
 self._update_metrics()
 
 def __internal_repr__(self):
- return repr(self.c)
+ return '`%s`' % self.c
 
 def _update_metrics(self):
 metrics = self._metrics = self.font_output.get_metrics(
@@ -1097,7 +1091,7 @@
 if self.size < NUM_SIZE_LEVELS:
 self.fontsize *= SHRINK_FACTOR
 self._update_metrics()
- 
+
 class Accent(Char):
 """The font metrics need to be dealt with differently for accents, since they
 are already offset correctly from the baseline in TrueType fonts."""
@@ -1305,7 +1299,7 @@
 p = self.list_head
 while p is not None:
 if isinstance(p, Char):
- raise RuntimeError("Internal error in mathtext")
+ raise RuntimeError("Internal mathtext error: Char node found in Vlist.")
 elif isinstance(p, Box):
 x += d + p.height
 d = p.depth
@@ -1504,6 +1498,19 @@
 self.super = None
 Hlist.__init__(self, [])
 
+class AutoSizedDelim(Hlist):
+ def __init__(self, c, height, depth, state):
+ char = Char(c, state)
+ shift = 0.
+ if char.height + char.depth < height + depth:
+ factor = (height + depth) / (char.height + char.depth)
+ fontsize = char.fontsize * factor
+ state = state.copy()
+ state.fontsize = fontsize
+ char = Char(c, state)
+ shift = (depth - char.depth)
+ Hlist.__init__(self, [char])
+ self.shift_amount = shift
 
 class Ship(object):
 """Once the boxes have been set up, this sends them to output.
@@ -1612,7 +1619,7 @@
 
 while p:
 if isinstance(p, Char):
- raise RuntimeError("Internal error in mathtext")
+ raise RuntimeError("Internal mathtext error: Char node found in vlist")
 elif isinstance(p, List):
 if p.list_head is None:
 self.cur_v += p.height + p.depth
@@ -1663,7 +1670,7 @@
 ##############################################################################
 # PARSER
 
-class Parser:
+class Parser(object):
 _binary_operators = Set(r'''
 + - *
 \pm \sqcap \rhd
@@ -1707,7 +1714,7 @@
 
 _spaced_symbols = _binary_operators | _relation_symbols | _arrow_symbols
 
- _delimiter_symbols = Set(r', ; . !'.split())
+ _punctuation_symbols = Set(r', ; . !'.split())
 
 def __init__(self):
 # All forward declarations are here
@@ -1716,6 +1723,7 @@
 subsuper = Forward().setParseAction(self.subsuperscript).setName("subsuper")
 placeable = Forward().setName("placeable")
 simple = Forward().setName("simple")
+ autoDelim = Forward().setParseAction(self.auto_sized_delimiter)
 self._expression = Forward().setParseAction(self.finish).setName("finish")
 
 lbrace = Literal('{').suppress()
@@ -1724,42 +1732,9 @@
 start_group.setParseAction(self.start_group)
 end_group = rbrace
 end_group.setParseAction(self.end_group)
- lbrack = Literal('[')
- rbrack = Literal(']')
- lparen = Literal('(')
- rparen = Literal(')')
- grouping =(lbrack 
- | rbrack 
- | lparen 
- | rparen)
 
 bslash = Literal('\\')
 
- langle = Literal('<')
- rangle = Literal('>')
- equals = Literal('=')
- relation =(langle
- | rangle
- | equals)
-
- colon = Literal(':')
- comma = Literal(',')
- period = Literal('.')
- semicolon = Literal(';')
- exclamation = Literal('!')
- punctuation =(colon
- | comma
- | period
- | semicolon)
-
- at = Literal('@')
- percent = Literal('%')
- ampersand = Literal('&')
- misc =(exclamation
- | at
- | percent
- | ampersand)
-
 accent = oneOf("hat check dot breve acute ddot grave tilde bar vec "
 "\" ` ' ~ . ^")
 
@@ -1794,7 +1769,7 @@
 
 symbol = Regex("(" + ")|(".join(
 [
- r"\\[a-zA-Z0-9]+(?!{)",
+ r"\\(?!right)(?!left)[a-zA-Z0-9]+(?!{)",
 r"[a-zA-Z0-9 ]",
 r"[+\-*/]",
 r"[<>=]",
@@ -1845,7 +1820,8 @@
 
 simple <<(space
 | font
- | subsuper)
+ | subsuper
+ )
 
 subsuperop =(Literal("_")
 | Literal("^")
@@ -1861,8 +1837,22 @@
 | placeable
 )
 
+ ambiDelim = oneOf(r"| \| / \backslash \uparrow \downarrow \updownarrow \Uparrow \Downarrow \Updownarrow")
+ leftDelim = oneOf(r"( [ { \lfloor \langle \lceil")
+ rightDelim = oneOf(r") ] } \rfloot \rangle \rceil")
+
+ autoDelim <<(Suppress(Literal(r"\left"))
+ + (leftDelim | ambiDelim)
+ + Group(
+ autoDelim
+ ^ OneOrMore(simple))
+ + Suppress(Literal(r"\right"))
+ + (rightDelim | ambiDelim) 
+ )
+ 
 math = OneOrMore(
- simple
+ autoDelim
+ | simple
 ).setParseAction(self.math).setName("math")
 
 math_delim =(~bslash
@@ -1955,7 +1945,7 @@
 return [Hlist([self._make_space(0.3),
 Char(c, self.get_state()),
 self._make_space(0.3)])]
- elif c in self._delimiter_symbols:
+ elif c in self._punctuation_symbols:
 return [Hlist([Char(c, self.get_state()),
 self._make_space(0.3)])]
 return [Char(toks[0], self.get_state())]
@@ -2173,8 +2163,17 @@
 hlist = Hlist([vlist, FixedGlue(thickness * 2.)])
 return [hlist]
 
+ def auto_sized_delimiter(self, s, loc, toks):
+ front, middle, back = toks
+ state = self.get_state()
+ height = max([x.height for x in middle])
+ depth = max([x.depth for x in middle])
+ hlist = Hlist(
+ [AutoSizedDelim(front, height, depth, state)] +
+ middle.asList() +
+ [AutoSizedDelim(back, height, depth, state)])
+ return hlist
 
-
 ####
 
 ##############################################################################
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3613
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3613&view=rev
Author: jdh2358
Date: 2007年07月25日 09:17:22 -0700 (2007年7月25日)
Log Message:
-----------
rewrote mathext demo to use pythonic api
Modified Paths:
--------------
 branches/mathtext_mgd/examples/mathtext_demo.py
Modified: branches/mathtext_mgd/examples/mathtext_demo.py
===================================================================
--- branches/mathtext_mgd/examples/mathtext_demo.py	2007年07月25日 15:34:52 UTC (rev 3612)
+++ branches/mathtext_mgd/examples/mathtext_demo.py	2007年07月25日 16:17:22 UTC (rev 3613)
@@ -1,27 +1,26 @@
 #!/usr/bin/env python
 """
-
-In order to use mathtext, you must build matplotlib.ft2font. This is
-built by default in the windows installer.
-
-For other platforms, edit setup.py and set
-
-BUILD_FT2FONT = True
-
+Use matplotlib's internal LaTex parser and layout engine. For true
+latex rendering, see the text.usetex option
 """
-from pylab import *
-subplot(111, axisbg='y')
-plot([1,2,3], 'r')
-x = arange(0.0, 3.0, 0.1)
+import numpy as npy
+from pylab import figure, show
+fig = figure()
+fig.subplots_adjust(bottom=0.2)
 
-grid(True)
-xlabel(r'$\Delta_i^j$', fontsize=20)
-ylabel(r'$\Delta_{i+1}^j$', fontsize=20)
+ax = fig.add_subplot(111, axisbg='y')
+ax.plot([1,2,3], 'r')
+x = npy.arange(0.0, 3.0, 0.1)
+
+ax.grid(True)
+ax.set_xlabel(r'$\Delta_i^j$', fontsize=20)
+ax.set_ylabel(r'$\Delta_{i+1}^j$', fontsize=20)
 tex = r'$\mathcal{R}\prod_{i=\alpha_{i+1}}^\infty a_i\sin(2 \pi f x_i)$'
-text(1, 1.6, tex, fontsize=20, va='bottom')
 
+ax.text(1, 1.6, tex, fontsize=20, va='bottom')
+
 #title(r'$\Delta_i^j \hspace{0.4} \rm{versus} \hspace{0.4} \Delta_{i+1}^j$', fontsize=20)
-savefig('mathtext_demo')
+fig.savefig('mathtext_demo')
 
 
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年07月25日 15:40:14
Revision: 3612
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3612&view=rev
Author: mdboom
Date: 2007年07月25日 08:34:52 -0700 (2007年7月25日)
Log Message:
-----------
Fix for get_xheight/get_underline_thickness. Update examples to use
new math syntax.
Modified Paths:
--------------
 branches/mathtext_mgd/examples/mathtext_demo.py
 branches/mathtext_mgd/lib/matplotlib/mathtext.py
Modified: branches/mathtext_mgd/examples/mathtext_demo.py
===================================================================
--- branches/mathtext_mgd/examples/mathtext_demo.py	2007年07月25日 14:43:13 UTC (rev 3611)
+++ branches/mathtext_mgd/examples/mathtext_demo.py	2007年07月25日 15:34:52 UTC (rev 3612)
@@ -17,8 +17,8 @@
 grid(True)
 xlabel(r'$\Delta_i^j$', fontsize=20)
 ylabel(r'$\Delta_{i+1}^j$', fontsize=20)
-tex = r'$\cal{R}\prod_{i=\alpha_{i+1}}^\infty a_i\rm{sin}(2 \pi f x_i)$'
-text(1, 1.6, tex, fontsize=20)
+tex = r'$\mathcal{R}\prod_{i=\alpha_{i+1}}^\infty a_i\sin(2 \pi f x_i)$'
+text(1, 1.6, tex, fontsize=20, va='bottom')
 
 #title(r'$\Delta_i^j \hspace{0.4} \rm{versus} \hspace{0.4} \Delta_{i+1}^j$', fontsize=20)
 savefig('mathtext_demo')
Modified: branches/mathtext_mgd/lib/matplotlib/mathtext.py
===================================================================
--- branches/mathtext_mgd/lib/matplotlib/mathtext.py	2007年07月25日 14:43:13 UTC (rev 3611)
+++ branches/mathtext_mgd/lib/matplotlib/mathtext.py	2007年07月25日 15:34:52 UTC (rev 3612)
@@ -699,7 +699,6 @@
 basename, font, metrics, symbol_name, num, glyph, offset = \
 self._get_info(font, sym, fontsize, dpi)
 
- font.draw_rect(0, 0, self.width - 1, self.height - 1)
 font.draw_glyph_to_bitmap(
 int(ox), int(oy - metrics.ymax), glyph)
 
@@ -711,16 +710,16 @@
 def get_used_characters(self):
 return self.used_characters
 
- def get_xheight(self, font, fontsize):
+ def get_xheight(self, font, fontsize, dpi):
 basename, cached_font = self._get_font(font)
- cached_font.font.set_size(fontsize)
+ cached_font.font.set_size(fontsize, dpi)
 pclt = cached_font.font.get_sfnt_table('pclt')
 xHeight = pclt['xHeight'] / 64.0
 return xHeight
 
- def get_underline_thickness(self, font, fontsize):
+ def get_underline_thickness(self, font, fontsize, dpi):
 basename, cached_font = self._get_font(font)
- cached_font.font.set_size(fontsize)
+ cached_font.font.set_size(fontsize, dpi)
 return max(1.0, cached_font.font.underline_thickness / 64.0)
 
 def get_kern(self, fontleft, symleft, fontsizeleft,
@@ -944,11 +943,11 @@
 ps = "%f %f %f %f rectfill" % (x1, self.height - y2, x2 - x1, y2 - y1)
 self.pswriter.write(ps)
 
- def get_xheight(self, font, fontsize):
+ def get_xheight(self, font, fontsize, dpi):
 basename, cached_font = self._get_font(font)
 return cached_font.get_xheight() * 0.001 * fontsize
 
- def get_underline_thickness(self, font, fontsize):
+ def get_underline_thickness(self, font, fontsize, dpi):
 basename, cached_font = self._get_font(font)
 return cached_font.get_underline_thickness() * 0.001 * fontsize
 
@@ -1367,7 +1366,7 @@
 """Convenience class to create a horizontal rule."""
 def __init__(self, state):
 thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize)
+ state.font, state.fontsize, state.dpi)
 height = depth = thickness * 0.5
 Rule.__init__(self, None, height, depth, state)
 
@@ -1375,7 +1374,7 @@
 """Convenience class to create a vertical rule."""
 def __init__(self, state):
 thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize)
+ state.font, state.fontsize, state.dpi)
 Rule.__init__(self, thickness, None, None, state)
 
 class Glue(Node):
@@ -1950,6 +1949,7 @@
 return [box]
 
 def symbol(self, s, loc, toks):
+ # print "symbol", toks
 c = toks[0]
 if c in self._spaced_symbols:
 return [Hlist([self._make_space(0.3),
@@ -1982,7 +1982,7 @@
 assert(len(toks)==1)
 state = self.get_state()
 thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize)
+ state.font, state.fontsize, state.dpi)
 accent, sym = toks[0]
 accent = Accent(self._accent_map[accent], self.get_state())
 centered = HCentered([accent])
@@ -2067,11 +2067,12 @@
 sub = next2
 else:
 raise ParseFatalException("Subscript/superscript string is too long.")
-
+ 
 state = self.get_state()
 rule_thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize)
- xHeight = state.font_output.get_xheight(state.font, state.fontsize)
+ state.font, state.fontsize, state.dpi)
+ xHeight = state.font_output.get_xheight(
+ state.font, state.fontsize, state.dpi)
 
 if self.is_overunder(nucleus):
 vlist = []
@@ -2155,7 +2156,7 @@
 cden.hpack(width, 'exactly')
 state = self.get_state()
 thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize)
+ state.font, state.fontsize, state.dpi)
 space = thickness * 3.0
 vlist = Vlist([cnum,
 FixedGlue(thickness * 2.0),
@@ -2243,7 +2244,7 @@
 pswriter = list()
 font_output.set_canvas_size(w, h, pswriter)
 ship(2, 2, box)
- 
+
 if self.output == 'SVG':
 # The empty list at the end is for lines
 svg_elements = Bunch(svg_glyphs=font_output.svg_glyphs,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.

Showing results of 5455

<< < 1 .. 213 214 215 216 217 .. 219 > >> (Page 215 of 219)
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.
Thanks for helping keep SourceForge clean.
X





Briefly describe the problem (required):
Upload screenshot of ad (required):
Select a file, or drag & drop file here.
Screenshot instructions:

Click URL instructions:
Right-click on the ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)

More information about our ad policies

Ad destination/click URL:

AltStyle によって変換されたページ (->オリジナル) /