Index: src/_backend_agg.cpp
===================================================================
--- src/_backend_agg.cpp	(revision 6367)
+++ src/_backend_agg.cpp	(working copy)
@@ -737,7 +737,7 @@
 RendererAgg::draw_image(const Py::Tuple& args) {
   _VERBOSE("RendererAgg::draw_image");
 
-  args.verify_length(4, 6);
+  args.verify_length(4, 7);
 
   double x = Py::Float(args[0]);
   double y = Py::Float(args[1]);
@@ -749,7 +749,7 @@
 
   theRasterizer.reset_clipping();
   rendererBase.reset_clipping(true);
-  if (args.size() == 6) {
+  if (args.size() >= 6) {
     clippath = args[4];
     clippath_trans = py_to_agg_transformation_matrix(args[5], false);
     has_clippath = render_clippath(clippath, clippath_trans);
@@ -959,7 +959,8 @@
    const Py::Object&              edgecolors_obj,
    const Py::SeqBase<Py::Float>&  linewidths,
    const Py::SeqBase<Py::Object>& linestyles_obj,
-   const Py::SeqBase<Py::Int>&    antialiaseds) {
+   const Py::SeqBase<Py::Int>&    antialiaseds,
+   const Py::SeqBase<Py::Object>&  urls) {
   typedef agg::conv_transform<typename PathGenerator::path_iterator> transformed_path_t;
   typedef SimplifyPath<transformed_path_t>			     simplify_t;
   typedef agg::conv_curve<simplify_t>				     simplified_curve_t;
@@ -1154,7 +1155,7 @@
 Py::Object
 RendererAgg::draw_path_collection(const Py::Tuple& args) {
   _VERBOSE("RendererAgg::draw_path_collection");
-  args.verify_length(13);
+  args.verify_length(14);
 
   //segments, trans, clipbox, colors, linewidths, antialiaseds
   agg::trans_affine	  master_transform = py_to_agg_transformation_matrix(args[0]);
@@ -1170,7 +1171,7 @@
   Py::SeqBase<Py::Float>  linewidths	   = args[10];
   Py::SeqBase<Py::Object> linestyles_obj   = args[11];
   Py::SeqBase<Py::Int>    antialiaseds	   = args[12];
-
+  Py::SeqBase<Py::Object> urls             = args[13];
   PathListGenerator path_generator(paths);
 
   try {
@@ -1187,7 +1188,8 @@
        edgecolors_obj,
        linewidths,
        linestyles_obj,
-       antialiaseds);
+       antialiaseds,
+       urls);
   } catch (const char *e) {
     throw Py::RuntimeError(e);
   }
@@ -1295,6 +1297,7 @@
   Py::SeqBase<Py::Object> linestyles_obj;
   Py::Tuple antialiaseds(1);
   antialiaseds[0] = Py::Int(antialiased ? 1 : 0);
+  Py::SeqBase<Py::Object> urls;
 
   if (showedges) {
     npy_intp dims[] = { 1, 4, 0 };
@@ -1326,7 +1329,8 @@
          edgecolors_obj,
          linewidths,
          linestyles_obj,
-         antialiaseds);
+         antialiaseds,
+         urls);
     } catch (const char* e) {
       throw Py::RuntimeError(e);
     }
Index: src/_backend_agg.h
===================================================================
--- src/_backend_agg.h	(revision 6367)
+++ src/_backend_agg.h	(working copy)
@@ -228,7 +228,8 @@
      const Py::Object&              edgecolors_obj,
      const Py::SeqBase<Py::Float>&  linewidths,
      const Py::SeqBase<Py::Object>& linestyles_obj,
-     const Py::SeqBase<Py::Int>&    antialiaseds);
+     const Py::SeqBase<Py::Int>&    antialiaseds,
+     const Py::SeqBase<Py::Object>&  urls);
 
 private:
   void create_alpha_buffers();
Index: lib/matplotlib/backend_bases.py
===================================================================
--- lib/matplotlib/backend_bases.py	(revision 6367)
+++ lib/matplotlib/backend_bases.py	(working copy)
@@ -107,7 +107,7 @@
     def draw_path_collection(self, master_transform, cliprect, clippath,
                              clippath_trans, paths, all_transforms, offsets,
                              offsetTrans, facecolors, edgecolors, linewidths,
-                             linestyles, antialiaseds):
+                             linestyles, antialiaseds, urls):
         """
         Draws a collection of paths, selecting drawing properties from
         the lists *facecolors*, *edgecolors*, *linewidths*,
@@ -136,7 +136,7 @@
         for xo, yo, path_id, gc, rgbFace in self._iter_collection(
             path_ids, cliprect, clippath, clippath_trans,
             offsets, offsetTrans, facecolors, edgecolors,
-            linewidths, linestyles, antialiaseds):
+            linewidths, linestyles, antialiaseds, urls):
             path, transform = path_id
             transform = transforms.Affine2D(transform.get_matrix()).translate(xo, yo)
             self.draw_path(gc, path, transform, rgbFace)
@@ -164,7 +164,7 @@
         return self.draw_path_collection(
             master_transform, cliprect, clippath, clippath_trans,
             paths, [], offsets, offsetTrans, facecolors, edgecolors,
-            linewidths, [], [antialiased])
+            linewidths, [], [antialiased], [None])
 
     def _iter_collection_raw_paths(self, master_transform, paths, all_transforms):
         """
@@ -198,7 +198,7 @@
 
     def _iter_collection(self, path_ids, cliprect, clippath, clippath_trans,
                          offsets, offsetTrans, facecolors, edgecolors,
-                         linewidths, linestyles, antialiaseds):
+                         linewidths, linestyles, antialiaseds, urls):
         """
         This is a helper method (along with
         :meth:`_iter_collection_raw_paths`) to make it easier to write
@@ -232,6 +232,7 @@
         Nlinewidths = len(linewidths)
         Nlinestyles = len(linestyles)
         Naa         = len(antialiaseds)
+        Nurls       = len(urls)
 
         if (Nfacecolors == 0 and Nedgecolors == 0) or Npaths == 0:
             return
@@ -268,6 +269,9 @@
                 gc.set_alpha(rgbFace[-1])
                 rgbFace = rgbFace[:3]
             gc.set_antialiased(antialiaseds[i % Naa])
+            
+            if Nurls:
+                gc.set_url(urls[i % Nurls])
 
             yield xo, yo, path_id, gc, rgbFace
 
@@ -279,7 +283,7 @@
         """
         return 1.0
 
-    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
+    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None, url=None):
         """
         Draw the image instance into the current axes;
 
@@ -433,6 +437,7 @@
         self._linewidth = 1
         self._rgb = (0.0, 0.0, 0.0)
         self._hatch = None
+        self._url = None
 
     def copy_properties(self, gc):
         'Copy properties from gc to self'
@@ -447,6 +452,7 @@
         self._linewidth = gc._linewidth
         self._rgb = gc._rgb
         self._hatch = gc._hatch
+        self._url = gc._url
 
     def get_alpha(self):
         """
@@ -521,6 +527,12 @@
         matlab format string, a html hex color string, or a rgb tuple
         """
         return self._rgb
+    
+    def get_url(self):
+        """
+        returns a url if one is set, None otherwise
+        """
+        return self._url
 
     def set_alpha(self, alpha):
         """
@@ -621,6 +633,12 @@
             raise ValueError('Unrecognized linestyle: %s' % style)
         self._linestyle = style
         self.set_dashes(offset, dashes)
+        
+    def set_url(self, url):
+        """
+        Sets the url for links in compatible backends
+        """
+        self._url = url
 
     def set_hatch(self, hatch):
         """
Index: lib/matplotlib/artist.py
===================================================================
--- lib/matplotlib/artist.py	(revision 6367)
+++ lib/matplotlib/artist.py	(working copy)
@@ -50,6 +50,7 @@
         self._propobservers = {} # a dict from oids to funcs
         self.axes = None
         self._remove_method = None
+        self._url = None
 
     def remove(self):
         """
@@ -313,6 +314,18 @@
         """
         return self.figure is not None
 
+    def get_url(self):
+        """
+        Returns the url
+        """
+        return self._url
+    
+    def set_url(self, url):
+        """
+        Sets the url for the artist
+        """
+        self._url = url
+
     def get_figure(self):
         """
         Return the :class:`~matplotlib.figure.Figure` instance the
Index: lib/matplotlib/patches.py
===================================================================
--- lib/matplotlib/patches.py	(revision 6367)
+++ lib/matplotlib/patches.py	(working copy)
@@ -278,6 +278,7 @@
         gc.set_antialiased(self._antialiased)
         self._set_gc_clip(gc)
         gc.set_capstyle('projecting')
+        gc.set_url(self._url)
 
         if (not self.fill or self._facecolor is None or
             (cbook.is_string_like(self._facecolor) and self._facecolor.lower()=='none')):
@@ -325,6 +326,7 @@
                     antialiased = None,
                     hatch = None,
                     fill=True,
+                    url=None,
                     **kwargs
                     ):
     """
@@ -344,6 +346,7 @@
     self.set_linestyle(linestyle)
     self.set_antialiased(antialiased)
     self.set_hatch(hatch)
+    self.set_url(url)
     self.fill = fill
     self._combined_transform = transforms.IdentityTransform()
 
Index: lib/matplotlib/axes.py
===================================================================
--- lib/matplotlib/axes.py	(revision 6367)
+++ lib/matplotlib/axes.py	(working copy)
@@ -5480,7 +5480,7 @@
     def imshow(self, X, cmap=None, norm=None, aspect=None,
                interpolation=None, alpha=1.0, vmin=None, vmax=None,
                origin=None, extent=None, shape=None, filternorm=1,
-               filterrad=4.0, imlim=None, resample=None, **kwargs):
+               filterrad=4.0, imlim=None, resample=None, url=None, **kwargs):
         """
         call signature::
 
@@ -5601,6 +5601,7 @@
             im.set_clim(vmin, vmax)
         else:
             im.autoscale_None()
+        im.set_url(url)
 
         xmin, xmax, ymin, ymax = im.get_extent()
 
Index: lib/matplotlib/collections.py
===================================================================
--- lib/matplotlib/collections.py	(revision 6367)
+++ lib/matplotlib/collections.py	(working copy)
@@ -71,6 +71,7 @@
                  norm = None,  # optional for ScalarMappable
                  cmap = None,  # ditto
                  pickradius = 5.0,
+                 urls = None,
                  **kwargs
                  ):
         """
@@ -86,6 +87,7 @@
         self.set_linewidth(linewidths)
         self.set_linestyle(linestyles)
         self.set_antialiased(antialiaseds)
+        self.set_urls(urls)
 
         self._uniform_offsets = None
         self._offsets = np.array([], np.float_)
@@ -203,7 +205,7 @@
             paths, self.get_transforms(),
             offsets, transOffset,
             self.get_facecolor(), self.get_edgecolor(), self._linewidths,
-            self._linestyles, self._antialiaseds)
+            self._linestyles, self._antialiaseds, self._urls)
         renderer.close_group(self.__class__.__name__)
 
     def contains(self, mouseevent):
@@ -227,6 +229,14 @@
     def set_pickradius(self,pickradius): self.pickradius = 5
     def get_pickradius(self): return self.pickradius
 
+    def set_urls(self, urls):
+	if urls is None:
+            self._urls = [None,]
+        else:
+            self._urls = urls
+        
+    def get_urls(self): return self._urls
+
     def set_offsets(self, offsets):
         """
         Set the offsets for the collection.  *offsets* can be a scalar
Index: lib/matplotlib/image.py
===================================================================
--- lib/matplotlib/image.py	(revision 6367)
+++ lib/matplotlib/image.py	(working copy)
@@ -62,6 +62,7 @@
                  filternorm=1,
                  filterrad=4.0,
                  resample = False,
+                 url=None,
                  **kwargs
                  ):
 
@@ -93,8 +94,8 @@
         self.set_interpolation(interpolation)
         self.set_resample(resample)
         self.axes = ax
+	self._url = url
 
-
         self._imcache = None
 
         self.update(kwargs)
@@ -116,6 +117,12 @@
         martist.Artist.set_alpha(self, alpha)
         self._imcache = None
 
