Index: legend.py
===================================================================
--- legend.py	(revision 7056)
+++ 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, hook_before_after_draw
 from matplotlib.cbook import is_string_like, iterable, silent_list, safezip
 from matplotlib.font_manager import FontProperties
 from matplotlib.lines import Line2D
@@ -317,6 +317,7 @@
 
         return x+xdescent, y+ydescent
 
+    @hook_before_after_draw
     def draw(self, renderer):
         "Draw everything that belongs to the legend"
         if not self.get_visible(): return
Index: artist.py
===================================================================
--- artist.py	(revision 7056)
+++ artist.py	(working copy)
@@ -22,6 +22,36 @@
 # 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 hook_before_after_draw(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()
+
+    def draw_wrapper(artist, renderer):
+        before(artist, renderer)    
+        draw(artist, renderer)
+        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__
+    return draw_wrapper
+    
+
 class Artist(object):
     """
     Abstract base class for someone who renders into a
@@ -45,6 +75,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 +541,21 @@
         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]
+        """
+        self._rasterized = rasterized
 
+    @hook_before_after_draw
     def draw(self, renderer, *args, **kwargs):
         'Derived classes drawing method'
         if not self.get_visible(): return
Index: lines.py
===================================================================
--- lines.py	(revision 7056)
+++ lines.py	(working copy)
@@ -18,6 +18,8 @@
 from transforms import Affine2D, Bbox, TransformedPath, IdentityTransform
 
 from matplotlib import rcParams
+from artist import hook_before_after_draw
+
 # 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)
 
+    @hook_before_after_draw
     def draw(self, renderer):
         if self._invalid:
             self.recache()
Index: quiver.py
===================================================================
--- quiver.py	(revision 7056)
+++ quiver.py	(working copy)
@@ -282,6 +282,7 @@
         else:
             return y
 
+    @martist.hook_before_after_draw
     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.hook_before_after_draw
     def draw(self, renderer):
         self._init()
         if self._new_UV or self.angles == 'xy':

 
Index: patches.py
===================================================================
--- patches.py	(revision 7056)
+++ patches.py	(working copy)
@@ -260,7 +260,7 @@
         'Return the current hatching pattern'
         return self._hatch
 
-
+    @artist.hook_before_after_draw
     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.hook_before_after_draw
     def draw(self, renderer):
         """
         Ellipses are normally drawn using an approximation that uses
Index: axes.py
===================================================================
--- axes.py	(revision 7056)
+++ axes.py	(working copy)
@@ -1585,6 +1585,7 @@
 
     #### Drawing
 
+    @martist.hook_before_after_draw
     def draw(self, renderer=None, inframe=False):
         "Draw everything (plot lines, axes, labels)"
         if renderer is None:
Index: axis.py
===================================================================
--- axis.py	(revision 7056)
+++ axis.py	(working copy)
@@ -176,6 +176,7 @@
         'Return the tick location (data coords) as a scalar'
         return self._loc
 
+    @artist.hook_before_after_draw
     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.hook_before_after_draw
     def draw(self, renderer, *args, **kwargs):
         'Draw the axis lines, grid lines, tick lines and labels'
         ticklabelBoxes = []
Index: collections.py
===================================================================
--- collections.py	(revision 7056)
+++ collections.py	(working copy)
@@ -190,6 +190,7 @@
 
         return transform, transOffset, offsets, paths
 
+    @artist.hook_before_after_draw
     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.hook_before_after_draw
     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.hook_before_after_draw
     def draw(self, renderer):
         self._transforms = [
             transforms.Affine2D().rotate(-self._rotation).scale(
Index: figure.py
===================================================================
--- figure.py	(revision 7056)
+++ figure.py	(working copy)
@@ -15,7 +15,7 @@
 import time
 
 import artist
-from artist import Artist
+from artist import Artist, hook_before_after_draw
 from axes import Axes, SubplotBase, subplot_class_factory
 from cbook import flatten, allequal, Stack, iterable, dedent
 import _image
@@ -727,6 +727,7 @@
         """
         self.clf()
 
+    @hook_before_after_draw
     def draw(self, renderer):
         """
         Render the figure using :class:`matplotlib.backend_bases.RendererBase` instance renderer
Index: image.py
===================================================================
--- image.py	(revision 7056)
+++ image.py	(working copy)
@@ -225,7 +225,7 @@
                   norm=self._filternorm, radius=self._filterrad)
         return im
 
-
+    @martist.hook_before_after_draw
     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.hook_before_after_draw
     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.hook_before_after_draw
     def draw(self, renderer, *args, **kwargs):
         if not self.get_visible(): return
         # todo: we should be able to do some cacheing here
Index: table.py
===================================================================
--- table.py	(revision 7056)
+++ table.py	(working copy)
@@ -23,7 +23,7 @@
 import warnings
 
 import artist
-from artist import Artist
+from artist import Artist, hook_before_after_draw
 from patches import Rectangle
 from cbook import is_string_like
 from text import Text
@@ -90,6 +90,7 @@
 
         return fontsize
 
+    @hook_before_after_draw
     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
 
+    @hook_before_after_draw
     def draw(self, renderer):
         # Need a renderer to do hit tests on mouseevent; assume the last one will do
         if renderer is None:
