I'm attaching a slightly modified version of the patch, originally by
Eric Bruning.
I changed the name to "allow_rasterization", and added some code to
check if the draw method is decorated when set_rasterized is called
(I'll be glad to hear any better idea for this).
The second patch is to let you use MixedModeRenderer when saving ps
output, i.e., rasterzation for ps backend. The rasterization per
artist is not that useful for ps backend as it does not support alpha
compositions. However, I introduced *rasterization_zorder* attributes
in Axes class, and slightly modified its draw method so that all the
artists whose zorder is below *rasterization_zorder* will be
rasterized (to a single image). My main use case for this is to have
transparent (but rasterized) contour lines or texts overlayed on top
of a background image (for PS backend). Take a look at the example
script I added (examples/misc/rasterization_demo.py).
Any comment or suggestion will be welcomed.
I'm planning to commit this change to the svn soon, unless others come
up with some issues.
Regards,
-JJ
On Mon, May 4, 2009 at 10:05 AM, Eric Bruning <eric.brun...@gmail.com> wrote:
> On Wed, Apr 29, 2009 at 4:17 PM, Eric Firing <efir...@hawaii.edu> wrote:
>> Jae-Joon Lee wrote:
>>>
>>> On Sun, Apr 26, 2009 at 11:31 PM, Eric Bruning <eric.brun...@gmail.com>
>>> wrote:
>>>>
>>>> I like that this solution doesn't litter every call to draw with
>>>> rasterize checks. But it means that the rasterization support had
>>>> better be robust, since Artist authors might not know they're
>>>> interacting with the rasterization code. It has the downside of being
>>>> implicit rather than explicit.
>>>
>>> Eric,
>>> I think we'd better stick to your decorator solution.
>>>
>>> Anyhow, I thought you had a svn commit permission but it seems not. Do
>>> you (and other dwevelopers) mind if I commit this patch to the trunk?
>>
>> It would be especially good for John and Mike to have a look.
>>
>> As a matter of style, I suggest a name change. "@hook_before_after_draw" is
>> too generic, and brings to mind discussions a long time ago about possibly
>> adding a general hook mechanism; even before rasterization, and before
>> decorators were available, there were thoughts that we might need this.
>> (Now I don't remember what the motivation was, but I think it had to do
>> with coordinating different elements of a plot.) In any case, the decorator
>> is actually very specific to rasterization, so maybe call it
>> "@with_rasterization" or "@allow_rasterization".
>>
>> I am very anxious to see rasterization support in place; let's just be sure
>> we have a good API and mechanism. The patch looks reasonable to me, but I
>> have no experience in writing decorators, and have not had time to really
>> think about the rasterization API problem.
>
> I like Eric's suggestion to rename the decorator if its only purpose
> is to handle rasterizing. A generic draw hook solution would be fun to
> develop, but I don't have time for that learning curve at the moment.
> So a raster-specific decorator is good by me; I like
> @allow_rasterization.
>
> It's correct that I'd need someone to commit the patch for me. In my
> view, renaming the decorator is a simple search-replace that can be
> handled by the committer, but I'm happy to help with any changes we
> agree on.
>
>>> One I thing I want to add your patch is to warn users when they set
>>> "rasterized" attribute of the artists whose draw method is not
>>> decorated. I'll think about it later but feel free to propose any.
>
> I have no experience with decorator detection. Presumably you can so
> some sort of inspection of self.draw in Artist.set_rasterized.
>
> Thanks,
> Eric B
>
>
>>>
>>> Thanks,
>>>
>>> -JJ
>>>
>>>
>>> ------------------------------------------------------------------------------
>>> Register Now & Save for Velocity, the Web Performance & Operations
>>> Conference from O'Reilly Media. Velocity features a full day of expert-led,
>>> hands-on workshops and two days of sessions from industry leaders in
>>> dedicated Performance & Operations tracks. Use code vel09scf and Save an
>>> extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
>>> _______________________________________________
>>> Matplotlib-devel mailing list
>>> Matplotlib-devel@lists.sourceforge.net
>>> https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
>>
>>
>
Index: lib/matplotlib/legend.py
===================================================================
--- lib/matplotlib/legend.py (revision 7085)
+++ lib/matplotlib/legend.py (working copy)
@@ -26,7 +26,7 @@
import numpy as np
from matplotlib import rcParams
-from matplotlib.artist import Artist
+from matplotlib.artist import Artist, allow_rasterization
from matplotlib.cbook import is_string_like, iterable, silent_list, safezip
from matplotlib.font_manager import FontProperties
from matplotlib.lines import Line2D
@@ -323,6 +323,7 @@
return x+xdescent, y+ydescent
+ @allow_rasterization
def draw(self, renderer):
"Draw everything that belongs to the legend"
if not self.get_visible(): return
Index: lib/matplotlib/artist.py
===================================================================
--- lib/matplotlib/artist.py (revision 7085)
+++ lib/matplotlib/artist.py (working copy)
@@ -22,6 +22,38 @@
# http://groups.google.com/groups?hl=en&lr=&threadm=mailman.5090.1098044946.5135.python-list%40python.org&rnum=1&prev=/groups%3Fq%3D__doc__%2Bauthor%253Ajdhunter%2540ace.bsd.uchicago.edu%26hl%3Den%26btnG%3DGoogle%2BSearch
+
+
+def allow_rasterization(draw):
+ """
+ Decorator for Artist.draw method. Provides routines
+ that run before and after the draw call. The before and after functions
+ are useful for changing artist-dependant renderer attributes or making
+ other setup function calls, such as starting and flushing a mixed-mode
+ renderer.
+ """
+ def before(artist, renderer):
+ if artist.get_rasterized():
+ renderer.start_rasterizing()
+
+ def after(artist, renderer):
+ if artist.get_rasterized():
+ renderer.stop_rasterizing()
+
+ # the axes class has a second argument inframe for its draw method.
+ def draw_wrapper(artist, renderer, *kl):
+ before(artist, renderer)
+ draw(artist, renderer, *kl)
+ after(artist, renderer)
+
+ # "safe wrapping" to exactly replicate anything we haven't overridden above
+ draw_wrapper.__name__ = draw.__name__
+ draw_wrapper.__dict__ = draw.__dict__
+ draw_wrapper.__doc__ = draw.__doc__
+ draw_wrapper._rasterized = True
+ return draw_wrapper
+
+
class Artist(object):
"""
Abstract base class for someone who renders into a
@@ -45,6 +77,7 @@
self._label = ''
self._picker = None
self._contains = None
+ self._rasterized = None
self.eventson = False # fire events only if eventson
self._oid = 0 # an observer id
@@ -510,7 +543,24 @@
else:
gc.set_clip_rectangle(None)
gc.set_clip_path(None)
+
+ def get_rasterized(self):
+ return self._rasterized
+
+ def set_rasterized(self, rasterized):
+ """
+ Force rasterized (bitmap) drawing in vector backend output.
+
+ Defaults to None, which implies the backend's default behavior
+
+ ACCEPTS: [True | False | None]
+ """
+ if rasterized and not hasattr(self.draw, "_rasterized"):
+ warnings.warn("Rasterization of '%s' will be ignored" % self)
+ self._rasterized = rasterized
+
+ @allow_rasterization
def draw(self, renderer, *args, **kwargs):
'Derived classes drawing method'
if not self.get_visible(): return
Index: lib/matplotlib/lines.py
===================================================================
--- lib/matplotlib/lines.py (revision 7085)
+++ lib/matplotlib/lines.py (working copy)
@@ -18,6 +18,8 @@
from transforms import Affine2D, Bbox, TransformedPath, IdentityTransform
from matplotlib import rcParams
+from artist import allow_rasterization
+
# special-purpose marker identifiers:
(TICKLEFT, TICKRIGHT, TICKUP, TICKDOWN,
CARETLEFT, CARETRIGHT, CARETUP, CARETDOWN) = range(8)
@@ -459,6 +461,7 @@
if len(x)<2: return 1
return np.alltrue(x[1:]-x[0:-1]>=0)
+ @allow_rasterization
def draw(self, renderer):
if self._invalid:
self.recache()
Index: lib/matplotlib/quiver.py
===================================================================
--- lib/matplotlib/quiver.py (revision 7085)
+++ lib/matplotlib/quiver.py (working copy)
@@ -282,6 +282,7 @@
else:
return y
+ @martist.allow_rasterization
def draw(self, renderer):
self._init()
self.vector.draw(renderer)
@@ -418,6 +419,7 @@
if self.width is None:
self.width = 0.06 * self.span / sn
+ @martist.allow_rasterization
def draw(self, renderer):
self._init()
if self._new_UV or self.angles == 'xy':
Index: lib/matplotlib/patches.py
===================================================================
--- lib/matplotlib/patches.py (revision 7085)
+++ lib/matplotlib/patches.py (working copy)
@@ -260,7 +260,7 @@
'Return the current hatching pattern'
return self._hatch
-
+ @artist.allow_rasterization
def draw(self, renderer):
'Draw the :class:`Patch` to the given *renderer*.'
if not self.get_visible(): return
@@ -1176,6 +1176,7 @@
self.theta2 = theta2
__init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
+ @artist.allow_rasterization
def draw(self, renderer):
"""
Ellipses are normally drawn using an approximation that uses
Index: lib/matplotlib/axes.py
===================================================================
--- lib/matplotlib/axes.py (revision 7085)
+++ lib/matplotlib/axes.py (working copy)
@@ -1602,6 +1617,7 @@
#### Drawing
+ @martist.allow_rasterization
def draw(self, renderer=None, inframe=False):
"Draw everything (plot lines, axes, labels)"
if renderer is None:
Index: lib/matplotlib/axis.py
===================================================================
--- lib/matplotlib/axis.py (revision 7085)
+++ lib/matplotlib/axis.py (working copy)
@@ -176,6 +176,7 @@
'Return the tick location (data coords) as a scalar'
return self._loc
+ @artist.allow_rasterization
def draw(self, renderer):
if not self.get_visible(): return
renderer.open_group(self.__name__)
@@ -719,6 +720,7 @@
bbox2 = mtransforms.Bbox.from_extents(0, 0, 0, 0)
return bbox, bbox2
+ @artist.allow_rasterization
def draw(self, renderer, *args, **kwargs):
'Draw the axis lines, grid lines, tick lines and labels'
ticklabelBoxes = []
Index: lib/matplotlib/collections.py
===================================================================
--- lib/matplotlib/collections.py (revision 7085)
+++ lib/matplotlib/collections.py (working copy)
@@ -190,6 +190,7 @@
return transform, transOffset, offsets, paths
+ @artist.allow_rasterization
def draw(self, renderer):
if not self.get_visible(): return
renderer.open_group(self.__class__.__name__)
@@ -594,6 +595,7 @@
def get_datalim(self, transData):
return self._bbox
+ @artist.allow_rasterization
def draw(self, renderer):
if not self.get_visible(): return
renderer.open_group(self.__class__.__name__)
@@ -781,6 +783,7 @@
__init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
+ @artist.allow_rasterization
def draw(self, renderer):
self._transforms = [
transforms.Affine2D().rotate(-self._rotation).scale(
Index: lib/matplotlib/figure.py
===================================================================
--- lib/matplotlib/figure.py (revision 7085)
+++ lib/matplotlib/figure.py (working copy)
@@ -15,7 +15,7 @@
import time
import artist
-from artist import Artist
+from artist import Artist, allow_rasterization
from axes import Axes, SubplotBase, subplot_class_factory
from cbook import flatten, allequal, Stack, iterable, dedent
import _image
@@ -727,6 +727,7 @@
"""
self.clf()
+ @allow_rasterization
def draw(self, renderer):
"""
Render the figure using :class:`matplotlib.backend_bases.RendererBase` instance renderer
Index: lib/matplotlib/image.py
===================================================================
--- lib/matplotlib/image.py (revision 7085)
+++ lib/matplotlib/image.py (working copy)
@@ -225,7 +225,7 @@
norm=self._filternorm, radius=self._filterrad)
return im
-
+ @martist.allow_rasterization
def draw(self, renderer, *args, **kwargs):
if not self.get_visible(): return
if (self.axes.get_xscale() != 'linear' or
@@ -571,6 +571,7 @@
im.is_grayscale = self.is_grayscale
return im
+ @martist.allow_rasterization
def draw(self, renderer, *args, **kwargs):
if not self.get_visible(): return
im = self.make_image(renderer.get_image_magnification())
@@ -723,6 +724,7 @@
return im
+ @martist.allow_rasterization
def draw(self, renderer, *args, **kwargs):
if not self.get_visible(): return
# todo: we should be able to do some cacheing here
Index: lib/matplotlib/table.py
===================================================================
--- lib/matplotlib/table.py (revision 7085)
+++ lib/matplotlib/table.py (working copy)
@@ -23,7 +23,7 @@
import warnings
import artist
-from artist import Artist
+from artist import Artist, allow_rasterization
from patches import Rectangle
from cbook import is_string_like
from text import Text
@@ -90,6 +90,7 @@
return fontsize
+ @allow_rasterization
def draw(self, renderer):
if not self.get_visible(): return
# draw the rectangle
@@ -215,6 +216,7 @@
def _approx_text_height(self):
return self.FONTSIZE/72.0*self.figure.dpi/self._axes.bbox.height * 1.2
+ @allow_rasterization
def draw(self, renderer):
# Need a renderer to do hit tests on mouseevent; assume the last one will do
if renderer is None:
Index: lib/matplotlib/backend_bases.py
===================================================================
--- lib/matplotlib/backend_bases.py (revision 7085)
+++ lib/matplotlib/backend_bases.py (working copy)
@@ -1443,6 +1443,7 @@
facecolor=facecolor,
edgecolor=edgecolor,
orientation=orientation,
+ dryrun=True,
**kwargs)
renderer = self.figure._cachedRenderer
bbox_inches = self.figure.get_tightbbox(renderer)
Index: lib/matplotlib/axes.py
===================================================================
--- lib/matplotlib/axes.py (revision 7085)
+++ lib/matplotlib/axes.py (working copy)
@@ -531,6 +531,8 @@
self._frameon = frameon
self._axisbelow = rcParams['axes.axisbelow']
+ self._rasterization_zorder = -30000
+
self._hold = rcParams['axes.hold']
self._connected = {} # a dict from events to (id, func)
self.cla()
@@ -1566,6 +1568,19 @@
"""
self._autoscaleYon = b
+ def set_rasterization_zorder(self, z):
+ """
+ Set zorder value below which artists will be rasterized
+ """
+ self._rasterization_zorder = z
+
+ def get_rasterization_zorder(self):
+ """
+ Get zorder value below which artists will be rasterized
+ """
+ return self._rasterization_zorder
+
+
def autoscale_view(self, tight=False, scalex=True, scaley=True):
"""
autoscale the view limits using the data limits. You can
@@ -1619,15 +1635,57 @@
else:
self.apply_aspect()
+
+ artists = []
+
+
+
+ artists.extend(self.collections)
+ artists.extend(self.patches)
+ artists.extend(self.lines)
+ artists.extend(self.texts)
+ artists.extend(self.artists)
+ if self.axison and not inframe:
+ if self._axisbelow:
+ self.xaxis.set_zorder(0.5)
+ self.yaxis.set_zorder(0.5)
+ else:
+ self.xaxis.set_zorder(2.5)
+ self.yaxis.set_zorder(2.5)
+ artists.extend([self.xaxis, self.yaxis])
+ if not inframe: artists.append(self.title)
+ artists.extend(self.tables)
+ if self.legend_ is not None:
+ artists.append(self.legend_)
+
+ # the frame draws the edges around the axes patch -- we
+ # decouple these so the patch can be in the background and the
+ # frame in the foreground.
+ if self.axison and self._frameon:
+ artists.append(self.frame)
+
+
+ dsu = [ (a.zorder, i, a) for i, a in enumerate(artists)
+ if not a.get_animated() ]
+ dsu.sort()
+
+
+ # rasterze artists with negative zorder
+ # if the minimum zorder is negative, start rasterization
+ rasterization_zorder = self._rasterization_zorder
+ if dsu[0][0] < rasterization_zorder:
+ renderer.start_rasterizing()
+ dsu_rasterized = [l for l in dsu if l[0] < rasterization_zorder]
+ dsu = [l for l in dsu if l[0] >= rasterization_zorder]
+ else:
+ dsu_rasterized = []
+
+
# the patch draws the background rectangle -- the frame below
# will draw the edges
if self.axison and self._frameon:
self.patch.draw(renderer)
- artists = []
-
-
-
if len(self.images)<=1 or renderer.option_image_nocomposite():
for im in self.images:
im.draw(renderer)
@@ -1656,35 +1714,13 @@
self.patch.get_path(),
self.patch.get_transform())
- artists.extend(self.collections)
- artists.extend(self.patches)
- artists.extend(self.lines)
- artists.extend(self.texts)
- artists.extend(self.artists)
- if self.axison and not inframe:
- if self._axisbelow:
- self.xaxis.set_zorder(0.5)
- self.yaxis.set_zorder(0.5)
- else:
- self.xaxis.set_zorder(2.5)
- self.yaxis.set_zorder(2.5)
- artists.extend([self.xaxis, self.yaxis])
- if not inframe: artists.append(self.title)
- artists.extend(self.tables)
- if self.legend_ is not None:
- artists.append(self.legend_)
- # the frame draws the edges around the axes patch -- we
- # decouple these so the patch can be in the background and the
- # frame in the foreground.
- if self.axison and self._frameon:
- artists.append(self.frame)
+ if dsu_rasterized:
+ for zorder, i, a in dsu_rasterized:
+ a.draw(renderer)
+ renderer.stop_rasterizing()
- dsu = [ (a.zorder, i, a) for i, a in enumerate(artists)
- if not a.get_animated() ]
- dsu.sort()
-
for zorder, i, a in dsu:
a.draw(renderer)
Index: lib/matplotlib/backends/backend_ps.py
===================================================================
--- lib/matplotlib/backends/backend_ps.py (revision 7085)
+++ lib/matplotlib/backends/backend_ps.py (working copy)
@@ -33,6 +33,9 @@
from matplotlib.path import Path
from matplotlib.transforms import Affine2D
+from matplotlib.backends.backend_mixed import MixedModeRenderer
+
+
import numpy as npy
import binascii
import re
@@ -843,8 +846,13 @@
def print_eps(self, outfile, *args, **kwargs):
return self._print_ps(outfile, 'eps', *args, **kwargs)
+
+
+
+
+
def _print_ps(self, outfile, format, *args, **kwargs):
- papertype = kwargs.get("papertype", rcParams['ps.papersize'])
+ papertype = kwargs.pop("papertype", rcParams['ps.papersize'])
papertype = papertype.lower()
if papertype == 'auto':
pass
@@ -852,25 +860,28 @@
raise RuntimeError( '%s is not a valid papertype. Use one \
of %s'% (papertype, ', '.join( papersize.keys() )) )
- orientation = kwargs.get("orientation", "portrait").lower()
+ orientation = kwargs.pop("orientation", "portrait").lower()
if orientation == 'landscape': isLandscape = True
elif orientation == 'portrait': isLandscape = False
else: raise RuntimeError('Orientation must be "portrait" or "landscape"')
self.figure.set_dpi(72) # Override the dpi kwarg
- imagedpi = kwargs.get("dpi", 72)
- facecolor = kwargs.get("facecolor", "w")
- edgecolor = kwargs.get("edgecolor", "w")
+ imagedpi = kwargs.pop("dpi", 72)
+ facecolor = kwargs.pop("facecolor", "w")
+ edgecolor = kwargs.pop("edgecolor", "w")
if rcParams['text.usetex']:
self._print_figure_tex(outfile, format, imagedpi, facecolor, edgecolor,
- orientation, isLandscape, papertype)
+ orientation, isLandscape, papertype,
+ **kwargs)
else:
self._print_figure(outfile, format, imagedpi, facecolor, edgecolor,
- orientation, isLandscape, papertype)
+ orientation, isLandscape, papertype,
+ **kwargs)
def _print_figure(self, outfile, format, dpi=72, facecolor='w', edgecolor='w',
- orientation='portrait', isLandscape=False, papertype=None):
+ orientation='portrait', isLandscape=False, papertype=None,
+ **kwargs):
"""
Render the figure to hardcopy. Set the figure patch face and
edge colors. This is useful because some of the GUIs have a
@@ -939,10 +950,30 @@
self.figure.set_facecolor(facecolor)
self.figure.set_edgecolor(edgecolor)
- self._pswriter = StringIO()
- renderer = RendererPS(width, height, self._pswriter, imagedpi=dpi)
+
+ dryrun = kwargs.get("dryrun", False)
+ if dryrun:
+ class NullWriter(object):
+ def write(self, *kl, **kwargs):
+ pass
+
+ self._pswriter = NullWriter()
+ else:
+ self._pswriter = StringIO()
+
+
+ # mixed mode rendering
+ _bbox_inches_restore = kwargs.pop("bbox_inches_restore", None)
+ ps_renderer = RendererPS(width, height, self._pswriter, imagedpi=dpi)
+ renderer = MixedModeRenderer(self.figure,
+ width, height, dpi, ps_renderer,
+ bbox_inches_restore=_bbox_inches_restore)
+
self.figure.draw(renderer)
+ if dryrun: # return immediately if dryrun (tightbbox=True)
+ return
+
self.figure.set_facecolor(origfacecolor)
self.figure.set_edgecolor(origedgecolor)
@@ -1019,7 +1050,8 @@
shutil.move(tmpfile, outfile)
def _print_figure_tex(self, outfile, format, dpi, facecolor, edgecolor,
- orientation, isLandscape, papertype):
+ orientation, isLandscape, papertype,
+ **kwargs):
"""
If text.usetex is True in rc, a temporary pair of tex/eps files
are created to allow tex to manage the text layout via the PSFrags
@@ -1051,10 +1083,29 @@
self.figure.set_facecolor(facecolor)
self.figure.set_edgecolor(edgecolor)
- self._pswriter = StringIO()
- renderer = RendererPS(width, height, self._pswriter, imagedpi=dpi)
+ dryrun = kwargs.get("dryrun", False)
+ if dryrun:
+ class NullWriter(object):
+ def write(self, *kl, **kwargs):
+ pass
+
+ self._pswriter = NullWriter()
+ else:
+ self._pswriter = StringIO()
+
+
+ # mixed mode rendering
+ _bbox_inches_restore = kwargs.pop("bbox_inches_restore", None)
+ ps_renderer = RendererPS(width, height, self._pswriter, imagedpi=dpi)
+ renderer = MixedModeRenderer(self.figure,
+ width, height, dpi, ps_renderer,
+ bbox_inches_restore=_bbox_inches_restore)
+
self.figure.draw(renderer)
+ if dryrun: # return immediately if dryrun (tightbbox=True)
+ return
+
self.figure.set_facecolor(origfacecolor)
self.figure.set_edgecolor(origedgecolor)
@@ -1121,7 +1172,7 @@
font_preamble = texmanager.get_font_preamble()
custom_preamble = texmanager.get_custom_preamble()
- convert_psfrags(tmpfile, renderer.psfrag, font_preamble,
+ convert_psfrags(tmpfile, ps_renderer.psfrag, font_preamble,
custom_preamble, paperWidth, paperHeight,
orientation)
Index: examples/misc/rasterization_demo.py
===================================================================
--- examples/misc/rasterization_demo.py (revision 0)
+++ examples/misc/rasterization_demo.py (revision 0)
@@ -0,0 +1,50 @@
+import numpy as np
+import matplotlib.pyplot as plt
+
+d = np.arange(100).reshape(10, 10)
+x, y = np.meshgrid(np.arange(11), np.arange(11))
+
+theta = 0.25*np.pi
+xx = x*np.cos(theta) - y*np.sin(theta)
+yy = x*np.sin(theta) + y*np.cos(theta)
+
+ax1 = plt.subplot(221)
+ax1.set_aspect(1)
+ax1.pcolormesh(xx, yy, d)
+ax1.set_title("No Rasterization")
+
+ax2 = plt.subplot(222)
+ax2.set_aspect(1)
+ax2.set_title("Rasterization")
+
+m = ax2.pcolormesh(xx, yy, d)
+m.set_rasterized(True)
+
+ax3 = plt.subplot(223)
+ax3.set_aspect(1)
+ax3.pcolormesh(xx, yy, d)
+ax3.text(0.5, 0.5, "Text", alpha=0.2,
+ va="center", ha="center", size=50, transform=ax3.transAxes)
+
+ax3.set_title("No Rasterization")
+
+
+ax4 = plt.subplot(224)
+ax4.set_aspect(1)
+m = ax4.pcolormesh(xx, yy, d)
+m.set_zorder(-20)
+
+ax4.text(0.5, 0.5, "Text", alpha=0.2,
+ zorder=-15,
+ va="center", ha="center", size=50, transform=ax4.transAxes)
+
+ax4.set_rasterization_zorder(-10)
+
+ax4.set_title("Rasterization z<-10")
+
+
+# ax2.title.set_rasterized(True) # should display a warning
+
+plt.savefig("test_reasterization.pdf", dpi=150)
+plt.savefig("test_reasterization.eps", dpi=150)
+plt.savefig("test_reasterization.svg", dpi=150) # svg backend currently ifnores the dpi
------------------------------------------------------------------------------
The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your
production scanning environment may not be a perfect world - but thanks to
Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700
Series Scanner you'll get full speed at 300 dpi even with all image
processing features enabled. http://p.sf.net/sfu/kodak-com
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel