SourceForge logo
SourceForge logo
Menu

matplotlib-checkins

From: <mme...@us...> - 2008年12月12日 13:58:34
Revision: 6589
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6589&view=rev
Author: mmetz_bn
Date: 2008年12月12日 13:58:24 +0000 (2008年12月12日)
Log Message:
-----------
fix warning in hist for numpy 1.2
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/lib/matplotlib/axes.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月12日 13:42:22 UTC (rev 6588)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月12日 13:58:24 UTC (rev 6589)
@@ -1,3 +1,5 @@
+2008年12月12日 Fixed warning in hist() with numpy 1.2 - MM
+
 =================================================================
 2008年12月09日 Released 0.98.5 at svn r6573
 
Modified: branches/v0_98_5_maint/lib/matplotlib/axes.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/axes.py	2008年12月12日 13:42:22 UTC (rev 6588)
+++ branches/v0_98_5_maint/lib/matplotlib/axes.py	2008年12月12日 13:58:24 UTC (rev 6589)
@@ -6568,10 +6568,10 @@
 binsgiven = (cbook.iterable(bins) or range != None)
 
 # check the version of the numpy
- if np.__version__ < "1.2": # version 1.1
+ if np.__version__ < "1.3": # version 1.1 and 1.2
 hist_kwargs = dict(range=range,
 normed=bool(normed), new=True)
- else: # version 1.2 and later, drop new=True
+ else: # version 1.3 and later, drop new=True
 hist_kwargs = dict(range=range,
 normed=bool(normed))
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2008年12月15日 14:16:32
Revision: 6608
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6608&view=rev
Author: mdboom
Date: 2008年12月15日 14:16:27 +0000 (2008年12月15日)
Log Message:
-----------
Fix gridlines not moving correctly during pan and zoom
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/lib/matplotlib/transforms.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月15日 06:26:18 UTC (rev 6607)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月15日 14:16:27 UTC (rev 6608)
@@ -1,3 +1,5 @@
+2008年12月15日 Fix grid lines not moving correctly during pan and zoom - MGD
+
 2008年12月12日 Fixed warning in hist() with numpy 1.2 - MM
 
 =================================================================
Modified: branches/v0_98_5_maint/lib/matplotlib/transforms.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/transforms.py	2008年12月15日 06:26:18 UTC (rev 6607)
+++ branches/v0_98_5_maint/lib/matplotlib/transforms.py	2008年12月15日 14:16:27 UTC (rev 6608)
@@ -120,8 +120,7 @@
 root = stack.pop()
 # Stop at subtrees that have already been invalidated
 if root._invalid != value or root.pass_through:
- value |= root._invalid
- root._invalid = value
+ root._invalid = self.INVALID
 stack.extend(root._parents.keys())
 
 def set_children(self, *children):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2008年12月15日 14:18:06
Revision: 6609
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6609&view=rev
Author: mdboom
Date: 2008年12月15日 14:18:03 +0000 (2008年12月15日)
Log Message:
-----------
Turn off anti-aliasing when auto-snapping.
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/src/_backend_agg.cpp
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月15日 14:16:27 UTC (rev 6608)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月15日 14:18:03 UTC (rev 6609)
@@ -1,3 +1,5 @@
+2008年12月15日 Fix anti-aliasing when auto-snapping - MGD
+
 2008年12月15日 Fix grid lines not moving correctly during pan and zoom - MGD
 
 2008年12月12日 Fixed warning in hist() with numpy 1.2 - MM
Modified: branches/v0_98_5_maint/src/_backend_agg.cpp
===================================================================
--- branches/v0_98_5_maint/src/_backend_agg.cpp	2008年12月15日 14:16:27 UTC (rev 6608)
+++ branches/v0_98_5_maint/src/_backend_agg.cpp	2008年12月15日 14:18:03 UTC (rev 6609)
@@ -355,7 +355,7 @@
 }
 
 template<class Path>
-bool should_snap(const GCAgg& gc, Path& path, const agg::trans_affine& trans) {
+bool should_snap(GCAgg& gc, Path& path, const agg::trans_affine& trans) {
 // If this contains only straight horizontal or vertical lines, it should be
 // quantized to the nearest pixels
 double x0, y0, x1, y1;
@@ -393,6 +393,7 @@
 }
 
 path.rewind(0);
+ gc.isaa = false;
 return true;
 case GCAgg::SNAP_FALSE:
 return false;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2008年12月15日 18:03:37
Revision: 6614
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6614&view=rev
Author: mdboom
Date: 2008年12月15日 18:03:34 +0000 (2008年12月15日)
Log Message:
-----------
Backporting 6613: Making $ work in regular text
Modified Paths:
--------------
 branches/v0_98_5_maint/doc/users/mathtext.rst
 branches/v0_98_5_maint/doc/users/text_intro.rst
 branches/v0_98_5_maint/doc/users/usetex.rst
 branches/v0_98_5_maint/lib/matplotlib/offsetbox.py
 branches/v0_98_5_maint/lib/matplotlib/text.py
Modified: branches/v0_98_5_maint/doc/users/mathtext.rst
===================================================================
--- branches/v0_98_5_maint/doc/users/mathtext.rst	2008年12月15日 17:58:43 UTC (rev 6613)
+++ branches/v0_98_5_maint/doc/users/mathtext.rst	2008年12月15日 18:03:34 UTC (rev 6614)
@@ -3,17 +3,19 @@
 Writing mathematical expressions
 ================================
 
-You can use TeX markup in any matplotlib text string. Note that you
-do not need to have TeX installed, since matplotlib ships its own TeX
-expression parser, layout engine and fonts. The layout engine is a
-fairly direct adaptation of the layout algorithms in Donald Knuth's
-TeX, so the quality is quite good (matplotlib also provides a
-``usetex`` option for those who do want to call out to TeX to generate
-their text (see :ref:`usetex-tutorial`).
+You can use a subset TeX markup in any matplotlib text string by
+placing it inside a pair of dollar signs ($).
 
-Any text element can use math text. You need to use raw strings
-(preceed the quotes with an ``'r'``), and surround the string text
-with dollar signs, as in TeX. Regular text and mathtext can be
+Note that you do not need to have TeX installed, since matplotlib
+ships its own TeX expression parser, layout engine and fonts. The
+layout engine is a fairly direct adaptation of the layout algorithms
+in Donald Knuth's TeX, so the quality is quite good (matplotlib also
+provides a ``usetex`` option for those who do want to call out to TeX
+to generate their text (see :ref:`usetex-tutorial`).
+
+Any text element can use math text. You should use raw strings
+(preceed the quotes with an ``'r'``), and surround the math text with
+dollar signs ($), as in TeX. Regular text and mathtext can be
 interleaved within the same string. Mathtext can use the Computer
 Modern fonts (from (La)TeX), `STIX <http://www.aip.org/stixfonts/>`_
 fonts (with are designed to blend well with Times) or a Unicode font
@@ -35,6 +37,26 @@
 
 produces ":math:`\alpha > \beta`".
 
+.. note::
+ Mathtext should be placed between a pair of dollar signs ($). To
+ make it easy to display monetary values, e.g. "100ドル.00", if a
+ single dollar sign is present in the entire string, it will be
+ displayed verbatim as a dollar sign. This is a small change from
+ regular TeX, where the dollar sign in non-math text would have to
+ be escaped ('\$').
+
+.. note::
+ While the syntax inside the pair of dollar signs ($) aims to be
+ TeX-like, the text outside does not. In particular, characters
+ such as::
+
+ # $ % & ~ _ ^ \ { } \( \) \[ \]
+
+ have special meaning outside of math mode in TeX. Therefore, these
+ characters will behave differently depending on the rcParam
+ ``text.usetex`` flag. See the :ref:`usetex tutorial
+ <usetex-tutorial>` for more information.
+
 Subscripts and superscripts
 ---------------------------
 
Modified: branches/v0_98_5_maint/doc/users/text_intro.rst
===================================================================
--- branches/v0_98_5_maint/doc/users/text_intro.rst	2008年12月15日 17:58:43 UTC (rev 6613)
+++ branches/v0_98_5_maint/doc/users/text_intro.rst	2008年12月15日 18:03:34 UTC (rev 6614)
@@ -18,8 +18,8 @@
 weight, text location and color, etc) with sensible defaults set in
 the rc file. And significantly for those interested in mathematical
 or scientific figures, matplotlib implements a large number of TeX
-math symbols and commands, to support mathematical expressions
-anywhere in your figure.
+math symbols and commands, to support :ref:`mathematical expressions
+<mathtext-tutorial>` anywhere in your figure.
 
 
 Basic text commands
Modified: branches/v0_98_5_maint/doc/users/usetex.rst
===================================================================
--- branches/v0_98_5_maint/doc/users/usetex.rst	2008年12月15日 17:58:43 UTC (rev 6613)
+++ branches/v0_98_5_maint/doc/users/usetex.rst	2008年12月15日 18:03:34 UTC (rev 6614)
@@ -59,6 +59,14 @@
 command ``\displaystyle``, as in `tex_demo.py`, will produce the same
 results.
 
+.. note::
+ Certain characters require special escaping in TeX, such as::
+
+ # $ % & ~ _ ^ \ { } \( \) \[ \]
+
+ Therefore, these characters will behave differently depending on
+ the rcParam ``text.usetex`` flag.
+
 .. _usetex-unicode:
 
 usetex with unicode
Modified: branches/v0_98_5_maint/lib/matplotlib/offsetbox.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/offsetbox.py	2008年12月15日 17:58:43 UTC (rev 6613)
+++ branches/v0_98_5_maint/lib/matplotlib/offsetbox.py	2008年12月15日 18:03:34 UTC (rev 6614)
@@ -548,7 +548,7 @@
 
 
 def get_extent(self, renderer):
- ismath = self._text.is_math_text(self._text._text)
+ clean_line, ismath = self._text.is_math_text(self._text._text)
 _, h_, d_ = renderer.get_text_width_height_descent(
 "lp", self._text._fontproperties, ismath=False)
 
@@ -558,30 +558,30 @@
 line = info[0][0] # first line
 
 _, hh, dd = renderer.get_text_width_height_descent(
- line, self._text._fontproperties, ismath=ismath)
+ clean_line, self._text._fontproperties, ismath=ismath)
 
 
 self._baseline_transform.clear()
 if len(info) > 1 and self._multilinebaseline: # multi line
 d = h-(hh-dd) # the baseline of the first line
 d_new = 0.5 * h - 0.5 * (h_ - d_)
- 
+
 self._baseline_transform.translate(0, d - d_new)
 d = d_new
- 
+
 else: # single line
 
 h_d = max(h_ - d_, h-dd)
 
 if self.get_minimumdescent():
 ## to have a minimum descent, #i.e., "l" and "p" have same
- ## descents. 
+ ## descents.
 d = max(dd, d_)
 else:
 d = dd
 
 h = h_d + d
- 
+
 return w, h, 0., d
 
 
Modified: branches/v0_98_5_maint/lib/matplotlib/text.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/text.py	2008年12月15日 17:58:43 UTC (rev 6613)
+++ branches/v0_98_5_maint/lib/matplotlib/text.py	2008年12月15日 18:03:34 UTC (rev 6614)
@@ -248,8 +248,9 @@
 
 baseline = None
 for i, line in enumerate(lines):
+ clean_line, ismath = self.is_math_text(line)
 w, h, d = renderer.get_text_width_height_descent(
- line, self._fontproperties, ismath=self.is_math_text(line))
+ clean_line, self._fontproperties, ismath=ismath)
 if baseline is None:
 baseline = h - d
 whs[i] = w, h
@@ -480,8 +481,9 @@
 y = y + posy
 if renderer.flipy():
 y = canvash-y
+ clean_line, ismath = self.is_math_text(line)
 
- renderer.draw_tex(gc, x, y, line,
+ renderer.draw_tex(gc, x, y, clean_line,
 self._fontproperties, angle)
 return
 
@@ -490,10 +492,11 @@
 y = y + posy
 if renderer.flipy():
 y = canvash-y
+ clean_line, ismath = self.is_math_text(line)
 
- renderer.draw_text(gc, x, y, line,
+ renderer.draw_text(gc, x, y, clean_line,
 self._fontproperties, angle,
- ismath=self.is_math_text(line))
+ ismath=ismath)
 
 def get_color(self):
 "Return the color of the text"
@@ -873,16 +876,19 @@
 """
 Returns True if the given string *s* contains any mathtext.
 """
- if rcParams['text.usetex']: return 'TeX'
-
 # Did we find an even number of non-escaped dollar signs?
 # If so, treat is as math text.
 dollar_count = s.count(r'$') - s.count(r'\$')
- if dollar_count > 0 and dollar_count % 2 == 0:
- return True
+ even_dollars = (dollar_count > 0 and dollar_count % 2 == 0)
 
- return False
+ if rcParams['text.usetex']:
+ return s, 'TeX'
 
+ if even_dollars:
+ return s, True
+ else:
+ return s.replace(r'\$', '$'), False
+
 def set_fontproperties(self, fp):
 """
 Set the font properties that control the text. *fp* must be a
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jd...@us...> - 2008年12月15日 20:45:24
Revision: 6622
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6622&view=rev
Author: jdh2358
Date: 2008年12月15日 20:45:20 +0000 (2008年12月15日)
Log Message:
-----------
hack to prevent distutils from creating links in our sdist
Modified Paths:
--------------
 branches/v0_98_5_maint/MANIFEST.in
 branches/v0_98_5_maint/lib/matplotlib/__init__.py
Modified: branches/v0_98_5_maint/MANIFEST.in
===================================================================
--- branches/v0_98_5_maint/MANIFEST.in	2008年12月15日 20:19:01 UTC (rev 6621)
+++ branches/v0_98_5_maint/MANIFEST.in	2008年12月15日 20:45:20 UTC (rev 6622)
@@ -1,7 +1,7 @@
 include CHANGELOG KNOWN_BUGS INSTALL
 include INTERACTIVE TODO
 include Makefile MANIFEST.in MANIFEST
-include matplotlibrc.template matplotlibrc setup.cfg.template
+include matplotlibrc.template setup.cfg.template
 include __init__.py setupext.py setup.py setupegg.py
 include examples/data/*
 include lib/mpl_toolkits
Modified: branches/v0_98_5_maint/lib/matplotlib/__init__.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/__init__.py	2008年12月15日 20:19:01 UTC (rev 6621)
+++ branches/v0_98_5_maint/lib/matplotlib/__init__.py	2008年12月15日 20:45:20 UTC (rev 6622)
@@ -89,7 +89,7 @@
 """
 from __future__ import generators
 
-__version__ = '0.98.5'
+__version__ = '0.98.5.1'
 __revision__ = '$Revision$'
 __date__ = '$Date$'
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jd...@us...> - 2008年12月16日 14:44:25
Revision: 6627
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6627&view=rev
Author: jdh2358
Date: 2008年12月16日 14:44:09 +0000 (2008年12月16日)
Log Message:
-----------
removed mpl_data link
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/doc/README.txt
 branches/v0_98_5_maint/doc/devel/documenting_mpl.rst
 branches/v0_98_5_maint/doc/make.py
 branches/v0_98_5_maint/doc/users/customizing.rst
 branches/v0_98_5_maint/doc/users/navigation_toolbar.rst
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月15日 21:04:03 UTC (rev 6626)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月16日 14:44:09 UTC (rev 6627)
@@ -1,3 +1,10 @@
+2008年12月15日 Removed mpl_data symlink in docs. On platforms that do not
+ support symlinks, these become copies, and the font files
+ are large, so the distro becomes unneccessarily bloaded.
+ Keeping the mpl_examples dir because relative links are
+ harder for the plot directive and the *.py files are not so
+ large. - JDH
+
 2008年12月15日 Fix \$ in non-math text with usetex off. Document
 differences between usetex on/off - MGD
 
Modified: branches/v0_98_5_maint/doc/README.txt
===================================================================
--- branches/v0_98_5_maint/doc/README.txt	2008年12月15日 21:04:03 UTC (rev 6626)
+++ branches/v0_98_5_maint/doc/README.txt	2008年12月16日 14:44:09 UTC (rev 6627)
@@ -27,9 +27,6 @@
 
 * sphinxext - Sphinx extensions for the mpl docs
 
-* mpl_data - a symbolic link to the matplotlib data for reference by
- sphinx documentation
-
 * mpl_examples - a link to the matplotlib examples in case any
 documentation wants to literal include them
 
Modified: branches/v0_98_5_maint/doc/devel/documenting_mpl.rst
===================================================================
--- branches/v0_98_5_maint/doc/devel/documenting_mpl.rst	2008年12月15日 21:04:03 UTC (rev 6626)
+++ branches/v0_98_5_maint/doc/devel/documenting_mpl.rst	2008年12月16日 14:44:09 UTC (rev 6627)
@@ -271,26 +271,41 @@
 ==========================
 
 In the documentation, you may want to include to a document in the
-matplotlib src, e.g. a license file, an image file from `mpl-data`, or an
-example. When you include these files, include them using a symbolic
-link from the documentation parent directory. This way, if we
-relocate the mpl documentation directory, all of the internal pointers
-to files will not have to change, just the top level symlinks. For
-example, In the top level doc directory we have symlinks pointing to
-the mpl `examples` and `mpl-data`::
+matplotlib src, e.g. a license file or an image file from `mpl-data`,
+refer to it via a relative path from the document where the rst file
+resides, eg, in :file:`users/navigation_toolbar.rst`, we refer to the
+image icons with::
 
- home:~/mpl/doc2> ls -l mpl_*
- mpl_data -> ../lib/matplotlib/mpl-data
- mpl_examples -> ../examples
+ .. image:: ../../lib/matplotlib/mpl-data/images/subplots.png
 
-
 In the `users` subdirectory, if I want to refer to a file in the mpl-data
 directory, I use the symlink directory. For example, from
 `customizing.rst`::
 
- .. literalinclude:: ../mpl_data/matplotlibrc
+ .. literalinclude:: ../../lib/matplotlib/mpl-data/matplotlibrc
 
+On exception to this is when referring to the examples dir. Relative
+paths are extremely confusing in the sphinx plot extensions, so
+without getting into the dirty details, it is easier to simply include
+a symlink to the files at the top doc level directory. This way, API
+documents like :meth:`matplotlib.pyplot.plot` can refer to the
+examples in a known location.
 
+In the top level doc directory we have symlinks pointing to
+the mpl `examples`::
+
+ home:~/mpl/doc> ls -l mpl_*
+ mpl_examples -> ../examples
+
+So we can include plots from the examples dir using the symlink::
+
+ .. plot:: mpl_examples/pylab_examples/simple_plot.py
+
+
+We used to use a symlink for :file:`mpl-data` too, but the distro
+becomes very large on platforms that do not support links (eg the font
+files are duplicated and large)
+
 .. _internal-section-refs:
 
 Internal section references
Modified: branches/v0_98_5_maint/doc/make.py
===================================================================
--- branches/v0_98_5_maint/doc/make.py	2008年12月15日 21:04:03 UTC (rev 6626)
+++ branches/v0_98_5_maint/doc/make.py	2008年12月16日 14:44:09 UTC (rev 6627)
@@ -41,7 +41,7 @@
 check_build()
 if not os.path.exists('examples/index.rst'):
 examples()
- shutil.copy('mpl_data/matplotlibrc', '_static/matplotlibrc')
+ shutil.copy('../lib/matplotlib/mpl-data/matplotlibrc', '_static/matplotlibrc')
 #figs()
 if os.system('sphinx-build -b html -d build/doctrees . build/html'):
 raise SystemExit("Building HTML failed.")
Modified: branches/v0_98_5_maint/doc/users/customizing.rst
===================================================================
--- branches/v0_98_5_maint/doc/users/customizing.rst	2008年12月15日 21:04:03 UTC (rev 6626)
+++ branches/v0_98_5_maint/doc/users/customizing.rst	2008年12月16日 14:44:09 UTC (rev 6627)
@@ -67,4 +67,4 @@
 
 `(download) <../_static/matplotlibrc>`__
 
-.. literalinclude:: ../mpl_data/matplotlibrc
+.. literalinclude:: ../../lib/matplotlib/mpl-data/matplotlibrc
Modified: branches/v0_98_5_maint/doc/users/navigation_toolbar.rst
===================================================================
--- branches/v0_98_5_maint/doc/users/navigation_toolbar.rst	2008年12月15日 21:04:03 UTC (rev 6626)
+++ branches/v0_98_5_maint/doc/users/navigation_toolbar.rst	2008年12月16日 14:44:09 UTC (rev 6627)
@@ -9,11 +9,11 @@
 to navigate through the data set. Here is a description of each of
 the buttons at the bottom of the toolbar
 
-.. image:: ../mpl_data/images/home.png
+.. image:: ../../lib/matplotlib/mpl-data/images/home.png
 
-.. image:: ../mpl_data/images/back.png
+.. image:: ../../lib/matplotlib/mpl-data/images/back.png
 
-.. image:: ../mpl_data/images/forward.png
+.. image:: ../../lib/matplotlib/mpl-data/images/forward.png
 
 The ``Forward`` and ``Back`` buttons
 These are akin to the web browser forward and back buttons. They
@@ -26,7 +26,7 @@
 ``Back``, think web browser where data views are web pages. Use
 the pan and zoom to rectangle to define new views.
 
-.. image:: ../mpl_data/images/move.png
+.. image:: ../../lib/matplotlib/mpl-data/images/move.png
 
 The ``Pan/Zoom`` button
 This button has two modes: pan and zoom. Click the toolbar button
@@ -50,7 +50,7 @@
 mouse button. The radius scale can be zoomed in and out using the
 right mouse button.
 
-.. image:: ../mpl_data/images/zoom_to_rect.png
+.. image:: ../../lib/matplotlib/mpl-data/images/zoom_to_rect.png
 
 The ``Zoom-to-rectangle`` button
 Click this toolbar button to activate this mode. Put your mouse
@@ -61,14 +61,14 @@
 with the right button, which will place your entire axes in the
 region defined by the zoom out rectangle.
 
-.. image:: ../mpl_data/images/subplots.png
+.. image:: ../../lib/matplotlib/mpl-data/images/subplots.png
 
 The ``Subplot-configuration`` button
 Use this tool to configure the parameters of the subplot: the
 left, right, top, bottom, space between the rows and space between
 the columns.
 
-.. image:: ../mpl_data/images/filesave.png
+.. image:: ../../lib/matplotlib/mpl-data/images/filesave.png
 
 The ``Save`` button
 Click this button to launch a file save dialog. You can save
@@ -84,14 +84,14 @@
 ================================== ==============================================
 Home/Reset **h** or **r** or **home**
 Back **c** or **left arrow** or **backspace**
-Forward **v** or **right arrow** 
-Pan/Zoom **p** 
-Zoom-to-rect **o** 
-Save **s** 
+Forward **v** or **right arrow**
+Pan/Zoom **p**
+Zoom-to-rect **o**
+Save **s**
 Toggle fullscreen **f**
 Constrain pan/zoom to x axis hold **x**
 Constrain pan/zoom to y axis hold **y**
-Preserve aspect ratio hold **CONTROL** 
+Preserve aspect ratio hold **CONTROL**
 Toggle grid **g**
 Toggle y axis scale (log/linear) **l**
 ================================== ==============================================
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jd...@us...> - 2008年12月16日 16:13:12
Revision: 6629
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6629&view=rev
Author: jdh2358
Date: 2008年12月16日 16:13:07 +0000 (2008年12月16日)
Log Message:
-----------
applied Darren's sphinx patch, cleaned up some docstrings
Modified Paths:
--------------
 branches/v0_98_5_maint/doc/api/api_changes.rst
 branches/v0_98_5_maint/doc/api/font_manager_api.rst
 branches/v0_98_5_maint/doc/pyplots/plotmap.py
 branches/v0_98_5_maint/doc/sphinxext/inheritance_diagram.py
 branches/v0_98_5_maint/doc/sphinxext/mathmpl.py
 branches/v0_98_5_maint/doc/sphinxext/only_directives.py
 branches/v0_98_5_maint/doc/users/event_handling.rst
 branches/v0_98_5_maint/lib/matplotlib/collections.py
 branches/v0_98_5_maint/lib/matplotlib/pyplot.py
 branches/v0_98_5_maint/lib/matplotlib/ticker.py
Modified: branches/v0_98_5_maint/doc/api/api_changes.rst
===================================================================
--- branches/v0_98_5_maint/doc/api/api_changes.rst	2008年12月16日 16:12:33 UTC (rev 6628)
+++ branches/v0_98_5_maint/doc/api/api_changes.rst	2008年12月16日 16:13:07 UTC (rev 6629)
@@ -253,7 +253,7 @@
 `Axes.toggle_log_lineary()` has been removed.
 
 :mod:`matplotlib.artist`
-~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 ============================================================ ============================================================
 Old method New method
Modified: branches/v0_98_5_maint/doc/api/font_manager_api.rst
===================================================================
--- branches/v0_98_5_maint/doc/api/font_manager_api.rst	2008年12月16日 16:12:33 UTC (rev 6628)
+++ branches/v0_98_5_maint/doc/api/font_manager_api.rst	2008年12月16日 16:13:07 UTC (rev 6629)
@@ -11,7 +11,7 @@
 :show-inheritance:
 
 :mod:`matplotlib.fontconfig_pattern`
-==============================
+========================================
 
 .. automodule:: matplotlib.fontconfig_pattern
 :members:
Modified: branches/v0_98_5_maint/doc/pyplots/plotmap.py
===================================================================
--- branches/v0_98_5_maint/doc/pyplots/plotmap.py	2008年12月16日 16:12:33 UTC (rev 6628)
+++ branches/v0_98_5_maint/doc/pyplots/plotmap.py	2008年12月16日 16:13:07 UTC (rev 6629)
@@ -11,7 +11,7 @@
 # read in topo data (on a regular lat/lon grid)
 # longitudes go from 20 to 380.
 # you can get this data from matplolib svn matplotlib/htdocs/screenshots/data/
-datadir = '/home/jdhunter/python/svn/matplotlib/htdocs/screenshots/data/'
+datadir = '/home/jdhunter/python/svn/matplotlib/trunk/htdocs/screenshots/data/'
 if not os.path.exists(datadir):
 raise SystemExit('You need to download the data with svn co https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/trunk/htdocs/screenshots/data/" and set the datadir variable in %s'%__file__)
 
Modified: branches/v0_98_5_maint/doc/sphinxext/inheritance_diagram.py
===================================================================
--- branches/v0_98_5_maint/doc/sphinxext/inheritance_diagram.py	2008年12月16日 16:12:33 UTC (rev 6628)
+++ branches/v0_98_5_maint/doc/sphinxext/inheritance_diagram.py	2008年12月16日 16:13:07 UTC (rev 6629)
@@ -39,8 +39,6 @@
 from md5 import md5
 
 from docutils.nodes import Body, Element
-from docutils.writers.html4css1 import HTMLTranslator
-from sphinx.latexwriter import LaTeXTranslator
 from docutils.parsers.rst import directives
 from sphinx.roles import xfileref_role
 
@@ -409,12 +407,9 @@
 inheritance_diagram_directive)
 
 def setup(app):
- app.add_node(inheritance_diagram)
-
- HTMLTranslator.visit_inheritance_diagram = \
- visit_inheritance_diagram(html_output_graph)
- HTMLTranslator.depart_inheritance_diagram = do_nothing
-
- LaTeXTranslator.visit_inheritance_diagram = \
- visit_inheritance_diagram(latex_output_graph)
- LaTeXTranslator.depart_inheritance_diagram = do_nothing
+ app.add_node(inheritance_diagram,
+ html=(visit_inheritance_diagram(html_output_graph),
+ do_nothing))
+ app.add_node(inheritance_diagram,
+ latex=(visit_inheritance_diagram(latex_output_graph),
+ do_nothing))
Modified: branches/v0_98_5_maint/doc/sphinxext/mathmpl.py
===================================================================
--- branches/v0_98_5_maint/doc/sphinxext/mathmpl.py	2008年12月16日 16:12:33 UTC (rev 6628)
+++ branches/v0_98_5_maint/doc/sphinxext/mathmpl.py	2008年12月16日 16:13:07 UTC (rev 6629)
@@ -6,8 +6,6 @@
 
 from docutils import nodes
 from docutils.parsers.rst import directives
-from docutils.writers.html4css1 import HTMLTranslator
-from sphinx.latexwriter import LaTeXTranslator
 import warnings
 
 # Define LaTeX math node:
@@ -69,8 +67,6 @@
 self.body.append(latex2html(node, source))
 def depart_latex_math_html(self, node):
 pass
- HTMLTranslator.visit_latex_math = visit_latex_math_html
- HTMLTranslator.depart_latex_math = depart_latex_math_html
 
 # Add visit/depart methods to LaTeX-Translator:
 def visit_latex_math_latex(self, node):
@@ -83,9 +79,14 @@
 '\\end{equation}'])
 def depart_latex_math_latex(self, node):
 pass
- LaTeXTranslator.visit_latex_math = visit_latex_math_latex
- LaTeXTranslator.depart_latex_math = depart_latex_math_latex
 
+ app.add_node(latex_math, html=(visit_latex_math_html,
+ depart_latex_math_html))
+ app.add_node(latex_math, latex=(visit_latex_math_latex,
+ depart_latex_math_latex))
+ app.add_role('math', math_role)
+
+
 from matplotlib import rcParams
 from matplotlib.mathtext import MathTextParser
 rcParams['mathtext.fontset'] = 'cm'
Modified: branches/v0_98_5_maint/doc/sphinxext/only_directives.py
===================================================================
--- branches/v0_98_5_maint/doc/sphinxext/only_directives.py	2008年12月16日 16:12:33 UTC (rev 6628)
+++ branches/v0_98_5_maint/doc/sphinxext/only_directives.py	2008年12月16日 16:13:07 UTC (rev 6629)
@@ -4,8 +4,6 @@
 #
 
 from docutils.nodes import Body, Element
-from docutils.writers.html4css1 import HTMLTranslator
-from sphinx.latexwriter import LaTeXTranslator
 from docutils.parsers.rst import directives
 
 class html_only(Body, Element):
@@ -63,9 +61,6 @@
 directives.register_directive('latexonly', LatexOnlyDirective)
 
 def setup(app):
- app.add_node(html_only)
- app.add_node(latex_only)
-
 # Add visit/depart methods to HTML-Translator:
 def visit_perform(self, node):
 pass
@@ -76,12 +71,7 @@
 def depart_ignore(self, node):
 node.children = []
 
- HTMLTranslator.visit_html_only = visit_perform
- HTMLTranslator.depart_html_only = depart_perform
- HTMLTranslator.visit_latex_only = visit_ignore
- HTMLTranslator.depart_latex_only = depart_ignore
-
- LaTeXTranslator.visit_html_only = visit_ignore
- LaTeXTranslator.depart_html_only = depart_ignore
- LaTeXTranslator.visit_latex_only = visit_perform
- LaTeXTranslator.depart_latex_only = depart_perform
+ app.add_node(html_only, html=(visit_perform, depart_perform))
+ app.add_node(html_only, latex=(visit_ignore, depart_ignore))
+ app.add_node(latex_only, latex=(visit_perform, depart_perform))
+ app.add_node(latex_only, html=(visit_ignore, depart_ignore))
Modified: branches/v0_98_5_maint/doc/users/event_handling.rst
===================================================================
--- branches/v0_98_5_maint/doc/users/event_handling.rst	2008年12月16日 16:12:33 UTC (rev 6628)
+++ branches/v0_98_5_maint/doc/users/event_handling.rst	2008年12月16日 16:13:07 UTC (rev 6629)
@@ -64,8 +64,8 @@
 'scroll_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse scroll wheel is rolled
 'figure_enter_event' :class:`~matplotlib.backend_bases.LocationEvent` - mouse enters a new figure
 'figure_leave_event' :class:`~matplotlib.backend_bases.LocationEvent` - mouse leaves a figure
-'axes_enter_event' :class:`~matplotlib.backend_bases.LocationEvent` - mouse enters a new axes
-'axes_leave_event' :class:`~matplotlib.backend_bases.LocationEvent` - mouse leaves an axes
+'axes_enter_event' :class:`~matplotlib.backend_bases.LocationEvent` - mouse enters a new axes
+'axes_leave_event' :class:`~matplotlib.backend_bases.LocationEvent` - mouse leaves an axes
 ======================= ======================================================================================
 
 .. _event-attributes:
Modified: branches/v0_98_5_maint/lib/matplotlib/collections.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/collections.py	2008年12月16日 16:12:33 UTC (rev 6628)
+++ branches/v0_98_5_maint/lib/matplotlib/collections.py	2008年12月16日 16:13:07 UTC (rev 6629)
@@ -703,7 +703,7 @@
 on the y-axis from *ymin* to *ymax*
 
 A :class:`BrokenBarHCollection` is returned.
- **kwargs are passed on to the collection
+ *kwargs* are passed on to the collection
 """
 xranges = []
 for ind0, ind1 in mlab.contiguous_regions(where):
Modified: branches/v0_98_5_maint/lib/matplotlib/pyplot.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/pyplot.py	2008年12月16日 16:12:33 UTC (rev 6628)
+++ branches/v0_98_5_maint/lib/matplotlib/pyplot.py	2008年12月16日 16:13:07 UTC (rev 6629)
@@ -603,7 +603,7 @@
 
 *axisbg*:
 The background color of the subplot, which can be any valid
- color specifier. See :module:`matplotlib.colors` for more
+ color specifier. See :mod:`matplotlib.colors` for more
 information.
 
 *polar*:
@@ -1138,63 +1138,62 @@
 def plotting():
 """
 Plotting commands
-
- ========= =================================================
- Command Description
- ========= =================================================
- axes Create a new axes
- axis Set or return the current axis limits
- bar make a bar chart
- boxplot make a box and whiskers chart
- cla clear current axes
- clabel label a contour plot
- clf clear a figure window
- close close a figure window
- colorbar add a colorbar to the current figure
- cohere make a plot of coherence
- contour make a contour plot
- contourf make a filled contour plot
- csd make a plot of cross spectral density
- draw force a redraw of the current figure
- errorbar make an errorbar graph
- figlegend add a legend to the figure
- figimage add an image to the figure, w/o resampling
- figtext add text in figure coords
- figure create or change active figure
- fill make filled polygons
+ ============ =================================================
+ Command Description
+ ========= =================================================
+ axes Create a new axes
+ axis Set or return the current axis limits
+ bar make a bar chart
+ boxplot make a box and whiskers chart
+ cla clear current axes
+ clabel label a contour plot
+ clf clear a figure window
+ close close a figure window
+ colorbar add a colorbar to the current figure
+ cohere make a plot of coherence
+ contour make a contour plot
+ contourf make a filled contour plot
+ csd make a plot of cross spectral density
+ draw force a redraw of the current figure
+ errorbar make an errorbar graph
+ figlegend add a legend to the figure
+ figimage add an image to the figure, w/o resampling
+ figtext add text in figure coords
+ figure create or change active figure
+ fill make filled polygons
 fill_between make filled polygons
- gca return the current axes
- gcf return the current figure
- gci get the current image, or None
- getp get a handle graphics property
- hist make a histogram
- hold set the hold state on current axes
- legend add a legend to the axes
- loglog a log log plot
- imread load image file into array
- imshow plot image data
- matshow display a matrix in a new figure preserving aspect
- pcolor make a pseudocolor plot
- plot make a line plot
- plotfile plot data from a flat file
- psd make a plot of power spectral density
- quiver make a direction field (arrows) plot
- rc control the default params
- savefig save the current figure
- scatter make a scatter plot
- setp set a handle graphics property
- semilogx log x axis
- semilogy log y axis
- show show the figures
- specgram a spectrogram plot
- stem make a stem plot
- subplot make a subplot (numrows, numcols, axesnum)
- table add a table to the axes
- text add some text at location x,y to the current axes
- title add a title to the current axes
- xlabel add an xlabel to the current axes
- ylabel add a ylabel to the current axes
- ========= =================================================
+ gca return the current axes
+ gcf return the current figure
+ gci get the current image, or None
+ getp get a handle graphics property
+ hist make a histogram
+ hold set the hold state on current axes
+ legend add a legend to the axes
+ loglog a log log plot
+ imread load image file into array
+ imshow plot image data
+ matshow display a matrix in a new figure preserving aspect
+ pcolor make a pseudocolor plot
+ plot make a line plot
+ plotfile plot data from a flat file
+ psd make a plot of power spectral density
+ quiver make a direction field (arrows) plot
+ rc control the default params
+ savefig save the current figure
+ scatter make a scatter plot
+ setp set a handle graphics property
+ semilogx log x axis
+ semilogy log y axis
+ show show the figures
+ specgram a spectrogram plot
+ stem make a stem plot
+ subplot make a subplot (numrows, numcols, axesnum)
+ table add a table to the axes
+ text add some text at location x,y to the current axes
+ title add a title to the current axes
+ xlabel add an xlabel to the current axes
+ ylabel add a ylabel to the current axes
+ ============ =================================================
 
 The following commands will set the default colormap accordingly:
 
Modified: branches/v0_98_5_maint/lib/matplotlib/ticker.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/ticker.py	2008年12月16日 16:12:33 UTC (rev 6628)
+++ branches/v0_98_5_maint/lib/matplotlib/ticker.py	2008年12月16日 16:13:07 UTC (rev 6629)
@@ -213,7 +213,7 @@
 'Return fixed strings for tick labels'
 def __init__(self, seq):
 """
- seq is a sequence of strings. For positions ``i<len(seq)` return
+ seq is a sequence of strings. For positions `i<len(seq)` return
 *seq[i]* regardless of *x*. Otherwise return ''
 """
 self.seq = seq
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <lee...@us...> - 2008年12月16日 19:02:43
Revision: 6635
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6635&view=rev
Author: leejjoon
Date: 2008年12月16日 19:02:39 +0000 (2008年12月16日)
Log Message:
-----------
fixed dpi-dependent behavior of legend and text fancybox.
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/lib/matplotlib/legend.py
 branches/v0_98_5_maint/lib/matplotlib/text.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月16日 19:01:45 UTC (rev 6634)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月16日 19:02:39 UTC (rev 6635)
@@ -1,3 +1,6 @@
+2008年12月16日 Fixed dpi-dependent behavior of Legend and fancybox in Text.
+ -JJL
+
 2008年12月15日 Removed mpl_data symlink in docs. On platforms that do not
 support symlinks, these become copies, and the font files
 are large, so the distro becomes unneccessarily bloaded.
Modified: branches/v0_98_5_maint/lib/matplotlib/legend.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/legend.py	2008年12月16日 19:01:45 UTC (rev 6634)
+++ branches/v0_98_5_maint/lib/matplotlib/legend.py	2008年12月16日 19:02:39 UTC (rev 6635)
@@ -207,6 +207,11 @@
 reps = int(self.numpoints / len(self._scatteryoffsets)) + 1
 self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.scatterpoints]
 
+ # handles & labels (which can be iterators) need to be
+ # explicitly converted to list.
+ self._handles_labels = list(handles), list(labels)
+
+
 # _legend_box is an OffsetBox instance that contains all
 # legend items and will be initialized from _init_legend_box()
 # method.
@@ -273,9 +278,9 @@
 
 self._drawFrame = True
 
- # populate the legend_box with legend items.
- self._init_legend_box(handles, labels)
- self._legend_box.set_figure(self.figure)
+ # init with null renderer
+ #self._init_legend_box(handles, labels, None)
+ #self._legend_box.set_figure(self.figure)
 
 
 def _set_artist_props(self, a):
@@ -294,7 +299,7 @@
 ox, oy = self._find_best_position(width, height)
 return ox+xdescent, oy+ydescent
 
- def _findoffset_loc(self, width, height, xdescent, ydescent):
+ def _findoffset_loc(self, width, height, xdescent, ydescent, renderer):
 "Heper function to locate the legend using the location code"
 
 if iterable(self._loc) and len(self._loc)==2:
@@ -304,7 +309,7 @@
 x, y = bbox.x0 + bbox.width * fx, bbox.y0 + bbox.height * fy
 else:
 bbox = Bbox.from_bounds(0, 0, width, height)
- x, y = self._get_anchored_bbox(self._loc, bbox, self.parent.bbox)
+ x, y = self._get_anchored_bbox(self._loc, bbox, self.parent.bbox, renderer)
 
 return x+xdescent, y+ydescent
 
@@ -312,6 +317,11 @@
 "Draw everything that belongs to the legend"
 if not self.get_visible(): return
 
+ # populate the legend_box with legend items.
+ handles, labels = self._handles_labels
+ self._init_legend_box(handles, labels, renderer)
+ self._legend_box.set_figure(self.figure)
+
 renderer.open_group('legend')
 
 # find_offset function will be provided to _legend_box and
@@ -320,12 +330,16 @@
 if self._loc == 0:
 self._legend_box.set_offset(self._findoffset_best)
 else:
- self._legend_box.set_offset(self._findoffset_loc)
+ def _findoffset_loc(width, height, xdescent, ydescent):
+ return self._findoffset_loc(width, height, xdescent, ydescent, renderer)
+ self._legend_box.set_offset(_findoffset_loc)
 
+ fontsize = renderer.points_to_pixels(self.fontsize)
+
 # if mode == fill, set the width of the legend_box to the
 # width of the paret (minus pads)
 if self._mode in ["expand"]:
- pad = 2*(self.borderaxespad+self.borderpad)*self.fontsize
+ pad = 2*(self.borderaxespad+self.borderpad)*fontsize
 self._legend_box.set_width(self.parent.bbox.width-pad)
 
 if self._drawFrame:
@@ -334,6 +348,8 @@
 self.legendPatch.set_bounds(bbox.x0, bbox.y0,
 bbox.width, bbox.height)
 
+ self.legendPatch.set_mutation_scale(fontsize)
+
 if self.shadow:
 shadow = Shadow(self.legendPatch, 2, -2)
 shadow.draw(renderer)
@@ -353,7 +369,7 @@
 return self.fontsize/72.0*self.figure.dpi
 
 
- def _init_legend_box(self, handles, labels):
+ def _init_legend_box(self, handles, labels, renderer=None):
 """
 Initiallize the legend_box. The legend_box is an instance of
 the OffsetBox, which is packed with legend handles and
@@ -361,6 +377,11 @@
 drawing time.
 """
 
+ if renderer is None:
+ fontsize = self.fontsize
+ else:
+ fontsize = renderer.points_to_pixels(self.fontsize)
+
 # legend_box is a HPacker, horizontally packed with
 # columns. Each column is a VPacker, vertically packed with
 # legend items. Each legend item is HPacker packed with
@@ -411,13 +432,13 @@
 if npoints > 1:
 # we put some pad here to compensate the size of the
 # marker
- xdata = np.linspace(0.3*self.fontsize,
- (self.handlelength-0.3)*self.fontsize,
+ xdata = np.linspace(0.3*fontsize,
+ (self.handlelength-0.3)*fontsize,
 npoints)
 xdata_marker = xdata
 elif npoints == 1:
- xdata = np.linspace(0, self.handlelength*self.fontsize, 2)
- xdata_marker = [0.5*self.handlelength*self.fontsize]
+ xdata = np.linspace(0, self.handlelength*fontsize, 2)
+ xdata_marker = [0.5*self.handlelength*fontsize]
 
 if isinstance(handle, Line2D):
 ydata = ((height-descent)/2.)*np.ones(xdata.shape, float)
@@ -445,7 +466,7 @@
 
 elif isinstance(handle, Patch):
 p = Rectangle(xy=(0., 0.),
- width = self.handlelength*self.fontsize,
+ width = self.handlelength*fontsize,
 height=(height-descent),
 )
 p.update_from(handle)
@@ -499,7 +520,7 @@
 else:
 handle_list.append(None)
 
- handlebox = DrawingArea(width=self.handlelength*self.fontsize,
+ handlebox = DrawingArea(width=self.handlelength*fontsize,
 height=height,
 xdescent=0., ydescent=descent)
 
@@ -527,7 +548,7 @@
 for i0, di in largecol+smallcol:
 # pack handleBox and labelBox into itemBox
 itemBoxes = [HPacker(pad=0,
- sep=self.handletextpad*self.fontsize,
+ sep=self.handletextpad*fontsize,
 children=[h, t], align="baseline")
 for h, t in handle_label[i0:i0+di]]
 # minimumdescent=False for the text of the last row of the column
@@ -535,7 +556,7 @@
 
 # pack columnBox
 columnbox.append(VPacker(pad=0,
- sep=self.labelspacing*self.fontsize,
+ sep=self.labelspacing*fontsize,
 align="baseline",
 children=itemBoxes))
 
@@ -544,9 +565,9 @@
 else:
 mode = "fixed"
 
- sep = self.columnspacing*self.fontsize
+ sep = self.columnspacing*fontsize
 
- self._legend_box = HPacker(pad=self.borderpad*self.fontsize,
+ self._legend_box = HPacker(pad=self.borderpad*fontsize,
 sep=sep, align="baseline",
 mode=mode,
 children=columnbox)
@@ -627,7 +648,7 @@
 return self.legendPatch.get_window_extent()
 
 
- def _get_anchored_bbox(self, loc, bbox, parentbbox):
+ def _get_anchored_bbox(self, loc, bbox, parentbbox, renderer):
 """
 Place the *bbox* inside the *parentbbox* according to a given
 location code. Return the (x,y) coordinate of the bbox.
@@ -655,8 +676,9 @@
 C:"C"}
 
 c = anchor_coefs[loc]
-
- container = parentbbox.padded(-(self.borderaxespad) * self.fontsize)
+ 
+ fontsize = renderer.points_to_pixels(self.fontsize)
+ container = parentbbox.padded(-(self.borderaxespad) * fontsize)
 anchored_box = bbox.anchored(c, container=container)
 return anchored_box.x0, anchored_box.y0
 
Modified: branches/v0_98_5_maint/lib/matplotlib/text.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/text.py	2008年12月16日 19:01:45 UTC (rev 6634)
+++ branches/v0_98_5_maint/lib/matplotlib/text.py	2008年12月16日 19:02:39 UTC (rev 6635)
@@ -395,7 +395,8 @@
 tr = mtransforms.Affine2D().rotate(theta)
 tr = tr.translate(posx+x_box, posy+y_box)
 self._bbox_patch.set_transform(tr)
- self._bbox_patch.set_mutation_scale(self.get_size())
+ fontsize = renderer.points_to_pixels(self.get_size())
+ self._bbox_patch.set_mutation_scale(fontsize)
 #self._bbox_patch.draw(renderer)
 
 else:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <lee...@us...> - 2008年12月17日 00:51:00
Revision: 6640
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6640&view=rev
Author: leejjoon
Date: 2008年12月17日 00:50:56 +0000 (2008年12月17日)
Log Message:
-----------
Another attempt to fix dpi-dependent behavior of Legend
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/lib/matplotlib/legend.py
 branches/v0_98_5_maint/lib/matplotlib/offsetbox.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月16日 22:26:11 UTC (rev 6639)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月17日 00:50:56 UTC (rev 6640)
@@ -1,3 +1,5 @@
+2008年12月16日 Another attempt to fix dpi-dependent behavior of Legend. -JJL
+
 ======================================================================
 2008年12月16日 Release 0.98.5.1 at r6636
 
Modified: branches/v0_98_5_maint/lib/matplotlib/legend.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/legend.py	2008年12月16日 22:26:11 UTC (rev 6639)
+++ branches/v0_98_5_maint/lib/matplotlib/legend.py	2008年12月17日 00:50:56 UTC (rev 6640)
@@ -34,7 +34,7 @@
 from matplotlib.collections import LineCollection, RegularPolyCollection
 from matplotlib.transforms import Bbox
 
-from matplotlib.offsetbox import HPacker, VPacker, TextArea, DrawingArea
+from matplotlib.offsetbox import HPacker, VPacker, PackerBase, TextArea, DrawingArea
 
 
 class Legend(Artist):
@@ -207,11 +207,6 @@
 reps = int(self.numpoints / len(self._scatteryoffsets)) + 1
 self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.scatterpoints]
 
- # handles & labels (which can be iterators) need to be
- # explicitly converted to list.
- self._handles_labels = list(handles), list(labels)
-
-
 # _legend_box is an OffsetBox instance that contains all
 # legend items and will be initialized from _init_legend_box()
 # method.
@@ -277,12 +272,13 @@
 self._set_artist_props(self.legendPatch)
 
 self._drawFrame = True
-
+ 
 # init with null renderer
- #self._init_legend_box(handles, labels, None)
- #self._legend_box.set_figure(self.figure)
+ self._init_legend_box(handles, labels)
 
+ self._last_fontsize_points = self.fontsize
 
+
 def _set_artist_props(self, a):
 """
 set the boilerplate props for artists added to axes
@@ -294,9 +290,9 @@
 
 a.set_transform(self.get_transform())
 
- def _findoffset_best(self, width, height, xdescent, ydescent):
+ def _findoffset_best(self, width, height, xdescent, ydescent, renderer):
 "Heper function to locate the legend at its best position"
- ox, oy = self._find_best_position(width, height)
+ ox, oy = self._find_best_position(width, height, renderer)
 return ox+xdescent, oy+ydescent
 
 def _findoffset_loc(self, width, height, xdescent, ydescent, renderer):
@@ -317,10 +313,7 @@
 "Draw everything that belongs to the legend"
 if not self.get_visible(): return
 
- # populate the legend_box with legend items.
- handles, labels = self._handles_labels
- self._init_legend_box(handles, labels, renderer)
- self._legend_box.set_figure(self.figure)
+ self._update_legend_box(renderer)
 
 renderer.open_group('legend')
 
@@ -328,12 +321,15 @@
 # _legend_box will draw itself at the location of the return
 # value of the find_offset.
 if self._loc == 0:
- self._legend_box.set_offset(self._findoffset_best)
+ _findoffset = self._findoffset_best
 else:
- def _findoffset_loc(width, height, xdescent, ydescent):
- return self._findoffset_loc(width, height, xdescent, ydescent, renderer)
- self._legend_box.set_offset(_findoffset_loc)
+ _findoffset = self._findoffset_loc
 
+ def findoffset(width, height, xdescent, ydescent):
+ return _findoffset(width, height, xdescent, ydescent, renderer)
+ 
+ self._legend_box.set_offset(findoffset)
+ 
 fontsize = renderer.points_to_pixels(self.fontsize)
 
 # if mode == fill, set the width of the legend_box to the
@@ -361,15 +357,18 @@
 renderer.close_group('legend')
 
 
- def _approx_text_height(self):
+ def _approx_text_height(self, renderer=None):
 """
 Return the approximate height of the text. This is used to place
 the legend handle.
 """
- return self.fontsize/72.0*self.figure.dpi
+ if renderer is None:
+ return self.fontsize
+ else:
+ return renderer.points_to_pixels(self.fontsize)
 
 
- def _init_legend_box(self, handles, labels, renderer=None):
+ def _init_legend_box(self, handles, labels):
 """
 Initiallize the legend_box. The legend_box is an instance of
 the OffsetBox, which is packed with legend handles and
@@ -377,10 +376,7 @@
 drawing time.
 """
 
- if renderer is None:
- fontsize = self.fontsize
- else:
- fontsize = renderer.points_to_pixels(self.fontsize)
+ fontsize = self.fontsize
 
 # legend_box is a HPacker, horizontally packed with
 # columns. Each column is a VPacker, vertically packed with
@@ -415,10 +411,13 @@
 height = self._approx_text_height() * 0.7
 descent = 0.
 
- # each handle needs to be drawn inside a box of
- # (x, y, w, h) = (0, -descent, width, height).
- # And their corrdinates should be given in the display coordinates.
+ # each handle needs to be drawn inside a box of (x, y, w, h) =
+ # (0, -descent, width, height). And their corrdinates should
+ # be given in the display coordinates.
 
+ # NOTE : the coordinates will be updated again in
+ # _update_legend_box() method.
+
 # The transformation of each handle will be automatically set
 # to self.get_trasnform(). If the artist does not uses its
 # default trasnform (eg, Collections), you need to
@@ -548,8 +547,8 @@
 for i0, di in largecol+smallcol:
 # pack handleBox and labelBox into itemBox
 itemBoxes = [HPacker(pad=0,
- sep=self.handletextpad*fontsize,
- children=[h, t], align="baseline")
+ sep=self.handletextpad*fontsize,
+ children=[h, t], align="baseline")
 for h, t in handle_label[i0:i0+di]]
 # minimumdescent=False for the text of the last row of the column
 itemBoxes[-1].get_children()[1].set_minimumdescent(False)
@@ -572,10 +571,100 @@
 mode=mode,
 children=columnbox)
 
+ self._legend_box.set_figure(self.figure)
+
 self.texts = text_list
 self.legendHandles = handle_list
 
 
+
+
+ def _update_legend_box(self, renderer):
+ """
+ Update the dimension of the legend_box. This is required
+ becuase the paddings, the hadle size etc. depends on the dpi
+ of the renderer.
+ """
+
+ # fontsize in points.
+ fontsize = renderer.points_to_pixels(self.fontsize)
+
+ if self._last_fontsize_points == fontsize:
+ # no update is needed
+ return
+
+ # each handle needs to be drawn inside a box of
+ # (x, y, w, h) = (0, -descent, width, height).
+ # And their corrdinates should be given in the display coordinates.
+
+ # The approximate height and descent of text. These values are
+ # only used for plotting the legend handle.
+ height = self._approx_text_height(renderer) * 0.7
+ descent = 0.
+
+ for handle in self.legendHandles:
+ if isinstance(handle, RegularPolyCollection):
+ npoints = self.scatterpoints
+ else:
+ npoints = self.numpoints
+ if npoints > 1:
+ # we put some pad here to compensate the size of the
+ # marker
+ xdata = np.linspace(0.3*fontsize,
+ (self.handlelength-0.3)*fontsize,
+ npoints)
+ xdata_marker = xdata
+ elif npoints == 1:
+ xdata = np.linspace(0, self.handlelength*fontsize, 2)
+ xdata_marker = [0.5*self.handlelength*fontsize]
+
+ if isinstance(handle, Line2D):
+ legline = handle
+ ydata = ((height-descent)/2.)*np.ones(xdata.shape, float)
+ legline.set_data(xdata, ydata)
+
+ legline_marker = legline._legmarker
+ legline_marker.set_data(xdata_marker, ydata[:len(xdata_marker)])
+
+ elif isinstance(handle, Patch):
+ p = handle
+ p.set_bounds(0., 0.,
+ self.handlelength*fontsize,
+ (height-descent),
+ )
+
+ elif isinstance(handle, RegularPolyCollection):
+
+ p = handle
+ ydata = height*self._scatteryoffsets
+ p.set_offsets(zip(xdata_marker,ydata))
+
+
+ # correction factor
+ cor = fontsize / self._last_fontsize_points
+
+ # helper function to iterate over all children
+ def all_children(parent):
+ yield parent
+ for c in parent.get_children():
+ for cc in all_children(c): yield cc
+
+
+ #now update paddings
+ for box in all_children(self._legend_box):
+ if isinstance(box, PackerBase):
+ box.pad = box.pad * cor
+ box.sep = box.sep * cor
+
+ elif isinstance(box, DrawingArea):
+ box.width = self.handlelength*fontsize
+ box.height = height
+ box.xdescent = 0.
+ box.ydescent=descent
+
+ self._last_fontsize_points = fontsize
+
+
 def _auto_legend_data(self):
 """
 Returns list of vertices and extents covered by the plot.
@@ -683,7 +772,7 @@
 return anchored_box.x0, anchored_box.y0
 
 
- def _find_best_position(self, width, height, consider=None):
+ def _find_best_position(self, width, height, renderer, consider=None):
 """
 Determine the best location to place the legend.
 
@@ -696,7 +785,7 @@
 verts, bboxes, lines = self._auto_legend_data()
 
 bbox = Bbox.from_bounds(0, 0, width, height)
- consider = [self._get_anchored_bbox(x, bbox, self.parent.bbox) for x in range(1, len(self.codes))]
+ consider = [self._get_anchored_bbox(x, bbox, self.parent.bbox, renderer) for x in range(1, len(self.codes))]
 
 #tx, ty = self.legendPatch.get_x(), self.legendPatch.get_y()
 
Modified: branches/v0_98_5_maint/lib/matplotlib/offsetbox.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/offsetbox.py	2008年12月16日 22:26:11 UTC (rev 6639)
+++ branches/v0_98_5_maint/lib/matplotlib/offsetbox.py	2008年12月17日 00:50:56 UTC (rev 6640)
@@ -164,7 +164,7 @@
 
 accepts float
 """
- self._width = width
+ self.width = width
 
 def set_height(self, height):
 """
@@ -172,7 +172,7 @@
 
 accepts float
 """
- self._height = height
+ self.height = height
 
 def get_children(self):
 """
@@ -215,7 +215,31 @@
 bbox_artist(self, renderer, fill=False, props=dict(pad=0.))
 
 
-class VPacker(OffsetBox):
+class PackerBase(OffsetBox):
+ def __init__(self, pad=None, sep=None, width=None, height=None,
+ align=None, mode=None,
+ children=None):
+ """
+ *pad* : boundary pad
+ *sep* : spacing between items
+ *width*, *height* : width and height of the container box.
+ calculated if None.
+ *align* : alignment of boxes
+ *mode* : packing mode
+ """
+ super(PackerBase, self).__init__()
+
+ self.height = height
+ self.width = width
+ self.sep = sep
+ self.pad = pad
+ self.mode = mode
+ self.align = align
+
+ self._children = children
+
+
+class VPacker(PackerBase):
 """
 The VPacker has its children packed vertically. It automatically
 adjust the relative postisions of children in the drawing time.
@@ -231,18 +255,12 @@
 *align* : alignment of boxes
 *mode* : packing mode
 """
- super(VPacker, self).__init__()
+ super(VPacker, self).__init__(pad, sep, width, height,
+ align, mode, 
+ children)
 
- self._height = height
- self._width = width
- self._align = align
- self._sep = sep
- self._pad = pad
- self._mode = mode
- 
- self._children = children
- 
 
+
 def get_extent_offsets(self, renderer):
 """
 update offset of childrens and return the extents of the box
@@ -254,12 +272,12 @@
 
 wd_list = [(w, xd) for w, h, xd, yd in whd_list]
 width, xdescent, xoffsets = _get_aligned_offsets(wd_list,
- self._width,
- self._align)
+ self.width,
+ self.align)
 
 pack_list = [(h, yd) for w,h,xd,yd in whd_list]
- height, yoffsets_ = _get_packed_offsets(pack_list, self._height,
- self._sep, self._mode)
+ height, yoffsets_ = _get_packed_offsets(pack_list, self.height,
+ self.sep, self.mode)
 
 yoffsets = yoffsets_ + [yd for w,h,xd,yd in whd_list]
 ydescent = height - yoffsets[0]
@@ -268,18 +286,17 @@
 #w, h, xd, h_yd = whd_list[-1]
 yoffsets = yoffsets - ydescent
 
- return width + 2*self._pad, height + 2*self._pad, \
- xdescent+self._pad, ydescent+self._pad, \
+ return width + 2*self.pad, height + 2*self.pad, \
+ xdescent+self.pad, ydescent+self.pad, \
 zip(xoffsets, yoffsets)
 
 
-
-class HPacker(OffsetBox):
+class HPacker(PackerBase):
 """
 The HPacker has its children packed horizontally. It automatically
 adjust the relative postisions of children in the drawing time.
 """
- def __init__(self, pad=None, width=None, height=None, sep=None,
+ def __init__(self, pad=None, sep=None, width=None, height=None, 
 align="baseline", mode="fixed",
 children=None):
 """
@@ -290,19 +307,10 @@
 *align* : alignment of boxes
 *mode* : packing mode
 """
- super(HPacker, self).__init__()
+ super(HPacker, self).__init__(pad, sep, width, height,
+ align, mode, children)
 
- self._height = height
- self._width = width
- self._align = align
- 
- self._sep = sep
- self._pad = pad
- self._mode = mode
 
- self._children = children
- 
-
 def get_extent_offsets(self, renderer):
 """
 update offset of childrens and return the extents of the box
@@ -310,30 +318,30 @@
 
 whd_list = [c.get_extent(renderer) for c in self.get_children()]
 
- if self._height is None:
+ if self.height is None:
 height_descent = max([h-yd for w,h,xd,yd in whd_list]) 
 ydescent = max([yd for w,h,xd,yd in whd_list])
 height = height_descent + ydescent
 else:
- height = self._height - 2*self._pad # width w/o pad
+ height = self.height - 2*self._pad # width w/o pad
 
 hd_list = [(h, yd) for w, h, xd, yd in whd_list]
 height, ydescent, yoffsets = _get_aligned_offsets(hd_list,
- self._height,
- self._align)
+ self.height,
+ self.align)
 
 
 pack_list = [(w, xd) for w,h,xd,yd in whd_list]
- width, xoffsets_ = _get_packed_offsets(pack_list, self._width,
- self._sep, self._mode)
+ width, xoffsets_ = _get_packed_offsets(pack_list, self.width,
+ self.sep, self.mode)
 
 xoffsets = xoffsets_ + [xd for w,h,xd,yd in whd_list]
 
 xdescent=whd_list[0][2]
 xoffsets = xoffsets - xdescent
 
- return width + 2*self._pad, height + 2*self._pad, \
- xdescent + self._pad, ydescent + self._pad, \
+ return width + 2*self.pad, height + 2*self.pad, \
+ xdescent + self.pad, ydescent + self.pad, \
 zip(xoffsets, yoffsets)
 
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jd...@us...> - 2008年12月17日 12:51:26
Revision: 6644
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6644&view=rev
Author: jdh2358
Date: 2008年12月17日 12:51:22 +0000 (2008年12月17日)
Log Message:
-----------
added Jouni's pdf image dpi patch; apply fix to figimage
Modified Paths:
--------------
 branches/v0_98_5_maint/examples/pylab_examples/figimage_demo.py
 branches/v0_98_5_maint/lib/matplotlib/backends/backend_pdf.py
 branches/v0_98_5_maint/lib/matplotlib/figure.py
 branches/v0_98_5_maint/lib/matplotlib/image.py
Modified: branches/v0_98_5_maint/examples/pylab_examples/figimage_demo.py
===================================================================
--- branches/v0_98_5_maint/examples/pylab_examples/figimage_demo.py	2008年12月17日 11:20:35 UTC (rev 6643)
+++ branches/v0_98_5_maint/examples/pylab_examples/figimage_demo.py	2008年12月17日 12:51:22 UTC (rev 6644)
@@ -15,6 +15,11 @@
 im1 = plt.figimage(Z, xo=50, yo=0, cmap=cm.jet, origin='lower')
 im2 = plt.figimage(Z, xo=100, yo=100, alpha=.8, cmap=cm.jet, origin='lower')
 
+dpi = 200
+plt.savefig('figimage.png', dpi=dpi)
+plt.savefig('figimage.pdf', dpi=dpi)
+plt.savefig('figimage.svg', dpi=dpi)
+plt.savefig('figimage.eps', dpi=dpi)
 plt.show()
 
 
Modified: branches/v0_98_5_maint/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/backends/backend_pdf.py	2008年12月17日 11:20:35 UTC (rev 6643)
+++ branches/v0_98_5_maint/lib/matplotlib/backends/backend_pdf.py	2008年12月17日 12:51:22 UTC (rev 6644)
@@ -1184,13 +1184,14 @@
 truetype_font_cache = maxdict(50)
 afm_font_cache = maxdict(50)
 
- def __init__(self, file, dpi):
+ def __init__(self, file, dpi, image_dpi):
 RendererBase.__init__(self)
 self.file = file
 self.gc = self.new_gc()
 self.file.used_characters = self.used_characters = {}
 self.mathtext_parser = MathTextParser("Pdf")
 self.dpi = dpi
+ self.image_dpi = image_dpi
 self.tex_font_map = None
 
 def finalize(self):
@@ -1230,9 +1231,10 @@
 stat_key, (realpath, set()))
 used_characters[1].update(charset)
 
+ def get_image_magnification(self):
+ return self.image_dpi/72.0
+ 
 def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
- #print >>sys.stderr, "draw_image called"
-
 # MGDTODO: Support clippath here
 gc = self.new_gc()
 if bbox is not None:
@@ -1240,6 +1242,7 @@
 self.check_gc(gc)
 
 h, w = im.get_size_out()
+ h, w = 72.0*h/self.image_dpi, 72.0*w/self.image_dpi
 imob = self.file.imageObject(im)
 self.file.output(Op.gsave, w, 0, 0, h, x, y, Op.concat_matrix,
 imob, Op.use_xobject, Op.grestore)
@@ -1873,13 +1876,13 @@
 return 'pdf'
 
 def print_pdf(self, filename, **kwargs):
- dpi = 72 # there are 72 Postscript points to an inch
- # TODO: use the dpi kwarg for images
- self.figure.set_dpi(dpi)
+ ppi = 72 # Postscript points in an inch
+ image_dpi = kwargs.get('dpi', 72) # dpi to use for images
+ self.figure.set_dpi(ppi)
 width, height = self.figure.get_size_inches()
- file = PdfFile(width, height, dpi, filename)
+ file = PdfFile(width, height, ppi, filename)
 renderer = MixedModeRenderer(
- width, height, dpi, RendererPdf(file, dpi))
+ width, height, ppi, RendererPdf(file, ppi, image_dpi))
 self.figure.draw(renderer)
 renderer.finalize()
 file.close()
Modified: branches/v0_98_5_maint/lib/matplotlib/figure.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/figure.py	2008年12月17日 11:20:35 UTC (rev 6643)
+++ branches/v0_98_5_maint/lib/matplotlib/figure.py	2008年12月17日 12:51:22 UTC (rev 6644)
@@ -755,7 +755,7 @@
 # make a composite image blending alpha
 # list of (_image.Image, ox, oy)
 mag = renderer.get_image_magnification()
- ims = [(im.make_image(mag), im.ox*mag, im.oy*mag)
+ ims = [(im.make_image(mag), im.ox, im.oy)
 for im in self.images]
 
 im = _image.from_images(self.bbox.height * mag,
Modified: branches/v0_98_5_maint/lib/matplotlib/image.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/image.py	2008年12月17日 11:20:35 UTC (rev 6643)
+++ branches/v0_98_5_maint/lib/matplotlib/image.py	2008年12月17日 12:51:22 UTC (rev 6644)
@@ -630,6 +630,7 @@
 self.ox = offsetx
 self.oy = offsety
 self.update(kwargs)
+ self.magnification = 1.0
 
 def contains(self, mouseevent):
 """Test whether the mouse event occured within the image.
@@ -659,22 +660,30 @@
 -0.5+self.oy, numrows-0.5+self.oy)
 
 def make_image(self, magnification=1.0):
- # had to introduce argument magnification to satisfy the unit test
- # figimage_demo.py. I have no idea, how magnification should be used
- # within the function. It should be !=1.0 only for non-default DPI<
- # settings in the PS backend, as introduced by patch #1562394
- # Probably Nicholas Young should look over this code and see, how
- # magnification should be handled correctly.
 if self._A is None:
 raise RuntimeError('You must first set the image array')
 
 x = self.to_rgba(self._A, self._alpha)
-
- im = _image.fromarray(x, 1)
+ self.magnification = magnification
+ # if magnification is not one, we need to resize
+ ismag = magnification!=1
+ #if ismag: raise RuntimeError
+ if ismag:
+ isoutput = 0
+ else:
+ isoutput = 1
+ im = _image.fromarray(x, isoutput)
 fc = self.figure.get_facecolor()
 im.set_bg( *mcolors.colorConverter.to_rgba(fc, 0) )
 im.is_grayscale = (self.cmap.name == "gray" and
 len(self._A.shape) == 2)
+
+ if ismag:
+ numrows, numcols = self.get_size()
+ numrows *= magnification
+ numcols *= magnification
+ im.set_interpolation(_image.NEAREST)
+ im.resize(numcols, numrows)
 if self.origin=='upper':
 im.flipud_out()
 
@@ -683,9 +692,8 @@
 def draw(self, renderer, *args, **kwargs):
 if not self.get_visible(): return
 # todo: we should be able to do some cacheing here
- im = self.make_image()
-
- renderer.draw_image(round(self.ox), round(self.oy), im, self.figure.bbox,
+ im = self.make_image(renderer.get_image_magnification())
+ renderer.draw_image(round(self.ox/self.magnification), round(self.oy/self.magnification), im, self.figure.bbox,
 *self.get_transformed_clip_path_and_affine())
 
 def write_png(self, fname):
@@ -772,7 +780,7 @@
 x.shape = im.size[1], im.size[0], 4
 return x
 
-def thumbnail(infile, thumbfile, scale=0.1, interpolation='bilinear', 
+def thumbnail(infile, thumbfile, scale=0.1, interpolation='bilinear',
 preview=False):
 """
 make a thumbnail of image in *infile* with output filename
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jd...@us...> - 2008年12月17日 14:55:46
Revision: 6647
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6647&view=rev
Author: jdh2358
Date: 2008年12月17日 14:55:42 +0000 (2008年12月17日)
Log Message:
-----------
fix to figimage
Modified Paths:
--------------
 branches/v0_98_5_maint/examples/pylab_examples/figimage_demo.py
 branches/v0_98_5_maint/lib/matplotlib/image.py
Modified: branches/v0_98_5_maint/examples/pylab_examples/figimage_demo.py
===================================================================
--- branches/v0_98_5_maint/examples/pylab_examples/figimage_demo.py	2008年12月17日 12:59:50 UTC (rev 6646)
+++ branches/v0_98_5_maint/examples/pylab_examples/figimage_demo.py	2008年12月17日 14:55:42 UTC (rev 6647)
@@ -7,7 +7,7 @@
 import matplotlib.pyplot as plt
 
 
-fig = plt.figure(frameon=False)
+fig = plt.figure()
 Z = np.arange(10000.0)
 Z.shape = 100,100
 Z[:,50:] = 1.
@@ -15,11 +15,13 @@
 im1 = plt.figimage(Z, xo=50, yo=0, cmap=cm.jet, origin='lower')
 im2 = plt.figimage(Z, xo=100, yo=100, alpha=.8, cmap=cm.jet, origin='lower')
 
-dpi = 200
-plt.savefig('figimage.png', dpi=dpi)
-plt.savefig('figimage.pdf', dpi=dpi)
-plt.savefig('figimage.svg', dpi=dpi)
-plt.savefig('figimage.eps', dpi=dpi)
+
+if 0:
+ dpi = 72
+ plt.savefig('figimage_%d.png'%dpi, dpi=dpi, facecolor='gray')
+ plt.savefig('figimage_%d.pdf'%dpi, dpi=dpi, facecolor='gray')
+ plt.savefig('figimage_%d.svg'%dpi, dpi=dpi, facecolor='gray')
+ plt.savefig('figimage_%d.eps'%dpi, dpi=dpi, facecolor='gray')
 plt.show()
 
 
Modified: branches/v0_98_5_maint/lib/matplotlib/image.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/image.py	2008年12月17日 12:59:50 UTC (rev 6646)
+++ branches/v0_98_5_maint/lib/matplotlib/image.py	2008年12月17日 14:55:42 UTC (rev 6647)
@@ -693,7 +693,7 @@
 if not self.get_visible(): return
 # todo: we should be able to do some cacheing here
 im = self.make_image(renderer.get_image_magnification())
- renderer.draw_image(round(self.ox/self.magnification), round(self.oy/self.magnification), im, self.figure.bbox,
+ renderer.draw_image(round(self.ox), round(self.oy), im, self.figure.bbox,
 *self.get_transformed_clip_path_and_affine())
 
 def write_png(self, fname):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <lee...@us...> - 2008年12月18日 08:55:53
Revision: 6658
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6658&view=rev
Author: leejjoon
Date: 2008年12月18日 08:55:50 +0000 (2008年12月18日)
Log Message:
-----------
fix dpi-dependent behavior of text bbox & annotate arrow
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/lib/matplotlib/text.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月17日 23:37:18 UTC (rev 6657)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月18日 08:55:50 UTC (rev 6658)
@@ -1,3 +1,6 @@
+2008年12月17日 fix dpi-dependent behavior of text bbox and arrow in annotate
+ -JJL
+
 2008年12月16日 Another attempt to fix dpi-dependent behavior of Legend. -JJL
 
 ======================================================================
Modified: branches/v0_98_5_maint/lib/matplotlib/text.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/text.py	2008年12月17日 23:37:18 UTC (rev 6657)
+++ branches/v0_98_5_maint/lib/matplotlib/text.py	2008年12月18日 08:55:50 UTC (rev 6658)
@@ -367,7 +367,8 @@
 
 
 def update_bbox_position_size(self, renderer):
- """ Update the location and the size of the bbox. This method
+ """
+ Update the location and the size of the bbox. This method
 should be used when the position and size of the bbox needs to
 be updated before actually drawing the bbox.
 """
@@ -395,8 +396,8 @@
 tr = mtransforms.Affine2D().rotate(theta)
 tr = tr.translate(posx+x_box, posy+y_box)
 self._bbox_patch.set_transform(tr)
- fontsize = renderer.points_to_pixels(self.get_size())
- self._bbox_patch.set_mutation_scale(fontsize)
+ fontsize_in_pixel = renderer.points_to_pixels(self.get_size())
+ self._bbox_patch.set_mutation_scale(fontsize_in_pixel)
 #self._bbox_patch.draw(renderer)
 
 else:
@@ -434,7 +435,8 @@
 tr = mtransforms.Affine2D().rotate(theta)
 tr = tr.translate(posx+x_box, posy+y_box)
 self._bbox_patch.set_transform(tr)
- self._bbox_patch.set_mutation_scale(self.get_size())
+ fontsize_in_pixel = renderer.points_to_pixels(self.get_size())
+ self._bbox_patch.set_mutation_scale(fontsize_in_pixel)
 self._bbox_patch.draw(renderer)
 
 
@@ -1557,6 +1559,7 @@
 
 self.arrow_patch.set_positions((ox0, oy0), (ox1,oy1))
 mutation_scale = d.pop("mutation_scale", self.get_size())
+ mutation_scale = renderer.points_to_pixels(mutation_scale)
 self.arrow_patch.set_mutation_scale(mutation_scale)
 
 if self._bbox_patch:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jd...@us...> - 2008年12月18日 12:23:14
Revision: 6660
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6660&view=rev
Author: jdh2358
Date: 2008年12月18日 12:10:51 +0000 (2008年12月18日)
Log Message:
-----------
applied maxosx backend update
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/doc/_templates/index.html
 branches/v0_98_5_maint/lib/matplotlib/__init__.py
 branches/v0_98_5_maint/lib/matplotlib/backends/backend_macosx.py
 branches/v0_98_5_maint/src/_macosx.m
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月18日 09:02:11 UTC (rev 6659)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月18日 12:10:51 UTC (rev 6660)
@@ -1,6 +1,8 @@
+2008年12月17日 Applied macosx backend patch with support for path
+ collections, quadmesh, etc... - JDH
+
 2008年12月17日 fix dpi-dependent behavior of text bbox and arrow in annotate
 -JJL
-
 2008年12月16日 Another attempt to fix dpi-dependent behavior of Legend. -JJL
 
 ======================================================================
Modified: branches/v0_98_5_maint/doc/_templates/index.html
===================================================================
--- branches/v0_98_5_maint/doc/_templates/index.html	2008年12月18日 09:02:11 UTC (rev 6659)
+++ branches/v0_98_5_maint/doc/_templates/index.html	2008年12月18日 12:10:51 UTC (rev 6660)
@@ -1,5 +1,5 @@
 {% extends "layout.html" %}
-{% set title = 'Overview' %}
+{% set title = 'matplotlib: python plotting' %}
 
 
 {% block body %}
Modified: branches/v0_98_5_maint/lib/matplotlib/__init__.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/__init__.py	2008年12月18日 09:02:11 UTC (rev 6659)
+++ branches/v0_98_5_maint/lib/matplotlib/__init__.py	2008年12月18日 12:10:51 UTC (rev 6660)
@@ -89,7 +89,7 @@
 """
 from __future__ import generators
 
-__version__ = '0.98.5.1'
+__version__ = '0.98.5.2'
 __revision__ = '$Revision$'
 __date__ = '$Date$'
 
Modified: branches/v0_98_5_maint/lib/matplotlib/backends/backend_macosx.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/backends/backend_macosx.py	2008年12月18日 09:02:11 UTC (rev 6659)
+++ branches/v0_98_5_maint/lib/matplotlib/backends/backend_macosx.py	2008年12月18日 12:10:51 UTC (rev 6660)
@@ -10,6 +10,7 @@
 from matplotlib.figure import Figure
 from matplotlib.path import Path
 from matplotlib.mathtext import MathTextParser
+from matplotlib.colors import colorConverter
 
 
 
@@ -48,34 +49,47 @@
 self.width, self.height = width, height
 
 def draw_path(self, gc, path, transform, rgbFace=None):
- path = transform.transform_path(path)
- for points, code in path.iter_segments():
- if code == Path.MOVETO:
- gc.moveto(points)
- elif code == Path.LINETO:
- gc.lineto(points)
- elif code == Path.CURVE3:
- gc.curve3(points)
- elif code == Path.CURVE4:
- gc.curve4(points)
- elif code == Path.CLOSEPOLY:
- gc.closepoly()
 if rgbFace is not None:
 rgbFace = tuple(rgbFace)
- gc.stroke(rgbFace)
+ if gc!=self.gc:
+ n = self.gc.level() - gc.level()
+ for i in range(n): self.gc.restore()
+ self.gc = gc
+ gc.draw_path(path, transform, rgbFace)
 
+ def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None):
+ if rgbFace is not None:
+ rgbFace = tuple(rgbFace)
+ if gc!=self.gc:
+ n = self.gc.level() - gc.level()
+ for i in range(n): self.gc.restore()
+ self.gc = gc
+ gc.draw_markers(marker_path, marker_trans, path, trans, rgbFace)
+
+ def draw_path_collection(self, *args):
+ gc = self.gc
+ args = args[:13]
+ gc.draw_path_collection(*args)
+
+ def draw_quad_mesh(self, *args):
+ gc = self.gc
+ gc.draw_quad_mesh(*args)
+
 def new_gc(self):
 self.gc.reset()
 return self.gc
 
 def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
- self.gc.set_clip_rectangle(bbox)
 im.flipud_out()
 nrows, ncols, data = im.as_rgba_str()
- self.gc.draw_image(x, y, nrows, ncols, data)
+ self.gc.draw_image(x, y, nrows, ncols, data, bbox, clippath, clippath_trans)
 im.flipud_out()
 
 def draw_tex(self, gc, x, y, s, prop, angle):
+ if gc!=self.gc:
+ n = self.gc.level() - gc.level()
+ for i in range(n): self.gc.restore()
+ self.gc = gc
 # todo, handle props, angle, origins
 size = prop.get_size_in_points()
 texmanager = self.get_texmanager()
@@ -88,12 +102,20 @@
 gc.draw_mathtext(x, y, angle, Z)
 
 def _draw_mathtext(self, gc, x, y, s, prop, angle):
+ if gc!=self.gc:
+ n = self.gc.level() - gc.level()
+ for i in range(n): self.gc.restore()
+ self.gc = gc
 size = prop.get_size_in_points()
 ox, oy, width, height, descent, image, used_characters = \
 self.mathtext_parser.parse(s, self.dpi, prop)
 gc.draw_mathtext(x, y, angle, 255 - image.as_array())
 
 def draw_text(self, gc, x, y, s, prop, angle, ismath=False):
+ if gc!=self.gc:
+ n = self.gc.level() - gc.level()
+ for i in range(n): self.gc.restore()
+ self.gc = gc
 if ismath:
 self._draw_mathtext(gc, x, y, s, prop, angle)
 else:
@@ -143,6 +165,11 @@
 GraphicsContextBase.__init__(self)
 _macosx.GraphicsContext.__init__(self)
 
+ def set_foreground(self, fg, isRGB=False):
+ if not isRGB:
+ fg = colorConverter.to_rgb(fg)
+ _macosx.GraphicsContext.set_foreground(self, fg)
+
 def set_clip_rectangle(self, box):
 GraphicsContextBase.set_clip_rectangle(self, box)
 if not box: return
@@ -152,20 +179,8 @@
 GraphicsContextBase.set_clip_path(self, path)
 if not path: return
 path = path.get_fully_transformed_path()
- for points, code in path.iter_segments():
- if code == Path.MOVETO:
- self.moveto(points)
- elif code == Path.LINETO:
- self.lineto(points)
- elif code == Path.CURVE3:
- self.curve3(points)
- elif code == Path.CURVE4:
- self.curve4(points)
- elif code == Path.CLOSEPOLY:
- self.closepoly()
- self.clip_path()
+ _macosx.GraphicsContext.set_clip_path(self, path)
 
-
 ########################################################################
 # 
 # The following functions and classes are for pylab and implement
Modified: branches/v0_98_5_maint/src/_macosx.m
===================================================================
--- branches/v0_98_5_maint/src/_macosx.m	2008年12月18日 09:02:11 UTC (rev 6659)
+++ branches/v0_98_5_maint/src/_macosx.m	2008年12月18日 12:10:51 UTC (rev 6660)
@@ -4,15 +4,33 @@
 #include <Python.h>
 #include "numpy/arrayobject.h"
 
-static int nwin = 0;
+static int nwin = 0; /* The number of open windows */
+static int ngc = 0; /* The number of graphics contexts in use */
 
 
-/* Varius NSApplicationDefined event subtypes */
+/* For drawing Unicode strings with ATSUI */
+static ATSUStyle style = NULL;
+static ATSUTextLayout layout = NULL;
+
+/* CGFloat was defined in Mac OS X 10.5 */
+#ifndef CGFloat
+#define CGFloat float
+#endif
+
+
+/* Various NSApplicationDefined event subtypes */
 #define STDIN_READY 0
 #define SIGINT_CALLED 1
 #define STOP_EVENT_LOOP 2
 #define WINDOW_CLOSING 3
 
+/* Path definitions */
+#define STOP 0
+#define MOVETO 1
+#define LINETO 2
+#define CURVE3 3
+#define CURVE4 4
+#define CLOSEPOLY 5
 /* -------------------------- Helper function ---------------------------- */
 
 static void stdin_ready(CFReadStreamRef readStream, CFStreamEventType eventType, void* context)
@@ -147,8 +165,44 @@
 return 1;
 }
 
-static char show__doc__[] = "Show all the figures and enter the main loop.\nThis function does not return until all Matplotlib windows are closed,\nand is normally not needed in interactive sessions.";
+static int _init_atsui(void)
+{
+ OSStatus status;
 
+ status = ATSUCreateStyle(&style);
+ if (status!=noErr)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "ATSUCreateStyle failed");
+ return 0;
+ }
+
+ status = ATSUCreateTextLayout(&layout);
+ if (status!=noErr)
+ {
+ status = ATSUDisposeStyle(style);
+ if (status!=noErr)
+ PyErr_WarnEx(PyExc_RuntimeWarning, "ATSUDisposeStyle failed", 1);
+ PyErr_SetString(PyExc_RuntimeError, "ATSUCreateTextLayout failed");
+ return 0;
+ }
+
+
+ return 1;
+}
+
+static void _dealloc_atsui(void)
+{
+ OSStatus status;
+
+ status = ATSUDisposeStyle(style);
+ if (status!=noErr)
+ PyErr_WarnEx(PyExc_RuntimeWarning, "ATSUDisposeStyle failed", 1);
+
+ status = ATSUDisposeTextLayout(layout);
+ if (status!=noErr)
+ PyErr_WarnEx(PyExc_RuntimeWarning, "ATSUDisposeTextLayout failed", 1);
+}
+
 /* ---------------------------- Cocoa classes ---------------------------- */
 
 
@@ -220,76 +274,38 @@
 typedef struct {
 PyObject_HEAD
 CGContextRef cr;
- PyObject* converter; /* Convert color specifications to r,g,b triples */
 CGPatternRef pattern; /* For drawing hatches */
- ATSUStyle style; /* For drawing Unicode strings with ATSUI */
- ATSUTextLayout layout; /* For drawing Unicode strings with ATSUI */
 } GraphicsContext;
 
 static PyObject*
 GraphicsContext_new(PyTypeObject* type, PyObject *args, PyObject *kwds)
 {
- OSStatus status;
-
 GraphicsContext* self = (GraphicsContext*)type->tp_alloc(type, 0);
 if (!self) return NULL;
 self->cr = NULL;
- PyObject* module = PyImport_AddModule("matplotlib.colors");
- if (!module) return NULL;
- PyObject* dict = PyObject_GetAttrString(module, "__dict__");
- if (!dict) return NULL;
- PyObject* colorConverter = PyDict_GetItemString(dict, "colorConverter");
- Py_DECREF(dict);
- if (!colorConverter)
- {
- PyErr_SetString(PyExc_KeyError,
- "failed to find colorConverter in matplotlib.colors");
- return NULL;
- }
- self->converter = PyObject_GetAttrString(colorConverter, "to_rgb");
- if (!self->converter) return NULL;
-
 self->pattern = NULL;
 
- status = ATSUCreateStyle(&self->style);
- if (status!=noErr)
+ if (ngc==0)
 {
- Py_DECREF(self->converter);
- PyErr_SetString(PyExc_RuntimeError, "ATSUCreateStyle failed");
- return NULL;
+ int ok = _init_atsui();
+ if (!ok)
+ {
+ return NULL;
+ }
 }
+ ngc++;
 
- status = ATSUCreateTextLayout(&self->layout);
- if (status!=noErr)
- {
- Py_DECREF(self->converter);
- status = ATSUDisposeStyle(self->style);
- if (status!=noErr)
- PyErr_WarnEx(PyExc_RuntimeWarning, "ATSUDisposeStyle failed", 1);
- PyErr_SetString(PyExc_RuntimeError, "ATSUCreateTextLayout failed");
- return NULL;
- }
-
 return (PyObject*) self;
 }
 
 static void
 GraphicsContext_dealloc(GraphicsContext *self)
 {
- Py_DECREF(self->converter);
+ CGPatternRelease(self->pattern);
 
- if (self->pattern) CGPatternRelease(self->pattern);
+ ngc--;
+ if (ngc==0) _dealloc_atsui();
 
- OSStatus status;
-
- status = ATSUDisposeStyle(self->style);
- if (status!=noErr)
- PyErr_WarnEx(PyExc_RuntimeWarning, "ATSUDisposeStyle failed", 1);
-
- status = ATSUDisposeTextLayout(self->layout);
- if (status!=noErr)
- PyErr_WarnEx(PyExc_RuntimeWarning, "ATSUDisposeTextLayout failed", 1);
-
 self->ob_type->tp_free((PyObject*)self);
 }
 
@@ -308,6 +324,13 @@
 PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
 return NULL;
 }
+
+ if (self->pattern)
+ {
+ CGPatternRelease(self->pattern);
+ self->pattern = NULL;
+ }
+
 CGContextRestoreGState(cr);
 CGContextSaveGState(cr);
 Py_INCREF(Py_None);
@@ -400,7 +423,7 @@
 }
 
 static PyObject*
-GraphicsContext_clip_path (GraphicsContext* self)
+GraphicsContext_set_clip_path (GraphicsContext* self, PyObject* args)
 {
 CGContextRef cr = self->cr;
 if (!cr)
@@ -408,29 +431,216 @@
 PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
 return NULL;
 }
- CGContextRestoreGState(cr);
- CGContextSaveGState(cr);
- CGContextClip(cr);
- Py_INCREF(Py_None);
- return Py_None;
-}
+#ifdef BUH
+ CGContextRestoreGState(cr); /* FIXME */
+ CGContextSaveGState(cr); /* FIXME */
+#endif
 
-static PyObject*
-GraphicsContext_set_dashes (GraphicsContext* self, PyObject* args)
-{ 
- float phase = 0.0;
- PyObject* offset;
- PyObject* dashes;
+ PyObject* path;
 
- if (!PyArg_ParseTuple(args, "OO", &offset, &dashes)) return NULL;
+ if(!PyArg_ParseTuple(args, "O", &path)) return NULL;
 
- CGContextRef cr = self->cr;
- if (!cr)
+ PyObject* vertices = PyObject_GetAttrString(path, "vertices");
+ if (vertices==NULL)
 {
- PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
+ PyErr_SetString(PyExc_AttributeError, "path has no vertices");
 return NULL;
 }
+ Py_DECREF(vertices); /* Don't keep a reference here */
 
+ PyObject* codes = PyObject_GetAttrString(path, "codes");
+ if (codes==NULL)
+ {
+ PyErr_SetString(PyExc_AttributeError, "path has no codes");
+ return NULL;
+ }
+ Py_DECREF(codes); /* Don't keep a reference here */
+
+ PyArrayObject* coordinates;
+ coordinates = (PyArrayObject*)PyArray_FromObject(vertices,
+ NPY_DOUBLE, 2, 2);
+ if (!coordinates)
+ {
+ PyErr_SetString(PyExc_ValueError, "failed to convert vertices array");
+ return NULL;
+ }
+
+ if (PyArray_NDIM(coordinates) != 2 || PyArray_DIM(coordinates, 1) != 2)
+ {
+ Py_DECREF(coordinates);
+ PyErr_SetString(PyExc_ValueError, "invalid vertices array");
+ return NULL;
+ }
+
+ npy_intp n = PyArray_DIM(coordinates, 0);
+
+ if (n==0) /* Nothing to do here */
+ {
+ Py_DECREF(coordinates);
+ return NULL;
+ }
+
+ PyArrayObject* codelist = NULL;
+ if (codes != Py_None)
+ {
+ codelist = (PyArrayObject*)PyArray_FromObject(codes,
+ NPY_UINT8, 1, 1);
+ if (!codelist)
+ {
+ Py_DECREF(coordinates);
+ PyErr_SetString(PyExc_ValueError, "invalid codes array");
+ return NULL;
+ }
+ }
+
+ CGFloat x, y;
+
+ if (codelist==NULL)
+ {
+ npy_intp i;
+ npy_uint8 code = MOVETO;
+ for (i = 0; i < n; i++)
+ {
+ x = (CGFloat)(*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y = (CGFloat)(*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ if (isnan(x) || isnan(y))
+ {
+ code = MOVETO;
+ }
+ else
+ {
+ switch (code)
+ {
+ case MOVETO:
+ CGContextMoveToPoint(cr, x, y);
+ break;
+ case LINETO:
+ CGContextAddLineToPoint(cr, x, y);
+ break;
+ }
+ code = LINETO;
+ }
+ }
+ }
+ else
+ {
+ npy_intp i = 0;
+ BOOL was_nan = false;
+ npy_uint8 code;
+ CGFloat x1, y1, x2, y2, x3, y3;
+ while (i < n)
+ {
+ code = *(npy_uint8*)PyArray_GETPTR1(codelist, i);
+ if (code == CLOSEPOLY)
+ {
+ CGContextClosePath(cr);
+ i++;
+ }
+ else if (code == STOP)
+ {
+ break;
+ }
+ else if (was_nan)
+ {
+ if (code==CURVE3) i++;
+ else if (code==CURVE4) i+=2;
+ x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ if (isnan(x1) || isnan(y1))
+ {
+ was_nan = true;
+ }
+ else
+ {
+ CGContextMoveToPoint(cr, x1, y1);
+ was_nan = false;
+ }
+ }
+ else if (code==MOVETO)
+ {
+ x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ if (isnan(x1) || isnan(y1))
+ {
+ was_nan = true;
+ }
+ else
+ {
+ CGContextMoveToPoint(cr, x1, y1);
+ was_nan = false;
+ }
+ }
+ else if (code==LINETO)
+ {
+ x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ if (isnan(x1) || isnan(y1))
+ {
+ was_nan = true;
+ }
+ else
+ {
+ CGContextAddLineToPoint(cr, x1, y1);
+ was_nan = false;
+ }
+ }
+ else if (code==CURVE3)
+ {
+ x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ x2 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y2 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ if (isnan(x1) || isnan(y1) || isnan(x2) || isnan(y2))
+ {
+ was_nan = true;
+ }
+ else
+ {
+ CGContextAddQuadCurveToPoint(cr, x1, y1, x2, y2);
+ was_nan = false;
+ }
+ }
+ else if (code==CURVE4)
+ {
+ x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ x2 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y2 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ x3 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y3 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ if (isnan(x1) || isnan(y1) || isnan(x2) || isnan(y2) || isnan(x3) || isnan(y3))
+ {
+ was_nan = true;
+ }
+ else
+ {
+ CGContextAddCurveToPoint(cr, x1, y1, x2, y2, x3, y3);
+ was_nan = false;
+ }
+ }
+ }
+ Py_DECREF(codelist);
+ }
+
+ Py_DECREF(coordinates);
+
+ CGContextClip(cr);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static BOOL
+_set_dashes(CGContextRef cr, PyObject* offset, PyObject* dashes)
+{
+ float phase = 0.0;
 if (offset!=Py_None)
 {
 if (PyFloat_Check(offset)) phase = PyFloat_AsDouble(offset);
@@ -439,7 +649,7 @@
 {
 PyErr_SetString(PyExc_TypeError,
 "offset should be a floating point value");
- return NULL;
+ return false;
 }
 }
 
@@ -451,7 +661,7 @@
 {
 PyErr_SetString(PyExc_TypeError,
 "dashes should be a tuple or a list");
- return NULL;
+ return false;
 }
 int n = PyTuple_GET_SIZE(dashes);
 int i;
@@ -460,7 +670,7 @@
 {
 PyErr_SetString(PyExc_MemoryError, "Failed to store dashes");
 Py_DECREF(dashes);
- return NULL;
+ return false;
 }
 for (i = 0; i < n; i++)
 {
@@ -476,7 +686,7 @@
 {
 free(lengths);
 PyErr_SetString(PyExc_TypeError, "Failed to read dashes");
- return NULL;
+ return false;
 }
 CGContextSetLineDash(cr, phase, lengths, n);
 free(lengths);
@@ -484,29 +694,40 @@
 else
 CGContextSetLineDash(cr, phase, NULL, 0);
 
- Py_INCREF(Py_None);
- return Py_None;
+ return true;
 }
 
 static PyObject*
-GraphicsContext_set_foreground(GraphicsContext* self, PyObject* args, PyObject* keywords)
-{ float r, g, b;
- PyObject* fg;
- int isRGB = 0;
- static char* kwlist[] = {"fg", "isRGB", NULL};
- if(!PyArg_ParseTupleAndKeywords(args, keywords, "O|i", kwlist,
- &fg, &isRGB)) return NULL;
- if (isRGB)
+GraphicsContext_set_dashes (GraphicsContext* self, PyObject* args)
+{ 
+ PyObject* offset;
+ PyObject* dashes;
+
+ if (!PyArg_ParseTuple(args, "OO", &offset, &dashes)) return NULL;
+
+ CGContextRef cr = self->cr;
+ if (!cr)
 {
- if(!PyArg_ParseTuple(fg, "fff", &r, &g, &b)) return NULL;
+ PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
+ return NULL;
 }
+
+ BOOL ok = _set_dashes(cr, offset, dashes);
+ if (ok)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
 else
- { fg = PyObject_CallFunctionObjArgs(self->converter, fg, NULL);
- if(!fg) return NULL;
- if(!PyArg_ParseTuple(fg, "fff", &r, &g, &b)) return NULL;
- Py_DECREF(fg);
- }
+ return NULL;
+}
 
+static PyObject*
+GraphicsContext_set_foreground(GraphicsContext* self, PyObject* args)
+{
+ float r, g, b;
+ if(!PyArg_ParseTuple(args, "(fff)", &r, &g, &b)) return NULL;
+
 CGContextRef cr = self->cr;
 if (!cr)
 {
@@ -538,7 +759,7 @@
 return Py_None;
 }
 
-static void drawHatch (void *info, CGContextRef cr)
+static void _draw_hatch (void *info, CGContextRef cr)
 {
 int i;
 
@@ -603,12 +824,20 @@
 Py_DECREF(string);
 }
 
+static void _release_hatch(void* info)
+{
+ PyObject* hatches = info;
+ Py_DECREF(hatches);
+}
+
 static PyObject*
 GraphicsContext_set_hatch(GraphicsContext* self, PyObject* args)
 { PyObject* hatches;
 
 const float size = 12.0;
- static const CGPatternCallbacks callbacks = {0, &drawHatch, NULL};
+ static const CGPatternCallbacks callbacks = {0,
+ &_draw_hatch,
+ &_release_hatch};
 
 CGContextRef cr = self->cr;
 if (!cr)
@@ -687,122 +916,828 @@
 return Py_None;
 }
 
-static PyObject*
-GraphicsContext_moveto(GraphicsContext* self, PyObject* args)
-{ 
- float x;
- float y;
-
- if(!PyArg_ParseTuple(args, "(ff)", &x, &y)) return NULL;
-
- CGContextRef cr = self->cr;
- if (!cr)
+static int
+_convert_affine_transform(PyObject* object, CGAffineTransform* transform)
+/* Reads a Numpy affine transformation matrix and returns
+ * a CGAffineTransform.
+ */
+{
+ PyArrayObject* matrix = NULL;
+ if (object==Py_None)
 {
- PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
- return NULL;
+ PyErr_SetString(PyExc_ValueError,
+ "Found affine transformation matrix equal to None");
+ return 0;
 }
- CGContextMoveToPoint(cr, x, y);
+ matrix = (PyArrayObject*) PyArray_FromObject(object, NPY_DOUBLE, 2, 2);
+ if (!matrix)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "Invalid affine transformation matrix");
+ return 0;
+ }
+ if (PyArray_NDIM(matrix) != 2 || PyArray_DIM(matrix, 0) != 3 || PyArray_DIM(matrix, 1) != 3)
+ {
+ Py_DECREF(matrix);
+ PyErr_SetString(PyExc_ValueError,
+ "Affine transformation matrix has invalid dimensions");
+ return 0;
+ }
 
- Py_INCREF(Py_None);
- return Py_None;
+ size_t stride0 = (size_t)PyArray_STRIDE(matrix, 0);
+ size_t stride1 = (size_t)PyArray_STRIDE(matrix, 1);
+ char* row0 = PyArray_BYTES(matrix);
+ char* row1 = row0 + stride0;
+
+ double a = *(double*)(row0);
+ row0 += stride1;
+ double c = *(double*)(row0);
+ row0 += stride1;
+ double e = *(double*)(row0);
+ double b = *(double*)(row1);
+ row1 += stride1;
+ double d = *(double*)(row1);
+ row1 += stride1;
+ double f = *(double*)(row1);
+ *transform = CGAffineTransformMake(a, b, c, d, e, f);
+
+ Py_DECREF(matrix);
+ return 1;
 }
 
-static PyObject*
-GraphicsContext_lineto(GraphicsContext* self, PyObject* args)
+static int
+_draw_path(CGContextRef cr, PyObject* path, CGAffineTransform affine)
 {
- float x;
- float y;
+ CGPoint point;
 
- if(!PyArg_ParseTuple(args, "(ff)", &x, &y)) return NULL;
+ PyObject* vertices = PyObject_GetAttrString(path, "vertices");
+ if (vertices==NULL)
+ {
+ PyErr_SetString(PyExc_AttributeError, "path has no vertices");
+ return -1;
+ }
+ Py_DECREF(vertices); /* Don't keep a reference here */
 
- CGContextRef cr = self->cr;
- if (!cr)
+ PyObject* codes = PyObject_GetAttrString(path, "codes");
+ if (codes==NULL)
 {
- PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
- return NULL;
+ PyErr_SetString(PyExc_AttributeError, "path has no codes");
+ return -1;
 }
- CGContextAddLineToPoint(cr, x, y);
+ Py_DECREF(codes); /* Don't keep a reference here */
 
- Py_INCREF(Py_None);
- return Py_None;
+ PyArrayObject* coordinates;
+ coordinates = (PyArrayObject*)PyArray_FromObject(vertices,
+ NPY_DOUBLE, 2, 2);
+ if (!coordinates)
+ {
+ PyErr_SetString(PyExc_ValueError, "failed to convert vertices array");
+ return -1;
+ }
+
+ if (PyArray_NDIM(coordinates) != 2 || PyArray_DIM(coordinates, 1) != 2)
+ {
+ Py_DECREF(coordinates);
+ PyErr_SetString(PyExc_ValueError, "invalid vertices array");
+ return -1;
+ }
+
+ npy_intp n = PyArray_DIM(coordinates, 0);
+
+ if (n==0) /* Nothing to do here */
+ {
+ Py_DECREF(coordinates);
+ return 0;
+ }
+
+ PyArrayObject* codelist = NULL;
+ if (codes != Py_None)
+ {
+ codelist = (PyArrayObject*)PyArray_FromObject(codes,
+ NPY_UINT8, 1, 1);
+ if (!codelist)
+ {
+ Py_DECREF(coordinates);
+ PyErr_SetString(PyExc_ValueError, "invalid codes array");
+ return -1;
+ }
+ }
+
+ if (codelist==NULL)
+ {
+ npy_intp i;
+ npy_uint8 code = MOVETO;
+ for (i = 0; i < n; i++)
+ {
+ point.x = (CGFloat)(*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ point.y = (CGFloat)(*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ if (isnan(point.x) || isnan(point.y))
+ {
+ code = MOVETO;
+ }
+ else
+ {
+ point = CGPointApplyAffineTransform(point, affine);
+ switch (code)
+ {
+ case MOVETO:
+ CGContextMoveToPoint(cr, point.x, point.y);
+ break;
+ case LINETO:
+ CGContextAddLineToPoint(cr, point.x, point.y);
+ break;
+ }
+ code = LINETO;
+ }
+ }
+ }
+ else
+ {
+ npy_intp i = 0;
+ BOOL was_nan = false;
+ npy_uint8 code;
+ CGFloat x1, y1, x2, y2, x3, y3;
+ while (i < n)
+ {
+ code = *(npy_uint8*)PyArray_GETPTR1(codelist, i);
+ if (code == CLOSEPOLY)
+ {
+ CGContextClosePath(cr);
+ i++;
+ }
+ else if (code == STOP)
+ {
+ break;
+ }
+ else if (was_nan)
+ {
+ if (code==CURVE3) i++;
+ else if (code==CURVE4) i+=2;
+ x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ if (isnan(x1) || isnan(y1))
+ {
+ was_nan = true;
+ }
+ else
+ {
+ point.x = x1;
+ point.y = y1;
+ point = CGPointApplyAffineTransform(point, affine);
+ CGContextMoveToPoint(cr, point.x, point.y);
+ was_nan = false;
+ }
+ }
+ else if (code==MOVETO)
+ {
+ x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ if (isnan(x1) || isnan(y1))
+ {
+ was_nan = true;
+ }
+ else
+ {
+ point.x = x1;
+ point.y = y1;
+ point = CGPointApplyAffineTransform(point, affine);
+ CGContextMoveToPoint(cr, point.x, point.y);
+ was_nan = false;
+ }
+ }
+ else if (code==LINETO)
+ {
+ x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ if (isnan(x1) || isnan(y1))
+ {
+ was_nan = true;
+ }
+ else
+ {
+ point.x = x1;
+ point.y = y1;
+ point = CGPointApplyAffineTransform(point, affine);
+ CGContextAddLineToPoint(cr, point.x, point.y);
+ was_nan = false;
+ }
+ }
+ else if (code==CURVE3)
+ {
+ x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ x2 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y2 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ if (isnan(x1) || isnan(y1) || isnan(x2) || isnan(y2))
+ {
+ was_nan = true;
+ }
+ else
+ {
+ point.x = x1;
+ point.y = y1;
+ point = CGPointApplyAffineTransform(point, affine);
+ x1 = point.x;
+ y1 = point.y;
+ point.x = x2;
+ point.y = y2;
+ point = CGPointApplyAffineTransform(point, affine);
+ x2 = point.x;
+ y2 = point.y;
+ CGContextAddQuadCurveToPoint(cr, x1, y1, x2, y2);
+ was_nan = false;
+ }
+ }
+ else if (code==CURVE4)
+ {
+ x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ x2 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y2 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ x3 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ y3 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ i++;
+ if (isnan(x1) || isnan(y1) || isnan(x2) || isnan(y2) || isnan(x3) || isnan(y3))
+ {
+ was_nan = true;
+ }
+ else
+ {
+ point.x = x1;
+ point.y = y1;
+ point = CGPointApplyAffineTransform(point, affine);
+ x1 = point.x;
+ y1 = point.y;
+ point.x = x2;
+ point.y = y2;
+ point = CGPointApplyAffineTransform(point, affine);
+ x2 = point.x;
+ y2 = point.y;
+ point.x = x3;
+ point.y = y3;
+ point = CGPointApplyAffineTransform(point, affine);
+ x3 = point.x;
+ y3 = point.y;
+ CGContextAddCurveToPoint(cr, x1, y1, x2, y2, x3, y3);
+ was_nan = false;
+ }
+ }
+ }
+ }
+
+ Py_DECREF(coordinates);
+ Py_XDECREF(codelist);
+ return n;
 }
 
 static PyObject*
-GraphicsContext_curve3(GraphicsContext* self, PyObject* args)
-{ 
- float cpx;
- float cpy;
- float x;
- float y;
+GraphicsContext_draw_path (GraphicsContext* self, PyObject* args)
+{
+ PyObject* path;
+ PyObject* transform;
+ PyObject* rgbFace;
 
+ int ok;
+ 
 CGContextRef cr = self->cr;
+
 if (!cr)
 {
 PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
 return NULL;
 }
 
- if(!PyArg_ParseTuple(args, "(ffff)", &cpx,
- &cpy,
- &x,
- &y)) return NULL;
+ if(!PyArg_ParseTuple(args, "OO|O",
+ &path,
+ &transform,
+ &rgbFace)) return NULL;
 
- CGContextAddQuadCurveToPoint(cr, cpx, cpy, x, y);
+ if(rgbFace==Py_None) rgbFace = NULL;
 
+ CGAffineTransform affine;
+ ok = _convert_affine_transform(transform, &affine);
+ if (!ok) return NULL;
+
+ int n = _draw_path(cr, path, affine);
+ if (n==-1) return NULL;
+ 
+ if (n > 0)
+ {
+ if(rgbFace)
+ {
+ float r, g, b;
+ ok = PyArg_ParseTuple(rgbFace, "fff", &r, &g, &b);
+ if (!ok)
+ {
+ return NULL;
+ }
+ CGContextSaveGState(cr);
+ if(self->pattern)
+ {
+ float components[4];
+ components[0] = r;
+ components[1] = g;
+ components[2] = b;
+ components[3] = 1.0;
+ CGContextSetFillPattern(cr, self->pattern, components);
+ CGPatternRelease(self->pattern);
+ self->pattern = nil;
+ }
+ else CGContextSetRGBFillColor(cr, r, g, b, 1.0);
+ CGContextDrawPath(cr, kCGPathFillStroke);
+ CGContextRestoreGState(cr);
+ }
+ else CGContextStrokePath(cr);
+ }
+
 Py_INCREF(Py_None);
 return Py_None;
 }
 
 static PyObject*
-GraphicsContext_curve4 (GraphicsContext* self, PyObject* args)
+GraphicsContext_draw_markers (GraphicsContext* self, PyObject* args)
 {
- float cp1x;
- float cp1y;
- float cp2x;
- float cp2y;
- float x;
- float y;
+ PyObject* marker_path;
+ PyObject* marker_transform;
+ PyObject* path;
+ PyObject* transform;
+ PyObject* rgbFace;
 
+ int ok;
+ float r, g, b;
+ 
 CGContextRef cr = self->cr;
+
 if (!cr)
 {
 PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
 return NULL;
 }
 
- if(!PyArg_ParseTuple(args, "(ffffff)", &cp1x,
- &cp1y,
- &cp2x,
- &cp2y,
- &x,
- &y)) return NULL;
+ if(!PyArg_ParseTuple(args, "OOOO|O",
+ &marker_path,
+ &marker_transform,
+ &path,
+ &transform,
+ &rgbFace)) return NULL;
 
- CGContextAddCurveToPoint(cr, cp1x, cp1y, cp2x, cp2y, x, y);
+ if(rgbFace==Py_None) rgbFace = NULL;
 
+ if (rgbFace)
+ {
+ ok = PyArg_ParseTuple(rgbFace, "fff", &r, &g, &b);
+ if (!ok)
+ {
+ return NULL;
+ }
+ if(self->pattern)
+ {
+ float components[4];
+ components[0] = r;
+ components[1] = g;
+ components[2] = b;
+ components[3] = 1.0;
+ CGContextSetFillPattern(cr, self->pattern, components);
+ CGPatternRelease(self->pattern);
+ self->pattern = nil;
+ }
+ else CGContextSetRGBFillColor(cr, r, g, b, 1.0);
+ }
+
+ CGAffineTransform affine;
+ ok = _convert_affine_transform(transform, &affine);
+ if (!ok) return NULL;
+
+ CGAffineTransform marker_affine;
+ ok = _convert_affine_transform(marker_transform, &marker_affine);
+ if (!ok) return NULL;
+
+ PyObject* vertices = PyObject_GetAttrString(path, "vertices");
+ if (vertices==NULL)
+ {
+ PyErr_SetString(PyExc_AttributeError, "path has no vertices");
+ return NULL;
+ }
+ Py_DECREF(vertices); /* Don't keep a reference here */
+
+ PyArrayObject* coordinates;
+ coordinates = (PyArrayObject*)PyArray_FromObject(vertices,
+ NPY_DOUBLE, 2, 2);
+ if (!coordinates)
+ {
+ PyErr_SetString(PyExc_ValueError, "failed to convert vertices array");
+ return NULL;
+ }
+
+ if (PyArray_NDIM(coordinates) != 2 || PyArray_DIM(coordinates, 1) != 2)
+ {
+ Py_DECREF(coordinates);
+ PyErr_SetString(PyExc_ValueError, "invalid vertices array");
+ return NULL;
+ }
+
+ npy_intp i;
+ npy_intp n = PyArray_DIM(coordinates, 0);
+ CGPoint point;
+ CGAffineTransform t;
+ int m = 0;
+ for (i = 0; i < n; i++)
+ {
+ point.x = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
+ point.y = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
+ point = CGPointApplyAffineTransform(point, affine);
+ t = marker_affine;
+ t.tx += point.x;
+ t.ty += point.y;
+ m = _draw_path(cr, marker_path, t);
+
+ if (m > 0)
+ {
+ if(rgbFace) CGContextDrawPath(cr, kCGPathFillStroke);
+ else CGContextStrokePath(cr);
+ }
+ }
+
+ Py_DECREF(coordinates);
+
 Py_INCREF(Py_None);
 return Py_None;
 }
 
+static BOOL _clip(CGContextRef cr, PyObject* object)
+{ 
+ if (object == Py_None) return true;
+
+ PyArrayObject* array = NULL;
+ array = (PyArrayObject*) PyArray_FromObject(object, PyArray_DOUBLE, 2, 2);
+ if (!array)
+ {
+ PyErr_SetString(PyExc_ValueError, "failed to read clipping bounding box");
+ return false;
+ }
+
+ if (PyArray_NDIM(array)!=2 || PyArray_DIM(array, 0)!=2 || PyArray_DIM(array, 1)!=2)
+ {
+ Py_DECREF(array);
+ PyErr_SetString(PyExc_ValueError, "clipping bounding box should be a 2x2 array");
+ return false;
+ }
+
+ const double l = *(double*)PyArray_GETPTR2(array, 0, 0);
+ const double b = *(double*)PyArray_GETPTR2(array, 0, 1);
+ const double r = *(double*)PyArray_GETPTR2(array, 1, 0);
+ const double t = *(double*)PyArray_GETPTR2(array, 1, 1);
+
+ Py_DECREF(array);
+
+ CGRect rect;
+ rect.origin.x = (CGFloat) l;
+ rect.origin.y = (CGFloat) b;
+ rect.size.width = (CGFloat) (r-l);
+ rect.size.height = (CGFloat) (t-b);
+
+ CGContextClipToRect(cr, rect);
+
+ return true;
+}
+
+
 static PyObject*
-GraphicsContext_closepoly (GraphicsContext* self)
+GraphicsContext_draw_path_collection (GraphicsContext* self, PyObject* args)
 {
+ PyObject* master_transform_obj; 
+ PyObject* cliprect; 
+ PyObject* clippath;
+ PyObject* clippath_transform;
+ PyObject* paths;
+ PyObject* transforms_obj;
+ PyObject* offsets_obj;
+ PyObject* offset_transform_obj;
+ PyObject* facecolors_obj;
+ PyObject* edgecolors_obj;
+ PyObject* linewidths;
+ PyObject* linestyles;
+ PyObject* antialiaseds;
+
 CGContextRef cr = self->cr;
+
 if (!cr)
 {
 PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
 return NULL;
 }
 
- CGContextClosePath(cr);
+ if(!PyArg_ParseTuple(args, "OOOOOOOOOOOOO", &master_transform_obj,
+ &cliprect,
+ &clippath,
+ &clippath_transform,
+ &paths,
+ &transforms_obj,
+ &offsets_obj,
+ &offset_transform_obj,
+ &facecolors_obj,
+ &edgecolors_obj,
+ &linewidths,
+ &linestyles,
+ &antialiaseds))
+ return NULL;
 
+ CGContextSaveGState(cr);
+
+ CGAffineTransform transform;
+ CGAffineTransform master_transform;
+ CGAffineTransform offset_transform;
+ CGAffineTransform* transforms = NULL;
+
+ if (!_convert_affine_transform(master_transform_obj, &master_transform)) return NULL;
+ if (!_convert_affine_transform(offset_transform_obj, &offset_transform)) return NULL;
+
+ if (!_clip(cr, cliprect)) return NULL;
+ if (clippath!=Py_None)
+ {
+ if (!_convert_affine_transform(clippath_transform, &transform)) return NULL;
+ int n = _draw_path(cr, clippath, transform);
+ if (n==-1) return NULL;
+ else if (n > 0) CGContextClip(cr);
+ }
+
+ PyArrayObject* offsets = NULL;
+ PyArrayObject* facecolors = NULL;
+ PyArrayObject* edgecolors = NULL;
+
+ /* ------------------- Check offsets array ---------------------------- */
+
+ offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj, NPY_DOUBLE, 0, 2);
+ if (!offsets ||
+ (PyArray_NDIM(offsets)==2 && PyArray_DIM(offsets, 1)!=2) ||
+ (PyArray_NDIM(offsets)==1 && PyArray_DIM(offsets, 0)!=0))
+ {
+ PyErr_SetString(PyExc_ValueError, "Offsets array must be Nx2");
+ goto error;
+ }
+
+ /* ------------------- Check facecolors array ------------------------- */
+
+ facecolors = (PyArrayObject*)PyArray_FromObject(facecolors_obj,
+ NPY_DOUBLE, 1, 2);
+ if (!facecolors ||
+ (PyArray_NDIM(facecolors)==1 && PyArray_DIM(facecolors, 0)!=0) ||
+ (PyArray_NDIM(facecolors)==2 && PyArray_DIM(facecolors, 1)!=4))
+ {
+ PyErr_SetString(PyExc_ValueError, "Facecolors must by a Nx4 numpy array or empty");
+ goto error;
+ }
+
+ /* ------------------- Check edgecolors array ------------------------- */
+
+ edgecolors = (PyArrayObject*)PyArray_FromObject(edgecolors_obj,
+ NPY_DOUBLE, 1, 2);
+ if (!edgecolors ||
+ (PyArray_NDIM(edgecolors)==1 && PyArray_DIM(edgecolors, 0)!=0) ||
+ (PyArray_NDIM(edgecolors)==2 && PyArray_DIM(edgecolors, 1)!=4))
+ {
+ PyErr_SetString(PyExc_ValueError, "Edgecolors must by a Nx4 numpy array or empty");
+ goto error;
+ }
+
+ /* ------------------- Check the other arguments ---------------------- */
+
+ if (!PySequence_Check(paths))
+ {
+ PyErr_SetString(PyExc_ValueError, "paths must be a sequence object");
+ goto error;
+ }
+ if (!PySequence_Check(transforms_obj))
+ {
+ PyErr_SetString(PyExc_ValueError, "transforms must be a sequence object");
+ goto error;
+ }
+ if (!PySequence_Check(linewidths))
+ {
+ PyErr_SetString(PyExc_ValueError, "linewidths must be a sequence object");
+ goto error;
+ }
+ if (!PySequence_Check(linestyles))
+ {
+ PyErr_SetString(PyExc_ValueError, "linestyles must be a sequence object");
+ goto error;
+ }
+ if (!PySequence_Check(antialiaseds))
+ {
+ PyErr_SetString(PyExc_ValueError, "antialiaseds must be a sequence object");
+ goto error;
+ }
+
+ size_t Npaths = (size_t) PySequence_Size(paths);
+ size_t Noffsets = (size_t) PyArray_DIM(offsets, 0);
+ size_t N = Npaths > Noffsets ? Npaths : Noffsets;
+ size_t Ntransforms = (size_t) PySequence_Size(transforms_obj);
+ size_t Nfacecolors = (size_t) PyArray_DIM(facecolors, 0);
+ size_t Nedgecolors = (size_t) PyArray_DIM(edgecolors, 0);
+ size_t Nlinewidths = (size_t) PySequence_Size(linewidths);
+ size_t Nlinestyles = (size_t) PySequence_Size(linestyles);
+ size_t Naa = (size_t) PySequence_Size(antialiaseds);
+ if (N < Ntransforms) Ntransforms = N;
+ if (N < Nlinestyles) Nlinestyles = N;
+ if ((Nfacecolors == 0 && Nedgecolors == 0) || Npaths == 0)
+ {
+ goto success;
+ }
+
+ size_t i = 0;
+
+ /* Convert all of the transforms up front */
+ if (Ntransforms > 0)
+ {
+ transforms = malloc(Ntransforms*sizeof(CGAffineTransform));
+ if (!transforms) goto error;
+ for (i = 0; i < Ntransforms; i++)
+ {
+ PyObject* transform_obj = PySequence_ITEM(transforms_obj, i);
+ if(!_convert_affine_transform(transform_obj, &transforms[i])) goto error;
+ transforms[i] = CGAffineTransformConcat(transforms[i], master_transform);
+ }
+ }
+
+ CGPoint offset;
+ PyObject* path;
+
+ /* Preset graphics context properties if possible */
+ if (Naa==1)
+ {
+ switch(PyObject_IsTrue(PySequence_ITEM(antialiaseds, 0)))
+ {
+ case 1: CGContextSetShouldAntialias(cr, true); break;
+ case 0: CGContextSetShouldAntialias(cr, false); break;
+ case -1:
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "Failed to read antialiaseds array");
+ goto error;
+ }
+ }
+ }
+
+ if (Nlinewidths==1)
+ {
+ double linewidth = PyFloat_AsDouble(PySequence_ITEM(linewidths, 0));
+ CGContextSetLineWidth(cr, (CGFloat)linewidth); 
+ }
+ else if (Nlinewidths==0)
+ CGContextSetLineWidth(cr, 0.0); 
+
+ if (Nlinestyles==1)
+ {
+ PyObject* offset;
+ PyObject* dashes;
+ PyObject* linestyle = PySequence_ITEM(linestyles, 0);
+ if (!PyArg_ParseTuple(linestyle, "OO", &offset, &dashes)) goto error;
+ if (!_set_dashes(cr, offset, dashes)) goto error;
+ }
+
+ if (Nedgecolors==1)
+ {
+ const double r = *(double*)PyArray_GETPTR2(edgecolors, 0, 0);
+ const double g = *(double*)PyArray_GETPTR2(edgecolors, 0, 1);
+ const double b = *(double*)PyArray_GETPTR2(edgecolors, 0, 2);
+ const double a = *(double*)PyArray_GETPTR2(edgecolors, 0, 3);
+ CGContextSetRGBStrokeColor(cr, r, g, b, a);
+ }
+
+ if (Nfacecolors==1)
+ {
+ const double r = *(double*)PyArray_GETPTR2(facecolors, 0, 0);
+ const double g = *(double*)PyArray_GETPTR2(facecolors, 0, 1);
+ const double b = *(double*)PyArray_GETPTR2(facecolors, 0, 2);
+ const double a = *(double*)PyArray_GETPTR2(facecolors, 0, 3);
+ CGContextSetRGBFillColor(cr, r, g, b, a);
+ }
+
+ for (i = 0; i < N; i++)
+ {
+
+ if (Ntransforms)
+ {
+ transform = transforms[i % Ntransforms];
+ }
+ else
+ {
+ transform = master_transform;
+ }
+
+ if (Noffsets)
+ {
+ offset.x = (CGFloat) (*(double*)PyArray_GETPTR2(offsets, i % Noffsets, 0));
+ offset.y = (CGFloat) (*(double*)PyArray_GETPTR2(offsets, i % Noffsets, 1));
+ offset = CGPointApplyAffineTransform(offset, offset_transform);
+ transform.tx += offset.x;
+ transform.ty += offset.y;
+ }
+
+ if (Naa > 1)
+ {
+ switch(PyObject_IsTrue(PySequence_ITEM(antialiaseds, i % Naa)))
+ {
+ case 1: CGContextSetShouldAntialias(cr, true); break;
+ case 0: CGContextSetShouldAntialias(cr, false); break;
+ case -1:
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "Failed to read antialiaseds array");
+ goto error;
+ }
+ }
+ }
+
+ path = PySequence_ITEM(paths, i % Npaths);
+ int n = _draw_path(cr, path, transform);
+ if (n==-1) goto error;
+ else if (n==0) continue;
+
+ if (Nlinewidths > 1)
+ {
+ double linewidth = PyFloat_AsDouble(PySequence_ITEM(linewidths, i % Nlinewidths));
+ CGContextSetLineWidth(cr, (CGFloat)linewidth); 
+ }
+
+ if (Nlinestyles > 1)
+ {
+ PyObject* offset;
+ PyObject* dashes;
+ PyObject* linestyle = PySequence_ITEM(linestyles, i % Nlinestyles);
+ if (!PyArg_ParseTuple(linestyle, "OO", &offset, &dashes)) goto error;
+ if (!_set_dashes(cr, offset, dashes)) goto error;
+ }
+
+ if (Nedgecolors > 1)
+ {
+ npy_intp fi = i % Nedgecolors;
+ const double r = *(double*)PyArray_GETPTR2(edgecolors, fi, 0);
+ const double g = *(double*)PyArray_GETPTR2(edgecolors, fi, 1);
+ const double b = *(double*)PyArray_GETPTR2(edgecolors, fi, 2);
+ const double a = *(double*)PyArray_GETPTR2(edgecolors, fi, 3);
+ CGContextSetRGBStrokeColor(cr, r, g, b, a);
+ }
+
+ if (Nfacecolors > 1)
+ {
+ npy_intp fi = i % Nfacecolors;
+ const double r = *(double*)PyArray_GETPTR2(facecolors, fi, 0);
+ const double g = *(double*)PyArray_GETPTR2(facecolors, fi, 1);
+ const double b = *(double*)PyArray_GETPTR2(facecolors, fi, 2);
+ const double a = *(double*)PyArray_GETPTR2(facecolors, fi, 3);
+ CGContextSetRGBFillColor(cr, r, g, b, a);
+ CGContextDrawPath(cr, kCGPathFillStroke);
+ }
+ else if (Nfacecolors==1)
+ CGContextDrawPath(cr, kCGPathFillStroke);
+ else
+ CGContextStrokePath(cr);
+ }
+
+success:
+ CGContextRestoreGState(cr);
+ if (transforms) free(transforms);
+ Py_DECREF(offsets);
+ Py_DECREF(facecolors);
+ Py_DECREF(edgecolors);
+
 Py_INCREF(Py_None);
 return Py_None;
+
+error:
+ CGContextRestoreGState(cr);
+ if (transforms) free(transforms);
+ Py_XDECREF(offsets);
+ Py_XDECREF(facecolors);
+ Py_XDECREF(edgecolors);
+
+ return NULL;
 }
 
 static PyObject*
-GraphicsContext_stroke (GraphicsContext* self, PyObject* args)
+GraphicsContext_draw_quad_mesh (GraphicsContext* self, PyObject* args)
 {
- PyObject* color;
+ PyObject* master_transform_obj;
+ PyObject* cliprect;
+ PyObject* clippath;
+ PyObject* clippath_transform;
+ int meshWidth;
+ int meshHeight;
+ PyObject* vertices;
+ PyObject* offsets_obj;
+ PyObject* offset_transform_obj;
+ PyObject* facecolors_obj;
+ int antialiased;
+ int showedges;
+
 CGContextRef cr = self->cr;
 
 if (!cr)
@@ -811,35 +1746,219 @@
 return NULL;
 }
 
- if(!PyArg_ParseTuple(args, "O", &color)) return NULL;
+ if(!PyArg_ParseTuple(args, "OOOOiiOOOOii",
+ &master_transform_obj,
+ &cliprect,
+ &clippath,
+ &clippath_transform,
+ &meshWidth,
+ &meshHeight,
+ &vertices,
+ &offsets_obj,
+ &offset_transform_obj,
+ &facecolors_obj,
+ &antialiased,
+ &showedges)) return NULL;
 
- if(color!=Py_None)
+ PyArrayObject* offsets = NULL;
+ PyArrayObject* facecolors = NULL;
+
+ CGAffineTransform transform;
+ CGAffineTransform master_transform;
+ CGAffineTransform offset_transform;
+
+ if (!_convert_affine_transform(master_transform_obj, &master_transform))
+ return NULL;
+ if (!_convert_affine_transform(offset_transform_obj, &offset_transform))
+ return NULL;
+
+ /* clipping */
+
+ if (!_clip(cr, cliprect)) return NULL;
+ if (clippath!=Py_None)
 {
- float r, g, b;
- if(!PyArg_ParseTuple(color, "fff", &r, &g, &b)) return NULL;
- if(self->pattern)
+ if (!_convert_affine_transform(clippath_transform, &transform))
+ return NULL;
+ int n = _draw_path(cr, clippath, transform);
+ if (n==-1) return NULL;
+ else if (n > 0) CGContextClip(cr);
+ }
+
+ PyArrayObject* coordinates;
+ coordinates = (PyArrayObject*)PyArray_FromObject(vertices,
+ NPY_DOUBLE, 3, 3);
+ if (!coordinates ||
+ PyArray_NDIM(coordinates) != 3 || PyArray_DIM(coordinates, 2) != 2)
+ {
+ PyErr_SetString(PyExc_ValueError, "Invalid coordinates array");
+ goto error;
+ }
+
+ /* ------------------- Check offsets array ---------------------------- */
+
+ offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj, NPY_DOUBLE, 0, 2);
+ if (!offsets ||
+ (PyArray_NDIM(offsets)==2 && PyArray_DIM(offsets, 1)!=2) ||
+ (PyArray_NDIM(offsets)==1 && PyArray_DIM(offsets, 0)!=0))
+ {
+ PyErr_SetString(PyExc_ValueError, "Offsets array must be Nx2");
+ goto error;
+ }
+
+ /* ------------------- Check facecolors array ------------------------- */
+
+ facecolors = (PyArrayObject*)PyArray_FromObject(facecolors_obj,
+ NPY_DOUBLE, 1, 2);
+ if (!facecolors ||
+ (PyArray_NDIM(facecolors)==1 && PyArray_DIM(facecolors, 0)!=0) ||
+ (PyArray_NDIM(facecolors)==2 && PyArray_DIM(facecolors, 1)!=4))
+ {
+ PyErr_SetString(PyExc_ValueError, "Facecolors must by a Nx4 numpy array or empty");
+ goto error;
+ }
+
+ /* ------------------- Check the other arguments ---------------------- */
+
+ size_t Noffsets = (size_t) PyArray_DIM(offsets, 0);
+ size_t Npaths = meshWidth * meshHeight;
+ size_t Nfacecolors = (size_t) PyArray_DIM(facecolors, 0);
+ if ((Nfacecolors == 0 && !showedges) || Npaths == 0)
+ {
+ /* Nothing to do here */
+ goto success;
+ }
+
+ size_t i = 0;
+ size_t iw = 0;
+ size_t ih = 0;
+
+ CGPoint offset;
+
+ /* Preset graphics context properties if possible */
+ if (antialiased) CGContextSetShouldAntialias(cr, true);
+ else CGContextSetShouldAntialias(cr, false);
+
+ CGContextSetLineWidth(cr, 0.0);
+
+ if (Nfacecolors==1)
+ {
+ const double r = *(double*)PyArray_GETPTR2(facecolors, 0, 0);
+ const double g = *(double*)PyArray_GETPTR2(facecolors, 0, 1);
+ const double b = *(double*)PyArray_GETPTR2(facecolors, 0, 2);
+ const double a = *(double*)PyArray_GETPTR2(facecolors, 0, 3);
+ CGContextSetRGBFillColor(cr, r, g, b, a);
+ if (antialiased && !showedges)
 {
- float components[4];
- components[0] = r;
- components[1] = g;
- components[2] = b;
- components[3] = 1.0;
- CGContextSetFillPattern(cr, self->pattern, components);
- CGPatternRelease (self->pattern);
- self->pattern = nil;
+ CGContextSetRGBStrokeColor(cr, r, g, b, a);
 }
- else CGContextSetRGBFillColor(cr, r, g, b, 1.0);
- CGContextDrawPath(cr, kCGPathFillStroke);
 }
- else CGContextStrokePath(cr);
 
+ if (showedges)
+ {
+ CGContextSetRGBStrokeColor(cr, 0, 0, 0, 1);
+ }
+
+ for (ih = 0; ih < meshHeight; ih++)
+ {
+ for (iw = 0; iw < meshWidth; iw++, i++)
+ {
+
+ transform = master_transform;
+
+ if (Noffsets)
+ {
+ offset.x = (CGFloat) (*(double*)PyArray_GETPTR2(offsets, i % Noffsets, 0));
+ offset.y = (CGFloat) (*(double*)PyArray_GETPTR2(offsets, i % Noffsets, 1));
+ offset = CGPointApplyAffineTransform(offset, offset_transform);
+ transform.tx += offset.x;
+ transform.ty += offset.y;
+ }
+
+ CGPoint p;
+ CGPoint points[4];
+
+ p.x = (CGFloat)(*(double*)PyArray_GETPTR3(coordinates, ih, iw, 0));
+ p.y = (CGFloat)(*(double*)PyArray_GETPTR3(coordinates, ih, iw, 1));
+ if (isnan(p.x) || isnan(p.y)) continue;
+ points[0] = CGPointApplyAffineTransform(p, transform);
+
+ p.x = (CGFloat)(*(double*)PyArray_GETPTR3(coordinates, ih, iw+1, 0));
+ p.y = (CGFloat)(*(double*)PyArray_GETPTR3(coordinates, ih, iw+1, 1));
+ if (isnan(p.x) || isnan(p.y)) continue;
+ points[1] = CGPointApplyAffineTransform(p, transform);
+
+ p.x = (CGFloat)(*(double*)PyArray_GETPTR3(coordinates, ih+1, iw+1, 0));
+ p.y = (CGFloat)(*(double*)PyArray_GETPTR3(coordinates, ih+1, iw+1, 1));
+ if (isnan(p.x) || isnan(p.y)) continue;
+ points[2] = CGPointApplyAffineTransform(p, transform);
+
+ p.x = (CGFloat)(*(double*)PyArray_GETPTR3(coordinates, ih+1, iw, 0));
+ p.y = (CGFloat)(*(double*)PyArray_GETPTR3(coordinates, ih+1, iw, 1));
+ if (isnan(p.x) || isnan(p.y)) continue;
+ points[3] = CGPointApplyAffineTransform(p, transform);
+
+ CGContextMoveToPoint(cr, points[3].x, points[3].y);
+ CGContextAddLines(cr, points, 4);
+
+ if (Nfacecolors > 1)
+ {
+ npy_intp fi = i % Nfacecolors;
+ const double r = *(double*)PyArray_GETPTR2(facecolors, fi, 0);
+ const double g = *(double*)PyArray_GETPTR2(facecolors, fi, 1);
+ const double b = *(double*)PyArray_GETPTR2(facecolors, fi, 2);
+ const double a = *(double*)PyArray_GETPTR2(facecolors, fi, 3);
+ CGContextSetRGBFillColor(cr, r, g, b, a);
+ if (showedges)
+ {
+ CGContextDrawPath(cr, kCGPathFillStroke);
+ }
+ else if (antialiased)
+ {
+ CGContextSetRGBStrokeColor(cr, r, g, b, a);
+ CGContextDrawPath(cr, kCGPathFillStroke);
+ }
+ else
+ {
+ CGContextFillPath(cr);
+ }
+ }
+ else if (Nfacecolors==1)
+ {
+ if (showedges || antialiased)
+ {
+ CGContextDrawPath(cr, kCGPathFillStroke);
+ }
+ else
+ {
+ CGContextFillPath(cr);
+ }
+ }
+ else if (showedges)
+ {
+ CGContextStrokePath(cr);
+ }
+ }
+ }
+
+success:
+ Py_DECREF(offsets);
+ Py_DECREF(facecolors);
+ Py_DECREF(coordinates);
+
 Py_INCREF(Py_None);
 return Py_None;
+
+error:
+ Py_XDECREF(offsets);
+ Py_XDECREF(facecolors);
+ Py_XDECREF(coordinates);
+ return NULL;
 }
 
+
 static ATSFontRef
 setfont(CGContextRef cr, PyObject* family, float size, const char weight[],
- const char style[])
+ const ch...
 
[truncated message content]
From: <md...@us...> - 2008年12月18日 13:41:39
Revision: 6661
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6661&view=rev
Author: mdboom
Date: 2008年12月18日 13:41:35 +0000 (2008年12月18日)
Log Message:
-----------
Fix bug where a line with NULL data limits prevents subsequent data limits from calculating correctly
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/src/_path.cpp
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月18日 12:10:51 UTC (rev 6660)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月18日 13:41:35 UTC (rev 6661)
@@ -1,3 +1,8 @@
+2008年12月18日 Fix bug where a line with NULL data limits prevents
+ subsequent data limits from calculating correctly - MGD
+
+2008年12月17日 Major documentation generator changes - MGD
+
 2008年12月17日 Applied macosx backend patch with support for path
 collections, quadmesh, etc... - JDH
 
@@ -3,4 +8,5 @@
 2008年12月17日 fix dpi-dependent behavior of text bbox and arrow in annotate
 -JJL
+
 2008年12月16日 Another attempt to fix dpi-dependent behavior of Legend. -JJL
 
Modified: branches/v0_98_5_maint/src/_path.cpp
===================================================================
--- branches/v0_98_5_maint/src/_path.cpp	2008年12月18日 12:10:51 UTC (rev 6660)
+++ branches/v0_98_5_maint/src/_path.cpp	2008年12月18日 13:41:35 UTC (rev 6661)
@@ -403,10 +403,25 @@
 }
 else
 {
- extents_data[0] = std::min(x0, x1);
- extents_data[1] = std::min(y0, y1);
- extents_data[2] = std::max(x0, x1);
- extents_data[3] = std::max(y0, y1);
+ if (x0 > x1)
+ {
+ extents_data[0] = std::numeric_limits<double>::infinity();
+ extents_data[2] = -std::numeric_limits<double>::infinity();
+ }
+ else
+ {
+ extents_data[0] = x0;
+ extents_data[2] = x1;
+ }
+ if (y0 > y1) {
+ extents_data[1] = std::numeric_limits<double>::infinity();
+ extents_data[3] = -std::numeric_limits<double>::infinity();
+ }
+ else
+ {
+ extents_data[1] = y0;
+ extents_data[3] = y1;
+ }
 minpos_data[0] = xm;
 minpos_data[1] = ym;
 }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jd...@us...> - 2008年12月18日 16:29:54
Revision: 6665
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6665&view=rev
Author: jdh2358
Date: 2008年12月18日 16:29:51 +0000 (2008年12月18日)
Log Message:
-----------
removed some configobj and traits detritus
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/setup.py
 branches/v0_98_5_maint/setupext.py
Removed Paths:
-------------
 branches/v0_98_5_maint/lib/configobj.py
 branches/v0_98_5_maint/lib/enthought/
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月18日 15:38:33 UTC (rev 6664)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月18日 16:29:51 UTC (rev 6665)
@@ -1,3 +1,4 @@
+
 2008年12月18日 Fix bug where a line with NULL data limits prevents
 subsequent data limits from calculating correctly - MGD
 
Deleted: branches/v0_98_5_maint/lib/configobj.py
===================================================================
--- branches/v0_98_5_maint/lib/configobj.py	2008年12月18日 15:38:33 UTC (rev 6664)
+++ branches/v0_98_5_maint/lib/configobj.py	2008年12月18日 16:29:51 UTC (rev 6665)
@@ -1,2279 +0,0 @@
-# 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-mpl'
-
-__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 marker,
- # so it should be a valid ``key = value`` line
- mat = self._keyword.match(line)
- if mat is None:
- # it neither matched as a keyword
- # or a section marker
- self._handle_error(
- 'Invalid line at line "%s".',
- ParseError, infile, cur_index)
- else:
- # is a keyword value
- # value will include any inline comment
- (indent, key, value) = mat.groups()
- if indent and (self.indent_type is None):
- self.indent_type = indent
- # check for a multiline value
- if value[:3] in ['"""', "'''"]:
- try:
- (value, comment, cur_index) = self._multiline(
- value, infile, cur_index, maxline)
- except SyntaxError:
- self._handle_error(
- 'Parse error in value at line %s.',
- ParseError, infile, cur_index)
- continue
- else:
- if self.unrepr:
- comment = ''
- try:
- value = unrepr(value)
- except Exception, e:
- if type(e) == UnknownType:
- msg = 'Unknown name or type in value at line %s.'
- else:
- msg = 'Parse error in value at line %s.'
- self._handle_error(msg, UnreprError, infile,
- cur_index)
- continue
- else:
- if self.unrepr:
- comment = ''
- try:
- value = unrepr(value)
- except Exception, e:
- if isinstance(e, UnknownType):
- msg = 'Unknown name or type in value at line %s.'
- else:
- msg = 'Parse error in value at line %s.'
- self._handle_error(msg, UnreprError, infile,
- cur_index)
- continue
- else:
- # extract comment and lists
- try:
- (value, comment) = self._handle_value(value)
- except SyntaxError:
- self._handle_error(
- 'Parse error in value at line %s.',
- ParseError, infile, cur_index)
- continue
- #
- key = self._unquote(key)
- if this_section.has_key(key):
- self._handle_error(
- 'Duplicate keyword name at line %s.',
- DuplicateError, infile, cur_index)
- continue
- # add the key.
- # we set unrepr because if we have got this far we will never
- # be creating a new section
- this_section.__setitem__(key, value, unrepr=True)
- this_section.inline_comments[key] = comment
- this_section.comments[key] = comment_list
- continue
- #
- if self.indent_type is None:
- # no indentation used, set the type accordingly
- self.indent_type = ''
- #
- if self._terminated:
- comment_list.append('')
- # preserve the final comment
- if not self and not self.initial_comment:
- self.initial_comment = comment_list
- elif not reset_comment:
- self.final_comment = comment_list
- self.list_values = temp_list_values
-
- def _match_depth(self, sect, depth):
- """
- Given a section and a depth level, walk back through the sections
- parents to see if the depth level matches a previous section.
- 
- Return a reference to the right section,
- or raise a SyntaxError.
- """
- while depth < sect.depth:
- if sect is sect.parent:
- # we've reached the top level already
- raise SyntaxError
- sect = sect.parent
- if sect.depth == depth:
- return sect
- # shouldn't get here
- raise SyntaxError
-
- def _handle_error(self, text, ErrorClass, infile, cur_index):
- """
- Handle an error according to the error settings.
- 
- Either raise the error or store it.
- The error will have occured at ``cur_index``
- """
- line = infile[cur_index]
- cur_index += 1
- message = text % cur_index
- error = ErrorClass(message, cur_index, line)
- if self.raise_errors:
- # raise the error - parsing stops here
- raise error
- # store the error
- # reraise when parsing has finished
- self._errors.append(error)
-
- def _unquote(self, value):
- """Return an unquoted version of a value"""
- if (value[0] == value[-1]) and (value[0] in ('"', "'")):
- value = value[1:-1]
- return value
-
- def _quote(self, value, multiline=True):
- """
- Return a safely quoted version of a value.
- 
- Raise a ConfigObjError if the value cannot be safely quoted.
- If multiline is ``True`` (default) then use triple quotes
- if necessary.
- 
- Don't quote values that don't need it.
- Recursively quote members of a list and return a comma joined list.
- Multiline is ``False`` for lists.
- Obey list syntax for empty and single member lists.
- 
- If ``list_values=False`` then the value is only quoted if it contains
- a ...
 
[truncated message content]
From: <jd...@us...> - 2008年12月18日 16:31:49
Revision: 6666
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6666&view=rev
Author: jdh2358
Date: 2008年12月18日 16:31:44 +0000 (2008年12月18日)
Log Message:
-----------
tagging release 0.98.5.2
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/doc/api/api_changes.rst
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月18日 16:29:51 UTC (rev 6665)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月18日 16:31:44 UTC (rev 6666)
@@ -1,4 +1,8 @@
+=======================================================================
+Release 0.98.5.2 at r6665
 
+2008年12月18日 Removed configobj and experimental traits - JDH
+
 2008年12月18日 Fix bug where a line with NULL data limits prevents
 subsequent data limits from calculating correctly - MGD
 
Modified: branches/v0_98_5_maint/doc/api/api_changes.rst
===================================================================
--- branches/v0_98_5_maint/doc/api/api_changes.rst	2008年12月18日 16:29:51 UTC (rev 6665)
+++ branches/v0_98_5_maint/doc/api/api_changes.rst	2008年12月18日 16:31:44 UTC (rev 6666)
@@ -8,6 +8,7 @@
 
 Changes for 0.98.x
 ==================
+* Removed the configobj and experiemtnal traits rc support
 
 * Modified :func:`matplotlib.mlab.psd`, :func:`matplotlib.mlab.csd`,
 :func:`matplotlib.mlab.cohere`, and :func:`matplotlib.mlab.specgram`
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2008年12月18日 19:07:12
Revision: 6672
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6672&view=rev
Author: mdboom
Date: 2008年12月18日 19:07:08 +0000 (2008年12月18日)
Log Message:
-----------
Fix how example files are added to the build. Saves about 1MB in html output.
Modified Paths:
--------------
 branches/v0_98_5_maint/doc/conf.py
 branches/v0_98_5_maint/doc/make.py
 branches/v0_98_5_maint/doc/sphinxext/plot_directive.py
 branches/v0_98_5_maint/lib/matplotlib/pyplot.py
Added Paths:
-----------
 branches/v0_98_5_maint/doc/sphinxext/gen_rst.py
Modified: branches/v0_98_5_maint/doc/conf.py
===================================================================
--- branches/v0_98_5_maint/doc/conf.py	2008年12月18日 17:41:11 UTC (rev 6671)
+++ branches/v0_98_5_maint/doc/conf.py	2008年12月18日 19:07:08 UTC (rev 6672)
@@ -29,7 +29,7 @@
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
 extensions = ['mathmpl', 'math_symbol_table', 'sphinx.ext.autodoc',
 'only_directives', 'plot_directive', 'inheritance_diagram',
- 'gen_gallery']
+ 'gen_gallery', 'gen_rst']
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
Modified: branches/v0_98_5_maint/doc/make.py
===================================================================
--- branches/v0_98_5_maint/doc/make.py	2008年12月18日 17:41:11 UTC (rev 6671)
+++ branches/v0_98_5_maint/doc/make.py	2008年12月18日 19:07:08 UTC (rev 6672)
@@ -34,15 +34,12 @@
 
 def html():
 check_build()
- if not os.path.exists('examples/index.rst'):
- examples()
 shutil.copy('../lib/matplotlib/mpl-data/matplotlibrc', '_static/matplotlibrc')
- #figs()
 if small_docs:
 options = "-D plot_formats=\"['png']\""
 else:
 options = ''
- if os.system('sphinx-build %s -b html -d build/doctrees . build/html' % options):
+ if os.system('sphinx-build %s -P -b html -d build/doctrees . build/html' % options):
 raise SystemExit("Building HTML failed.")
 
 figures_dest_path = 'build/html/pyplots'
Copied: branches/v0_98_5_maint/doc/sphinxext/gen_rst.py (from rev 6660, branches/v0_98_5_maint/doc/examples/gen_rst.py)
===================================================================
--- branches/v0_98_5_maint/doc/sphinxext/gen_rst.py	 (rev 0)
+++ branches/v0_98_5_maint/doc/sphinxext/gen_rst.py	2008年12月18日 19:07:08 UTC (rev 6672)
@@ -0,0 +1,155 @@
+"""
+generate the rst files for the examples by iterating over the pylab examples
+"""
+import os, glob
+
+import os
+import re
+import sys
+fileList = []
+
+def out_of_date(original, derived):
+ """
+ Returns True if derivative is out-of-date wrt original,
+ both of which are full file paths.
+
+ TODO: this check isn't adequate in some cases. Eg, if we discover
+ a bug when building the examples, the original and derived will be
+ unchanged but we still want to force a rebuild.
+ """
+ return (not os.path.exists(derived) or
+ os.stat(derived).st_mtime < os.stat(original).st_mtime)
+
+noplot_regex = re.compile(r"#\s*-\*-\s*noplot\s*-\*-")
+
+def generate_example_rst(app):
+ rootdir = os.path.join(app.builder.srcdir, 'mpl_examples')
+ exampledir = os.path.join(app.builder.srcdir, 'examples')
+ if not os.path.exists(exampledir):
+ os.makedirs(exampledir)
+
+ datad = {}
+ for root, subFolders, files in os.walk(rootdir):
+ for fname in files:
+ if ( fname.startswith('.') or fname.startswith('#') or fname.startswith('_') or
+ fname.find('.svn')>=0 or not fname.endswith('.py') ):
+ continue
+
+ fullpath = os.path.join(root,fname)
+ contents = file(fullpath).read()
+ # indent
+ relpath = os.path.split(root)[-1]
+ datad.setdefault(relpath, []).append((fullpath, fname, contents))
+
+ subdirs = datad.keys()
+ subdirs.sort()
+
+ fhindex = file(os.path.join(exampledir, 'index.rst'), 'w')
+ fhindex.write("""\
+.. _examples-index:
+
+####################
+Matplotlib Examples
+####################
+
+.. htmlonly::
+
+ :Release: |version|
+ :Date: |today|
+
+.. toctree::
+ :maxdepth: 2
+
+""")
+
+ for subdir in subdirs:
+ rstdir = os.path.join(exampledir, subdir)
+ if not os.path.exists(rstdir):
+ os.makedirs(rstdir)
+
+ outputdir = os.path.join(app.builder.outdir, 'examples')
+ if not os.path.exists(outputdir):
+ os.makedirs(outputdir)
+
+ outputdir = os.path.join(outputdir, subdir)
+ if not os.path.exists(outputdir):
+ os.makedirs(outputdir)
+
+ subdirIndexFile = os.path.join(rstdir, 'index.rst')
+ fhsubdirIndex = file(subdirIndexFile, 'w')
+ fhindex.write(' %s/index.rst\n\n'%subdir)
+
+ fhsubdirIndex.write("""\
+.. _%s-examples-index:
+
+##############################################
+%s Examples
+##############################################
+
+.. htmlonly::
+
+ :Release: |version|
+ :Date: |today|
+
+.. toctree::
+ :maxdepth: 1
+
+"""%(subdir, subdir))
+
+ print subdir
+
+ data = datad[subdir]
+ data.sort()
+
+ for fullpath, fname, contents in data:
+ basename, ext = os.path.splitext(fname)
+ outputfile = os.path.join(outputdir, fname)
+ #thumbfile = os.path.join(thumb_dir, '%s.png'%basename)
+ #print ' static_dir=%s, basename=%s, fullpath=%s, fname=%s, thumb_dir=%s, thumbfile=%s'%(static_dir, basename, fullpath, fname, thumb_dir, thumbfile)
+
+ rstfile = '%s.rst'%basename
+ outrstfile = os.path.join(rstdir, rstfile)
+
+ fhsubdirIndex.write(' %s\n'%rstfile)
+
+ if (not out_of_date(fullpath, outputfile) and
+ not out_of_date(fullpath, outrstfile)):
+ continue
+
+ print ' %s'%fname
+
+ fh = file(outrstfile, 'w')
+ fh.write('.. _%s-%s:\n\n'%(subdir, basename))
+ title = '%s example code: %s'%(subdir, fname)
+ #title = '<img src=%s> %s example code: %s'%(thumbfile, subdir, fname)
+
+
+ fh.write(title + '\n')
+ fh.write('='*len(title) + '\n\n')
+
+ do_plot = (subdir in ('api',
+ 'pylab_examples',
+ 'units') and
+ not noplot_regex.search(contents))
+
+ if do_plot:
+ fh.write("\n\n.. plot:: %s\n\n::\n\n" % fullpath)
+ else:
+ fh.write("[`source code <%s>`_]\n\n::\n\n" % fname)
+ fhstatic = file(outputfile, 'w')
+ fhstatic.write(contents)
+ fhstatic.close()
+
+ # indent the contents
+ contents = '\n'.join([' %s'%row.rstrip() for row in contents.split('\n')])
+ fh.write(contents)
+
+ fh.write('\n\nKeywords: python, matplotlib, pylab, example, codex (see :ref:`how-to-search-examples`)')
+ fh.close()
+
+ fhsubdirIndex.close()
+
+ fhindex.close()
+
+def setup(app):
+ app.connect('builder-inited', generate_example_rst)
Property changes on: branches/v0_98_5_maint/doc/sphinxext/gen_rst.py
___________________________________________________________________
Added: svn:mergeinfo
 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771
Modified: branches/v0_98_5_maint/doc/sphinxext/plot_directive.py
===================================================================
--- branches/v0_98_5_maint/doc/sphinxext/plot_directive.py	2008年12月18日 17:41:11 UTC (rev 6671)
+++ branches/v0_98_5_maint/doc/sphinxext/plot_directive.py	2008年12月18日 19:07:08 UTC (rev 6672)
@@ -34,6 +34,41 @@
 import matplotlib.image as image
 from matplotlib import _pylab_helpers
 
+if hasattr(os.path, 'relpath'):
+ relpath = os.path.relpath
+else:
+ def relpath(target, base=os.curdir):
+ """
+ Return a relative path to the target from either the current dir or an optional base dir.
+ Base can be a directory specified either as absolute or relative to current dir.
+ """
+
+ if not os.path.exists(target):
+ raise OSError, 'Target does not exist: '+target
+
+ if not os.path.isdir(base):
+ raise OSError, 'Base is not a directory or does not exist: '+base
+
+ base_list = (os.path.abspath(base)).split(os.sep)
+ target_list = (os.path.abspath(target)).split(os.sep)
+
+ # On the windows platform the target may be on a completely different drive from the base.
+ if os.name in ['nt','dos','os2'] and base_list[0] <> target_list[0]:
+ raise OSError, 'Target is on a different drive to base. Target: '+target_list[0].upper()+', base: '+base_list[0].upper()
+
+ # Starting from the filepath root, work out how much of the filepath is
+ # shared by base and target.
+ for i in range(min(len(base_list), len(target_list))):
+ if base_list[i] <> target_list[i]: break
+ else:
+ # If we broke out of the loop, i is pointing to the first differing path elements.
+ # If we didn't break out of the loop, i is pointing to identical path elements.
+ # Increment i so that in all cases it points to the first differing path elements.
+ i+=1
+
+ rel_list = [os.pardir] * (len(base_list)-i) + target_list[i:]
+ return os.path.join(*rel_list)
+
 def write_char(s):
 sys.stdout.write(s)
 sys.stdout.flush()
@@ -186,6 +221,7 @@
 reference = directives.uri(arguments[0])
 basedir, fname = os.path.split(reference)
 basename, ext = os.path.splitext(fname)
+ basedir = relpath(basedir, setup.app.builder.srcdir)
 
 # Get the directory of the rst file, and determine the relative
 # path from the resulting html file to the plot_directive links
Modified: branches/v0_98_5_maint/lib/matplotlib/pyplot.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/pyplot.py	2008年12月18日 17:41:11 UTC (rev 6671)
+++ branches/v0_98_5_maint/lib/matplotlib/pyplot.py	2008年12月18日 19:07:08 UTC (rev 6672)
@@ -1138,9 +1138,9 @@
 def plotting():
 """
 Plotting commands
