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
