Index: lib/matplotlib/legend.py
===================================================================
--- lib/matplotlib/legend.py	(revision 6232)
+++ lib/matplotlib/legend.py	(working copy)
@@ -83,6 +83,7 @@
     def __init__(self, parent, handles, labels,
                  loc = None,
                  numpoints = None,     # the number of points in the legend line
+                 scatterpoints = 3,
                  prop = None,
                  pad = None,           # the fractional whitespace inside the legend border
                  borderpad = None,
@@ -92,19 +93,21 @@
                  handlelen = None,     # the length of the legend lines
                  handletextsep = None, # the space between the legend line and legend text
                  axespad = None,       # the border between the axes and legend edge
-
-                 shadow = None
+                 shadow = None,
+                 scatter_handle_yoffsets=None,
                  ):
         """
   parent                # the artist that contains the legend
   handles               # a list of artists (lines, patches) to add to the legend
   labels                # a list of strings to label the legend
   loc                   # a location code
-  numpoints = 4         # the number of points in the legend line
+  numpoints             # the number of points in the legend line - legend.numpoints
+  scatterpoints         # the number of points in scatter plot/Collection legend symbols
   prop = FontProperties(size='smaller')  # the font property
   pad = 0.2             # the fractional whitespace inside the legend border
   markerscale = 0.6     # the relative size of legend markers vs. original
   shadow                # if True, draw a shadow behind legend
+  scatter_handle_yoffsets  # a list of yoffsets for scatter symbols
 
 The following dimensions are in axes coords
   labelsep = 0.005     # the vertical space between the legend entries
@@ -117,8 +120,8 @@
 
         Artist.__init__(self)
 
-        proplist=[numpoints, pad, borderpad, markerscale, labelsep, handlelen, handletextsep, axespad, shadow]
-        propnames=['numpoints', 'pad', 'borderpad', 'markerscale', 'labelsep', 'handlelen', 'handletextsep', 'axespad', 'shadow']
+        proplist=[numpoints, scatterpoints, pad, borderpad, markerscale, labelsep, handlelen, handletextsep, axespad, shadow]
+        propnames=['numpoints','scatterpoints', 'pad', 'borderpad', 'markerscale', 'labelsep', 'handlelen', 'handletextsep', 'axespad', 'shadow']
         for name, value in safezip(propnames,proplist):
             if value is None:
                 value=rcParams["legend."+name]
@@ -127,13 +130,23 @@
             warnings.warn("Use 'borderpad' instead of 'pad'.", DeprecationWarning)
             # 2008/10/04
         if self.numpoints <= 0:
-            raise ValueError("numpoints must be >= 0; it was %d"% numpoints)
+            raise ValueError("numpoints must be > 0; it was %d"% numpoints)
+        if self.scatterpoints <= 0:
+            raise ValueError("scatterpoints must be > 0; it was %d"% scatterpoints)
         if prop is None:
             self.prop=FontProperties(size=rcParams["legend.fontsize"])
         else:
             self.prop=prop
         self.fontsize = self.prop.get_size_in_points()
 
+        # introduce y-offset for handles of the scatter plot
+        if scatter_handle_yoffsets is None:
+            self._scatter_handle_yoffsets = np.array([4./8., 5./8., 3./8.])
+        else:
+            self._scatter_handle_yoffsets = np.asarray(scatter_handle_yoffsets)
+        reps =  int(self.scatterpoints / len(self._scatter_handle_yoffsets)) + 1
+        self._scatter_handle_yoffsets = np.tile(self._scatter_handle_yoffsets, reps)[:self.scatterpoints]
+
         if isinstance(parent,Axes):
             self.isaxes = True
             self.set_figure(parent.figure)
@@ -250,10 +263,11 @@
         # centered marker proxy
 
         for handle, label in safezip(handles, texts):
-            if self.numpoints > 1:
-                xdata = np.linspace(left, left + self.handlelen, self.numpoints)
+            npoints = self.scatterpoints if isinstance(handle, RegularPolyCollection) else self.numpoints
+            if npoints > 1:
+                xdata = np.linspace(left, left + self.handlelen, npoints)
                 xdata_marker = xdata
-            elif self.numpoints == 1:
+            elif npoints == 1:
                 xdata = np.linspace(left, left + self.handlelen, 2)
                 xdata_marker = [left + 0.5*self.handlelen]
 
@@ -306,15 +320,26 @@
                 ret.append(legline)
 
             elif isinstance(handle, RegularPolyCollection):
-                if self.numpoints == 1:
-                    xdata = np.array([left])
-                p = Rectangle(xy=(min(xdata), y-3/4*HEIGHT),
-                              width = self.handlelen, height=HEIGHT/2,
-                              )
-                p.set_facecolor(handle._facecolors[0])
-                if handle._edgecolors != 'none' and len(handle._edgecolors):
-                    p.set_edgecolor(handle._edgecolors[0])
-                self._set_artist_props(p)
+                # the ydata values set here have no effects as it will
+                # be updated in the _update_positions() method.
+                ydata = (y-HEIGHT/2)*np.ones(np.asarray(xdata_marker).shape, float)
+
+                size_max, size_min = max(handle.get_sizes()),\
+                                     min(handle.get_sizes())
+                # we may need to scale these sizes by "markerscale"
+                # attribute. But other handle types does not seem
+                # to care about this atribute and it is currently ignored.
+                sizes = [.5*(size_max+size_min), size_max,
+                         size_min]
+
+                p = type(handle)(handle.get_numsides(),
+                                 rotation=handle.get_rotation(),
+                                 sizes=sizes,
+                                 offsets=zip(xdata_marker,ydata),
+                                 transOffset=self.get_transform())
+
+                p.update_from(handle)
+                p.set_figure(self.figure)
                 p.set_clip_box(None)
                 p.set_clip_path(None)
                 ret.append(p)
@@ -532,6 +557,11 @@
             elif isinstance(handle, Rectangle):
                 handle.set_y(y+1/4*h)
                 handle.set_height(h/2)
+            elif isinstance(handle,RegularPolyCollection):
+                offsets = handle.get_offsets()
+                offsets[:,1] = y+h*self._scatter_handle_yoffsets
+                handle.set_offsets(offsets)
+                
 
         # Set the data for the legend patch
         bbox = self._get_handle_text_bbox(renderer)
Index: lib/matplotlib/collections.py
===================================================================
--- lib/matplotlib/collections.py	(revision 6232)
+++ lib/matplotlib/collections.py	(working copy)
@@ -148,6 +148,12 @@
         result = result.inverse_transformed(transData)
         return result
 
+    def get_window_extent(self, renderer):
+        bbox = self.get_datalim(transforms.IdentityTransform())
+        #TODO:check to ensure that this does not fail for
+        #cases other than scatter plot legend
+        return bbox
+
     def _prepare_points(self):
         """Point prep for drawing and hit testing"""
 
@@ -417,7 +423,19 @@
         else:
             self._edgecolors = self.to_rgba(self._A, self._alpha)
 
+    def update_from(self, other):
+        'copy properties from other to self'
 
+        artist.Artist.update_from(self, other)
+        self._antialiaseds = other._antialiaseds
+        self._edgecolors_original = other._edgecolors_original
+        self._edgecolors = other._edgecolors
+        self._facecolors_original = other._facecolors_original
+        self._facecolors = other._facecolors
+        self._linewidths = other._linewidths
+        self._linestyles = other._linestyles
+        self._pickradius = other._pickradius
+
 # these are not available for the object inspector until after the
 # class is built so we define an initial set here for the init
 # function and they will be overridden after object defn
@@ -690,6 +708,7 @@
         """
         Collection.__init__(self,**kwargs)
         self._sizes = sizes
+        self._numsides = numsides
         self._paths = [self._path_generator(numsides)]
         self._rotation = rotation
         self.set_transform(transforms.IdentityTransform())
@@ -706,7 +725,16 @@
     def get_paths(self):
         return self._paths
 
+    def get_numsides(self):
+        return self._numsides
 
+    def get_rotation(self):
+        return self._rotation
+
+    def get_sizes(self):
+        return self._sizes
+
+
 class StarPolygonCollection(RegularPolyCollection):
     """
     Draw a collection of regular stars with *numsides* points."""