- ============ =================================================
+ =============== =========================================================
 Command Description
- ========= =================================================
+ =============== =========================================================
 axes Create a new axes
 axis Set or return the current axis limits
 bar make a bar chart
@@ -1193,7 +1193,7 @@
 title add a title to the current axes
 xlabel add an xlabel to the current axes
 ylabel add a ylabel to the current axes
- ============ =================================================
+ =============== =========================================================
 
 The following commands will set the default colormap accordingly:
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <lee...@us...> - 2008年12月19日 21:24:41
Revision: 6685
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6685&view=rev
Author: leejjoon
Date: 2008年12月19日 21:24:32 +0000 (2008年12月19日)
Log Message:
-----------
update legend-related document
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/doc/api/api_changes.rst
 branches/v0_98_5_maint/lib/matplotlib/__init__.py
 branches/v0_98_5_maint/lib/matplotlib/axes.py
 branches/v0_98_5_maint/lib/matplotlib/legend.py
 branches/v0_98_5_maint/lib/matplotlib/mpl-data/matplotlib.conf.template
 branches/v0_98_5_maint/lib/matplotlib/rcsetup.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月19日 20:27:18 UTC (rev 6684)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月19日 21:24:32 UTC (rev 6685)
@@ -1,3 +1,6 @@
+2008年12月19日 Update Axes.legend documnetation. /api/api_changes.rst is also 
+ updated to describe chages in keyword parameters. 
+ Issue a warning if old keyword parameters are used. - JJL
 
 =======================================================================
 Re-Released 0.98.5.2 at r6679
Modified: branches/v0_98_5_maint/doc/api/api_changes.rst
===================================================================
--- branches/v0_98_5_maint/doc/api/api_changes.rst	2008年12月19日 20:27:18 UTC (rev 6684)
+++ branches/v0_98_5_maint/doc/api/api_changes.rst	2008年12月19日 21:24:32 UTC (rev 6685)
@@ -8,6 +8,22 @@
 
 Changes for 0.98.x
 ==================
+* Following keyword parameters for :class:`matplotlib.label.Label` are now
+ deprecated and new set of parameters are introduced. The new parameters 
+ are given as a fraction of the font-size. Also, *scatteryoffsets*, 
+ *fancybox* and *columnspacing* are added as keyword parameters.
+
+ ================ ================
+ Deprecated New
+ ================ ================
+ pad borderpad 
+ labelsep labelspacing 
+ handlelen handlelength 
+ handlestextsep handletextpad 
+ axespad	 borderaxespad 
+ ================ ================ 
+
+
 * Removed the configobj and experiemtnal traits rc support
 
 * Modified :func:`matplotlib.mlab.psd`, :func:`matplotlib.mlab.csd`,
Modified: branches/v0_98_5_maint/lib/matplotlib/__init__.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/__init__.py	2008年12月19日 20:27:18 UTC (rev 6684)
+++ branches/v0_98_5_maint/lib/matplotlib/__init__.py	2008年12月19日 21:24:32 UTC (rev 6685)
@@ -582,7 +582,15 @@
 'tick.size' : 'tick.major.size',
 }
 
+_deprecated_ignore_map = {
+ 'legend.pad' : 'legend.borderpad',
+ 'legend.labelsep' : 'legend.labelspacing',
+ 'legend.handlelen' : 'legend.handlelength',
+ 'legend.handletextsep' : 'legend.handletextpad',
+ 'legend.axespad' : 'legend.borderaxespad',
+ }
 
+
 class RcParams(dict):
 
 """
@@ -602,6 +610,10 @@
 warnings.warn('%s is deprecated in matplotlibrc. Use %s \
 instead.'% (key, alt))
 key = alt
+ elif key in _deprecated_ignore_map:
+ alt = _deprecated_ignore_map[key]
+ warnings.warn('%s is deprecated. Use %s instead.'% (key, alt))
+ return
 cval = self.validate[key](val)
 dict.__setitem__(self, key, cval)
 except KeyError:
@@ -665,6 +677,9 @@
 except Exception, msg:
 warnings.warn('Bad val "%s" on line #%d\n\t"%s"\n\tin file \
 "%s"\n\t%s' % (val, cnt, line, fname, msg))
+ elif key in _deprecated_ignore_map:
+ warnings.warn('%s is deprecated. Update your matplotlibrc to use %s instead.'% (key, _deprecated_ignore_map[key]))
+ 
 else:
 print >> sys.stderr, """
 Bad key "%s" on line %d in