+    def set_url(self, url):
+        self._url = url
+
+    def get_url(self):
+        return self._url
+
     def changed(self):
         """
         Call this whenever the mappable is changed so observers can
@@ -235,8 +242,9 @@
             warnings.warn("Images are not supported on non-linear axes.")
         im = self.make_image(renderer.get_image_magnification())
         l, b, widthDisplay, heightDisplay = self.axes.bbox.bounds
+        clippath, affine = self.get_transformed_clip_path_and_affine()
         renderer.draw_image(round(l), round(b), im, self.axes.bbox.frozen(),
-                            *self.get_transformed_clip_path_and_affine())
+                            clippath, affine, self._url)
 
     def contains(self, mouseevent):
         """Test whether the mouse event occured within the image.
Index: lib/matplotlib/backends/backend_ps.py
===================================================================
--- lib/matplotlib/backends/backend_ps.py	(revision 6367)
+++ lib/matplotlib/backends/backend_ps.py	(working copy)
@@ -400,7 +400,7 @@
         """
         return self.image_magnification
 
-    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
+    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None, url=None):
         """
         Draw the Image instance into the current axes; x is the
         distance in pixels from the left hand side of the canvas and y
@@ -531,7 +531,7 @@
     def draw_path_collection(self, master_transform, cliprect, clippath,
                              clippath_trans, paths, all_transforms, offsets,
                              offsetTrans, facecolors, edgecolors, linewidths,
-                             linestyles, antialiaseds):
+                             linestyles, antialiaseds, urls):
         write = self._pswriter.write
 
         path_codes = []
@@ -548,7 +548,7 @@
         for xo, yo, path_id, gc, rgbFace in self._iter_collection(
             path_codes, cliprect, clippath, clippath_trans,
             offsets, offsetTrans, facecolors, edgecolors,
-            linewidths, linestyles, antialiaseds):
+            linewidths, linestyles, antialiaseds, urls):
 
             ps = "%g %g %s" % (xo, yo, path_id)
             self._draw_ps(ps, gc, rgbFace)
Index: lib/matplotlib/backends/backend_cairo.py
===================================================================
--- lib/matplotlib/backends/backend_cairo.py	(revision 6367)
+++ lib/matplotlib/backends/backend_cairo.py	(working copy)
@@ -153,7 +153,7 @@
 
         self._fill_and_stroke(ctx, rgbFace, gc.get_alpha())
 
-    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
+    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None, url=None):
         # bbox - not currently used
         if _debug: print '%s.%s()' % (self.__class__.__name__, _fn_name())
 
Index: lib/matplotlib/backends/backend_wx.py
===================================================================
--- lib/matplotlib/backends/backend_wx.py	(revision 6367)
+++ lib/matplotlib/backends/backend_wx.py	(working copy)
@@ -334,7 +334,7 @@
             gfx_ctx.StrokePath(wxpath)
         gc.unselect()
 
-    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
+    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None, url=None):
         if bbox != None:
             l,b,w,h = bbox.bounds
         else:
Index: lib/matplotlib/backends/backend_svg.py
===================================================================
--- lib/matplotlib/backends/backend_svg.py	(revision 6367)
+++ lib/matplotlib/backends/backend_svg.py	(working copy)
@@ -67,9 +67,13 @@
         else:
             clippath = 'clip-path="url(#%s)"' % clipid
 
+        if gc.get_url() is not None:
+            self._svgwriter.write('<a xlink:href="%s">' % gc.get_url())
         style = self._get_style(gc, rgbFace)
         self._svgwriter.write ('<%s style="%s" %s %s/>\n' % (
                 element, style, clippath, details))
+        if gc.get_url() is not None:
+            self._svgwriter.write('</a>')
 
     def _get_font(self, prop):
         key = hash(prop)
@@ -224,7 +228,7 @@
     def draw_path_collection(self, master_transform, cliprect, clippath,
                              clippath_trans, paths, all_transforms, offsets,
                              offsetTrans, facecolors, edgecolors, linewidths,
-                             linestyles, antialiaseds):
+                             linestyles, antialiaseds, urls):
         write = self._svgwriter.write
 
         path_codes = []
@@ -242,8 +246,11 @@
         for xo, yo, path_id, gc, rgbFace in self._iter_collection(
             path_codes, cliprect, clippath, clippath_trans,
             offsets, offsetTrans, facecolors, edgecolors,
-            linewidths, linestyles, antialiaseds):
+            linewidths, linestyles, antialiaseds, urls):
             clipid = self._get_gc_clip_svg(gc)
+            url = gc.get_url()
+            if url is not None:
+                self._svgwriter.write('<a xlink:href="%s">' % url)
             if clipid is not None:
                 write('<g clip-path="url(#%s)">' % clipid)
             details = 'xlink:href="#%s" x="%f" y="%f"' % (path_id, xo, self.height - yo)
@@ -251,10 +258,12 @@
             self._svgwriter.write ('<use style="%s" %s/>\n' % (style, details))
             if clipid is not None:
                 write('</g>')
+            if url is not None:
+                self._svgwriter.write('</a>')
 
         self._path_collection_id += 1
 
-    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
+    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None, url=None):
         # MGDTODO: Support clippath here
         trans = [1,0,0,1,0,0]
         transstr = ''
@@ -274,6 +283,8 @@
 
         h,w = im.get_size_out()
 
+        if url is not None:
+            self._svgwriter.write('<a xlink:href="%s">' % url)
         self._svgwriter.write (
             '<image x="%f" y="%f" width="%f" height="%f" '
             '%s xlink:href="'%(x/trans[0], (self.height-y)/trans[3]-h, w, h, transstr)
@@ -298,6 +309,8 @@
             self._svgwriter.write(filename)
 
         self._svgwriter.write('"/>\n')
+        if url is not None:
+            self._svgwriter.write('</a>')
 
     def draw_text(self, gc, x, y, s, prop, angle, ismath):
         if ismath:
Index: lib/matplotlib/backends/backend_gdk.py
===================================================================
--- lib/matplotlib/backends/backend_gdk.py	(revision 6367)
+++ lib/matplotlib/backends/backend_gdk.py	(working copy)
@@ -97,7 +97,7 @@
             if gc.gdkGC.line_width > 0:
                 self.gdkDrawable.draw_lines(gc.gdkGC, polygon)
 
-    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
+    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None, url=None):
         if bbox != None:
             l,b,w,h = bbox.bounds
             #rectangle = (int(l), self.height-int(b+h),
Index: lib/matplotlib/backends/backend_mixed.py
===================================================================
--- lib/matplotlib/backends/backend_mixed.py	(revision 6367)
+++ lib/matplotlib/backends/backend_mixed.py	(working copy)
@@ -91,6 +91,6 @@
                 image = frombuffer(buffer, w, h, True)
                 image.is_grayscale = False
                 image.flipud_out()
-                self._renderer.draw_image(l, height - b - h, image, None)
+                self._renderer.draw_image(l, height - b - h, image, None, None)
             self._raster_renderer = None
             self._rasterizing = False
Index: lib/matplotlib/backends/backend_pdf.py
===================================================================
--- lib/matplotlib/backends/backend_pdf.py	(revision 6367)
+++ lib/matplotlib/backends/backend_pdf.py	(working copy)
@@ -1230,7 +1230,7 @@
                 stat_key, (realpath, set()))
             used_characters[1].update(charset)
 
-    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
+    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None, url=None):
         #print >>sys.stderr, "draw_image called"
 
         # MGDTODO: Support clippath here
Index: lib/matplotlib/backends/backend_template.py
===================================================================
--- lib/matplotlib/backends/backend_template.py	(revision 6367)
+++ lib/matplotlib/backends/backend_template.py	(working copy)
@@ -102,7 +102,7 @@
 #                        showedges):
 #         pass
 
-    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
+    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None, url=None):
         pass
 
     def draw_text(self, gc, x, y, s, prop, angle, ismath=False):
Index: lib/matplotlib/text.py
===================================================================
--- lib/matplotlib/text.py	(revision 6367)
+++ lib/matplotlib/text.py	(working copy)
@@ -464,6 +464,7 @@
         gc = renderer.new_gc()
         gc.set_foreground(self._color)
         gc.set_alpha(self._alpha)
+        gc.set_url(self._url)
         if self.get_clip_on():
             gc.set_clip_rectangle(self.clipbox)
 