Modified: branches/v0_98_5_maint/lib/matplotlib/axes.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/axes.py	2008年12月19日 20:27:18 UTC (rev 6684)
+++ branches/v0_98_5_maint/lib/matplotlib/axes.py	2008年12月19日 21:24:32 UTC (rev 6685)
@@ -3728,10 +3728,6 @@
 A :class:`matplotlib.font_manager.FontProperties`
 instance, or *None* to use rc settings.
 
- *pad*: [ None | scalar ]
- The fractional whitespace inside the legend border, between 0 and 1.
- If *None*, use rc settings.
-
 *markerscale*: [ None | scalar ]
 The relative size of legend markers vs. original. If *None*, use rc
 settings.
@@ -3739,21 +3735,21 @@
 *shadow*: [ None | False | True ]
 If *True*, draw a shadow behind legend. If *None*, use rc settings.
 
- *labelsep*: [ None | scalar ]
- The vertical space between the legend entries. If *None*, use rc
- settings.
+ Padding and spacing between various elements use following keywords
+ parameters. The dimensions of these values are given as a fraction
+ of the fontsize. Values from rcParams will be used if None.
 
- *handlelen*: [ None | scalar ]
- The length of the legend lines. If *None*, use rc settings.
+ ================ ==================================================================
+ Keyword Description
+ ================ ==================================================================
+ borderpad the fractional whitespace inside the legend border
+ labelspacing the vertical space between the legend entries
+ handlelength the length of the legend handles
+ handletextpad the pad between the legend handle and text
+ borderaxespad the pad between the axes and legend border
+ columnspacing the spacing between columns
+ ================ ==================================================================
 
- *handletextsep*: [ None | scalar ]
- The space between the legend line and legend text. If *None*, use rc
- settings.
-
- *axespad*: [ None | scalar ]
- The border between the axes and legend edge. If *None*, use rc
- settings.
-
 **Example:**
 
 .. plot:: mpl_examples/api/legend_demo.py
Modified: branches/v0_98_5_maint/lib/matplotlib/legend.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/legend.py	2008年12月19日 20:27:18 UTC (rev 6684)
+++ branches/v0_98_5_maint/lib/matplotlib/legend.py	2008年12月19日 21:24:32 UTC (rev 6685)
@@ -98,7 +98,7 @@
 handletextsep = None, # deprecated; use handletextpad
 axespad = None, # deprecated; use borderaxespad
 
- # spacing & pad defined as a fractionof the font-size
+ # spacing & pad defined as a fraction of the font-size
 borderpad = None, # the whitespace inside the legend border
 labelspacing=None, #the vertical space between the legend entries
 handlelength=None, # the length of the legend handles
Modified: branches/v0_98_5_maint/lib/matplotlib/mpl-data/matplotlib.conf.template
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/mpl-data/matplotlib.conf.template	2008年12月19日 20:27:18 UTC (rev 6684)
+++ branches/v0_98_5_maint/lib/matplotlib/mpl-data/matplotlib.conf.template	2008年12月19日 21:24:32 UTC (rev 6685)
@@ -233,19 +233,11 @@
 origin = 'upper'
 
 [legend]
- # a float
- axespad = 0.02
 # a float or 'xx-small' or 'x-small' or 'small' or 'medium' or 'large' or
 # 'x-large' or 'xx-large'
 fontsize = 'medium'
- # a float
- handlelen = 0.050000000000000003
- # a float
- handletextsep = 0.02
 # a boolean
 isaxes = True
- # a float
- labelsep = 0.01
 # 'best' or 'upper right' or 'upper left' or 'lower left' or 'lower right'
 # or 'right' or 'center left' or 'center right' or 'lower center' or
 # 'upper center' or 'center'
@@ -254,11 +246,22 @@
 markerscale = 1.0
 # an integer
 numpoints = 3
- # a float
- pad = 0.20000000000000001
 # a boolean
 shadow = False
+ # float
+ borderpad = 0.4
+ # float
+ labelspacing = 0.5
+ # float
+ handlelength = 2.
+ # float
+ handletextpad = 0.8
+ # float
+ borderaxespad = 0.5
+ # float
+ columnspacing = 2.
 
+
 [lines]
 # a boolean
 antialiased = True
Modified: branches/v0_98_5_maint/lib/matplotlib/rcsetup.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/rcsetup.py	2008年12月19日 20:27:18 UTC (rev 6684)
+++ branches/v0_98_5_maint/lib/matplotlib/rcsetup.py	2008年12月19日 21:24:32 UTC (rev 6685)
@@ -422,18 +422,12 @@
 'legend.isaxes' : [True,validate_bool], # this option is internally ignored - it never served any useful purpose
 'legend.numpoints' : [2, validate_int], # the number of points in the legend line
 'legend.fontsize' : ['large', validate_fontsize],
- 'legend.pad' : [0, validate_float], # was 0.2, deprecated; the fractional whitespace inside the legend border
- 'legend.borderpad' : [0.4, validate_float], # units are fontsize
 'legend.markerscale' : [1.0, validate_float], # the relative size of legend markers vs. original
-
- # the following dimensions are in axes coords
- 'legend.labelsep' : [0.010, validate_float], # the vertical space between the legend entries
- 'legend.handlelen' : [0.05, validate_float], # the length of the legend lines
- 'legend.handletextsep' : [0.02, validate_float], # the space between the legend line and legend text
- 'legend.axespad' : [0.02, validate_float], # the border between the axes and legend edge
 'legend.shadow' : [False, validate_bool],
 
 
+ # the following dimensions are in fraction of the font size
+ 'legend.borderpad' : [0.4, validate_float], # units are fontsize
 'legend.labelspacing' : [0.5, validate_float], # the vertical space between the legend entries
 'legend.handlelength' : [2., validate_float], # the length of the legend lines
 'legend.handletextpad' : [.8, validate_float], # the space between the legend line and legend text
@@ -443,11 +437,6 @@
 
 'legend.markerscale' : [1.0, validate_float], # the relative size of legend markers vs. original
 
- # the following dimensions are in axes coords
- 'legend.labelsep' : [0.010, validate_float], # the vertical space between the legend entries
- 'legend.handlelen' : [0.05, validate_float], # the length of the legend lines
- 'legend.handletextsep' : [0.02, validate_float], # the space between the legend line and legend text
- 'legend.axespad' : [0.5, validate_float], # the border between the axes and legend edge
 'legend.shadow' : [False, validate_bool],
 
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <lee...@us...> - 2008年12月21日 03:46:09
Revision: 6688
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6688&view=rev
Author: leejjoon
Date: 2008年12月21日 03:46:05 +0000 (2008年12月21日)
Log Message:
-----------
fix hatch bug in pdf backend
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/examples/pylab_examples/hatch_demo.py
 branches/v0_98_5_maint/lib/matplotlib/backends/backend_pdf.py
 branches/v0_98_5_maint/lib/matplotlib/patches.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月19日 22:48:11 UTC (rev 6687)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月21日 03:46:05 UTC (rev 6688)
@@ -1,5 +1,8 @@
-2008年12月19日 Update Axes.legend documnetation. /api/api_changes.rst is also 
- updated to describe chages in keyword parameters. 
+2008年12月20日 fix the hatch bug in the pdf backend. minor update
+ in docs and example - JJL
+
+2008年12月19日 Update Axes.legend documnetation. /api/api_changes.rst is also
+ updated to describe chages in keyword parameters.
 Issue a warning if old keyword parameters are used. - JJL
 
 =======================================================================
Modified: branches/v0_98_5_maint/examples/pylab_examples/hatch_demo.py
===================================================================
--- branches/v0_98_5_maint/examples/pylab_examples/hatch_demo.py	2008年12月19日 22:48:11 UTC (rev 6687)
+++ branches/v0_98_5_maint/examples/pylab_examples/hatch_demo.py	2008年12月21日 03:46:05 UTC (rev 6688)
@@ -1,18 +1,25 @@
 """
-Hatching (pattern filled polygons) is supported currently on PS
+Hatching (pattern filled polygons) is supported currently on PS and PDF
 backend only. See the set_patch method in
 http://matplotlib.sf.net/matplotlib.patches.html#Patch
 for details
 """
-import matplotlib
-matplotlib.use('PS')
-from pylab import figure
+import matplotlib.pyplot as plt
 
-fig = figure()
-ax = fig.add_subplot(111)
-bars = ax.bar(range(1,5), range(1,5), color='gray', ecolor='black')
+fig = plt.figure()
+ax1 = fig.add_subplot(121)
+ax1.annotate("Hatch is only supported in the PS and PDF backend", (1, 1),
+ xytext=(0, 5),
+ xycoords="axes fraction", textcoords="offset points", ha="center"
+ )
+ax1.bar(range(1,5), range(1,5), color='gray', ecolor='black', hatch="/")
 
+
+ax2 = fig.add_subplot(122)
+bars = ax2.bar(range(1,5), range(1,5), color='gray', ecolor='black')
+
 patterns = ('/', '+', 'x', '\\')
 for bar, pattern in zip(bars, patterns):
 bar.set_hatch(pattern)
-fig.savefig('hatch4.ps')
+
+plt.show()
Modified: branches/v0_98_5_maint/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/backends/backend_pdf.py	2008年12月19日 22:48:11 UTC (rev 6687)
+++ branches/v0_98_5_maint/lib/matplotlib/backends/backend_pdf.py	2008年12月21日 03:46:05 UTC (rev 6688)
@@ -942,7 +942,7 @@
 def hatchPattern(self, lst):
 pattern = self.hatchPatterns.get(lst, None)
 if pattern is not None:
- return pattern[0]
+ return pattern
 
 name = Name('H%d' % self.nextHatch)
 self.nextHatch += 1
@@ -1233,7 +1233,7 @@
 
 def get_image_magnification(self):
 return self.image_dpi/72.0
- 
+
 def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
 # MGDTODO: Support clippath here
 gc = self.new_gc()
Modified: branches/v0_98_5_maint/lib/matplotlib/patches.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/patches.py	2008年12月19日 22:48:11 UTC (rev 6687)
+++ branches/v0_98_5_maint/lib/matplotlib/patches.py	2008年12月21日 03:46:05 UTC (rev 6688)
@@ -247,12 +247,12 @@
 
 CURRENT LIMITATIONS:
 
- 1. Hatching is supported in the PostScript backend only.
+ 1. Hatching is supported in the PostScript and the PDF backend only.
 
 2. Hatching is done with solid black lines of width 0.
 
 
- ACCEPTS: [ '/' | '\\' | '|' | '-' | '#' | 'x' ]
+ ACCEPTS: [ '/' | '\\' | '|' | '-' | '#' | 'x' ] (ps & pdf backend only)
 """
 self._hatch = h
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <lee...@us...> - 2008年12月21日 04:07:28
Revision: 6689
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6689&view=rev
Author: leejjoon
Date: 2008年12月21日 04:07:26 +0000 (2008年12月21日)
Log Message:
-----------
fix dpi dependent offset of Shadow
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/lib/matplotlib/patches.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2008年12月21日 03:46:05 UTC (rev 6688)
+++ branches/v0_98_5_maint/CHANGELOG	2008年12月21日 04:07:26 UTC (rev 6689)
@@ -1,3 +1,5 @@
+2008年12月20日 fix the dpi-dependent offset of Shadow. - JJL
+
 2008年12月20日 fix the hatch bug in the pdf backend. minor update
 in docs and example - JJL
 
Modified: branches/v0_98_5_maint/lib/matplotlib/patches.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/patches.py	2008年12月21日 03:46:05 UTC (rev 6688)
+++ branches/v0_98_5_maint/lib/matplotlib/patches.py	2008年12月21日 04:07:26 UTC (rev 6689)
@@ -372,7 +372,7 @@
 self.patch = patch
 self.props = props
 self._ox, self._oy = ox, oy
- self._update_transform()
+ self._shadow_transform = transforms.Affine2D()
 self._update()
 __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
 
@@ -390,20 +390,20 @@
 self.set_facecolor((r,g,b,0.5))
 self.set_edgecolor((r,g,b,0.5))
 
- def _update_transform(self):
- self._shadow_transform = transforms.Affine2D().translate(self._ox, self._oy)
+ def _update_transform(self, renderer):
+ ox = renderer.points_to_pixels(self._ox)
+ oy = renderer.points_to_pixels(self._oy)
+ self._shadow_transform.clear().translate(ox, oy)
 
 def _get_ox(self):
 return self._ox
 def _set_ox(self, ox):
 self._ox = ox
- self._update_transform()
 
 def _get_oy(self):
 return self._oy
 def _set_oy(self, oy):
 self._oy = oy
- self._update_transform()
 
 def get_path(self):
 return self.patch.get_path()
@@ -411,6 +411,10 @@
 def get_patch_transform(self):
 return self.patch.get_patch_transform() + self._shadow_transform
 
+ def draw(self, renderer):
+ self._update_transform(renderer)
+ Patch.draw(self, renderer)
+
 class Rectangle(Patch):
 """
 Draw a rectangle with lower left at *xy* = (*x*, *y*) with
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <ef...@us...> - 2009年01月06日 19:56:04
Revision: 6752
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6752&view=rev
Author: efiring
Date: 2009年01月06日 19:56:03 +0000 (2009年1月06日)
Log Message:
-----------
Backport 6745, 6746 from trunk
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/lib/matplotlib/contour.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2009年01月06日 19:52:42 UTC (rev 6751)
+++ branches/v0_98_5_maint/CHANGELOG	2009年01月06日 19:56:03 UTC (rev 6752)
@@ -1,3 +1,7 @@
+2009年01月06日 Fix bug in setting of dashed negative contours. - EF
+
+2009年01月06日 Be fault tolerant when len(linestyles)>NLev in contour. - MM
+
 2008年12月20日 fix the dpi-dependent offset of Shadow. - JJL
 
 2008年12月20日 fix the hatch bug in the pdf backend. minor update
Modified: branches/v0_98_5_maint/lib/matplotlib/contour.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/contour.py	2009年01月06日 19:52:42 UTC (rev 6751)
+++ branches/v0_98_5_maint/lib/matplotlib/contour.py	2009年01月06日 19:56:03 UTC (rev 6752)
@@ -535,7 +535,7 @@
 self.levels = kwargs.get('levels', None)
 self.filled = kwargs.get('filled', False)
 self.linewidths = kwargs.get('linewidths', None)
- self.linestyles = kwargs.get('linestyles', 'solid')
+ self.linestyles = kwargs.get('linestyles', None)
 
 self.alpha = kwargs.get('alpha', 1.0)
 self.origin = kwargs.get('origin', None)
@@ -613,9 +613,6 @@
 linestyle = lstyle,
 alpha=self.alpha)
 
- if level < 0.0 and self.monochrome:
- ls = mpl.rcParams['contour.negative_linestyle']
- col.set_linestyle(ls)
 col.set_label('_nolegend_')
 self.ax.add_collection(col, False)
 self.collections.append(col)
@@ -857,11 +854,18 @@
 Nlev = len(self.levels)
 if linestyles is None:
 tlinestyles = ['solid'] * Nlev
+ if self.monochrome:
+ neg_ls = mpl.rcParams['contour.negative_linestyle']
+ for i, lev in enumerate(self.levels):
+ if lev < 0.0:
+ tlinestyles[i] = neg_ls
 else:
 if cbook.is_string_like(linestyles):
 tlinestyles = [linestyles] * Nlev
- elif cbook.iterable(linestyles) and len(linestyles) <= Nlev:
+ elif cbook.iterable(linestyles) and len(linestyles) < Nlev:
 tlinestyles = list(linestyles) * int(np.ceil(Nlev/len(linestyles)))
+ elif cbook.iterable(linestyles): # len(linestyles) >= Nlev
+ tlinestyles = list(linestyles)[:Nlev]
 return tlinestyles
 
 def get_alpha(self):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <ef...@us...> - 2009年01月10日 20:34:36
Revision: 6773
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6773&view=rev
Author: efiring
Date: 2009年01月10日 20:34:28 +0000 (2009年1月10日)
Log Message:
-----------
Fix bug in pan/zoom with log coordinates.
The zoom calculations need to be done in display coordinates.
Thanks to David Trem for bug report.
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/lib/matplotlib/axes.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2009年01月10日 20:05:24 UTC (rev 6772)
+++ branches/v0_98_5_maint/CHANGELOG	2009年01月10日 20:34:28 UTC (rev 6773)
@@ -1,3 +1,5 @@
+2009年01月10日 Fix bug in pan/zoom with log coordinates. - EF
+
 2009年01月06日 Fix bug in setting of dashed negative contours. - EF
 
 2009年01月06日 Be fault tolerant when len(linestyles)>NLev in contour. - MM
Modified: branches/v0_98_5_maint/lib/matplotlib/axes.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/axes.py	2009年01月10日 20:05:24 UTC (rev 6772)
+++ branches/v0_98_5_maint/lib/matplotlib/axes.py	2009年01月10日 20:34:28 UTC (rev 6773)
@@ -2378,10 +2378,11 @@
 dy = dx
 
 alpha = np.power(10.0, (dx, dy))
- start = p.trans_inverse.transform_point((p.x, p.y))
- lim_points = p.lim.get_points()
- result = start + alpha * (lim_points - start)
- result = mtransforms.Bbox(result)
+ start = np.array([p.x, p.y])
+ oldpoints = p.lim.transformed(p.trans)
+ newpoints = start + alpha * (oldpoints - start)
+ result = mtransforms.Bbox(newpoints) \
+ .transformed(p.trans_inverse)
 except OverflowError:
 warnings.warn('Overflow while panning')
 return
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <as...@us...> - 2009年01月16日 18:24:23
Revision: 6792
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6792&view=rev
Author: astraw
Date: 2009年01月16日 18:24:19 +0000 (2009年1月16日)
Log Message:
-----------
Bugfix of C typedef of MPL_Int64 failing on WinXP64
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/src/MPL_isnan.h
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2009年01月16日 18:16:40 UTC (rev 6791)
+++ branches/v0_98_5_maint/CHANGELOG	2009年01月16日 18:24:19 UTC (rev 6792)
@@ -1,3 +1,7 @@
+2009年11月16日 Bugfix of C typedef of MPL_Int64 that was failing on
+ Windows XP 64 bit, as reported by George Goussard on numpy
+ mailing list. - ADS
+
 2009年01月10日 Fix bug in pan/zoom with log coordinates. - EF
 
 2009年01月06日 Fix bug in setting of dashed negative contours. - EF
Modified: branches/v0_98_5_maint/src/MPL_isnan.h
===================================================================
--- branches/v0_98_5_maint/src/MPL_isnan.h	2009年01月16日 18:16:40 UTC (rev 6791)
+++ branches/v0_98_5_maint/src/MPL_isnan.h	2009年01月16日 18:24:19 UTC (rev 6792)
@@ -12,19 +12,6 @@
 #include <stdint.h>
 #endif
 
-#if defined(SIZEOF_VOID_P)
-#if SIZEOF_VOID_P == 8
-#define MPL_LP64 1
-#else
-#define MPL_LP64 0
-#endif
-#else
-#define MPL_LP64 0
-#endif
-
-#if MPL_LP64
-typedef long int MPL_Int64;
-#else /* 32-bit platforms */
 #if defined(_MSC_VER)
 typedef __int64 MPL_Int64;
 #else
@@ -34,7 +21,6 @@
 typedef long long MPL_Int64;
 #endif
 #endif
-#endif
 
 #if !defined(MPL_U64)
 #define MPL_U64(u) (* (MPL_Int64 *) &(u) )
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <ef...@us...> - 2009年01月17日 04:22:10
Revision: 6802
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6802&view=rev
Author: efiring
Date: 2009年01月17日 04:22:07 +0000 (2009年1月17日)
Log Message:
-----------
Make is_string_like work with boost python wrapped sequences
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/lib/matplotlib/cbook.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2009年01月16日 21:24:01 UTC (rev 6801)
+++ branches/v0_98_5_maint/CHANGELOG	2009年01月17日 04:22:07 UTC (rev 6802)
@@ -1,4 +1,7 @@
-2009年11月16日 Bugfix of C typedef of MPL_Int64 that was failing on
+2009年01月16日 Fix bug in is_string_like so it doesn't raise an
+ unnecessary exception. - EF
+
+2009年01月16日 Bugfix of C typedef of MPL_Int64 that was failing on
 Windows XP 64 bit, as reported by George Goussard on numpy
 mailing list. - ADS
 
Modified: branches/v0_98_5_maint/lib/matplotlib/cbook.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/cbook.py	2009年01月16日 21:24:01 UTC (rev 6801)
+++ branches/v0_98_5_maint/lib/matplotlib/cbook.py	2009年01月17日 04:22:07 UTC (rev 6802)
@@ -275,7 +275,7 @@
 else:
 return False
 try: obj + ''
- except (TypeError, ValueError): return False
+ except: return False
 return True
 
 def is_sequence_of_strings(obj):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <ef...@us...> - 2009年01月19日 18:06:30
Revision: 6809
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6809&view=rev
Author: efiring
Date: 2009年01月19日 18:06:15 +0000 (2009年1月19日)
Log Message:
-----------
Don't try to delete nonexistent toolbar in backend_gtk
Modified Paths:
--------------
 branches/v0_98_5_maint/CHANGELOG
 branches/v0_98_5_maint/lib/matplotlib/backends/backend_gtk.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG	2009年01月19日 16:04:37 UTC (rev 6808)
+++ branches/v0_98_5_maint/CHANGELOG	2009年01月19日 18:06:15 UTC (rev 6809)
@@ -1,4 +1,4 @@
-	
+2009年01月19日 Fix bug in backend_gtk: don't delete nonexistent toolbar. - EF
 
 2009年01月16日 Fix bug in is_string_like so it doesn't raise an
 unnecessary exception. - EF
Modified: branches/v0_98_5_maint/lib/matplotlib/backends/backend_gtk.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/backends/backend_gtk.py	2009年01月19日 16:04:37 UTC (rev 6808)
+++ branches/v0_98_5_maint/lib/matplotlib/backends/backend_gtk.py	2009年01月19日 18:06:15 UTC (rev 6809)
@@ -484,7 +484,8 @@
 self.vbox.destroy()
 self.window.destroy()
 self.canvas.destroy()
- self.toolbar.destroy()
+ if self.toolbar:
+ self.toolbar.destroy()
 self.__dict__.clear()
 
 if Gcf.get_num_fig_managers()==0 and \
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
1 2 > >> (Page 1 of 2)
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 によって変換されたページ (->オリジナル) /