From: <md...@us...> - 2009-08-07 17:02:37
|
Revision: 7417 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7417&view=rev Author: mdboom Date: 2009-08-07 17:02:28 +0000 (Fri, 07 Aug 2009) Log Message: ----------- Refactor some backend methods for consistency and to reduce explosion of the number of arguments. A first crack at Gouraud shading in the Agg backend (not hooked up to anything). Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/api/api_changes.rst trunk/matplotlib/examples/pylab_examples/quadmesh_demo.py trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/backends/backend_agg.py trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py trunk/matplotlib/lib/matplotlib/backends/backend_mixed.py trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py trunk/matplotlib/lib/matplotlib/backends/backend_ps.py trunk/matplotlib/lib/matplotlib/backends/backend_svg.py trunk/matplotlib/lib/matplotlib/backends/backend_template.py trunk/matplotlib/lib/matplotlib/backends/backend_wx.py trunk/matplotlib/lib/matplotlib/collections.py trunk/matplotlib/lib/matplotlib/figure.py trunk/matplotlib/lib/matplotlib/font_manager.py trunk/matplotlib/lib/matplotlib/image.py trunk/matplotlib/src/_backend_agg.cpp trunk/matplotlib/src/_backend_agg.h Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/CHANGELOG 2009-08-07 17:02:28 UTC (rev 7417) @@ -1,3 +1,41 @@ +2009-08-07 In an effort to simplify the backend API, all clipping rectangles + and paths are now passed in using GraphicsContext objects, even + on collections and images. Therefore: + + draw_path_collection(self, master_transform, cliprect, clippath, + clippath_trans, paths, all_transforms, offsets, + offsetTrans, facecolors, edgecolors, linewidths, + linestyles, antialiaseds, urls) + + becomes: + + draw_path_collection(self, gc, master_transform, paths, all_transforms, + offsets, offsetTrans, facecolors, edgecolors, + linewidths, linestyles, antialiaseds, urls) + + + + draw_quad_mesh(self, master_transform, cliprect, clippath, + clippath_trans, meshWidth, meshHeight, coordinates, + offsets, offsetTrans, facecolors, antialiased, + showedges) + + becomes: + + draw_quad_mesh(self, gc, master_transform, meshWidth, meshHeight, + coordinates, offsets, offsetTrans, facecolors, + antialiased, showedges) + + + + draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None) + + becomes: + + draw_image(self, gc, x, y, im) + + - MGD + 2009-08-06 Tagging the 0.99.0 release at svn r7397 - JDH * fixed an alpha colormapping bug posted on sf 2832575 @@ -30,7 +68,6 @@ * apply sf patches 2830233 and 2823885 for osx setup and 64 bit; thanks Michiel - 2009-08-04 Made cbook.get_sample_data make use of the ETag and Last-Modified headers of mod_dav_svn. - JKS Modified: trunk/matplotlib/doc/api/api_changes.rst =================================================================== --- trunk/matplotlib/doc/api/api_changes.rst 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/doc/api/api_changes.rst 2009-08-07 17:02:28 UTC (rev 7417) @@ -18,6 +18,43 @@ .. _configobj: http://www.voidspace.org.uk/python/configobj.html .. _`enthought.traits`: http://code.enthought.com/projects/traits +Changes beyond 0.99.x +===================== + +In an effort to simplify the backend API, all clipping rectangles +and paths are now passed in using GraphicsContext objects, even +on collections and images. Therefore:: + + draw_path_collection(self, master_transform, cliprect, clippath, + clippath_trans, paths, all_transforms, offsets, + offsetTrans, facecolors, edgecolors, linewidths, + linestyles, antialiaseds, urls) + + # is now + + draw_path_collection(self, gc, master_transform, paths, all_transforms, + offsets, offsetTrans, facecolors, edgecolors, + linewidths, linestyles, antialiaseds, urls) + + + draw_quad_mesh(self, master_transform, cliprect, clippath, + clippath_trans, meshWidth, meshHeight, coordinates, + offsets, offsetTrans, facecolors, antialiased, + showedges) + + # is now + + draw_quad_mesh(self, gc, master_transform, meshWidth, meshHeight, + coordinates, offsets, offsetTrans, facecolors, + antialiased, showedges) + + + draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None) + + # is now + + draw_image(self, gc, x, y, im) + Changes in 0.99 ====================== Modified: trunk/matplotlib/examples/pylab_examples/quadmesh_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/quadmesh_demo.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/examples/pylab_examples/quadmesh_demo.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -11,7 +11,7 @@ from matplotlib import cm, colors from numpy import ma -n = 56 +n = 12 x = np.linspace(-1.5,1.5,n) y = np.linspace(-1.5,1.5,n*2) X,Y = np.meshgrid(x,y); Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/axes.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -1705,12 +1705,14 @@ l, b, w, h = self.bbox.bounds # composite images need special args so they will not # respect z-order for now - renderer.draw_image( - round(l), round(b), im, self.bbox, - self.patch.get_path(), - self.patch.get_transform()) + gc = renderer.new_gc() + gc.set_clip_rectangle(self.bbox) + gc.set_clip_path(mtransforms.TransformedPath( + self.patch.get_path(), + self.patch.get_transform())) + renderer.draw_image(gc, round(l), round(b), im) if dsu_rasterized: for zorder, i, a in dsu_rasterized: Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -108,24 +108,23 @@ marker_trans + transforms.Affine2D().translate(x, y), rgbFace) - def draw_path_collection(self, master_transform, cliprect, clippath, - clippath_trans, paths, all_transforms, offsets, - offsetTrans, facecolors, edgecolors, linewidths, - linestyles, antialiaseds, urls): + def draw_path_collection(self, gc, master_transform, paths, all_transforms, + offsets, offsetTrans, facecolors, edgecolors, + linewidths, linestyles, antialiaseds, urls): """ - Draws a collection of paths, selecting drawing properties from + Draws a collection of paths selecting drawing properties from the lists *facecolors*, *edgecolors*, *linewidths*, *linestyles* and *antialiaseds*. *offsets* is a list of offsets to apply to each of the paths. The offsets in - *offsets* are first transformed by *offsetTrans* before - being applied. + *offsets* are first transformed by *offsetTrans* before being + applied. This provides a fallback implementation of :meth:`draw_path_collection` that makes multiple calls to - draw_path. Some backends may want to override this in order - to render each set of path data only once, and then reference - that path multiple times with the different offsets, colors, - styles etc. The generator methods + :meth:`draw_path`. Some backends may want to override this in + order to render each set of path data only once, and then + reference that path multiple times with the different offsets, + colors, styles etc. The generator methods :meth:`_iter_collection_raw_paths` and :meth:`_iter_collection` are provided to help with (and standardize) the implementation across backends. It is highly @@ -137,18 +136,16 @@ master_transform, paths, all_transforms): path_ids.append((path, transform)) - for xo, yo, path_id, gc, rgbFace in self._iter_collection( - path_ids, cliprect, clippath, clippath_trans, - offsets, offsetTrans, facecolors, edgecolors, + for xo, yo, path_id, gc0, rgbFace in self._iter_collection( + gc, path_ids, offsets, offsetTrans, facecolors, edgecolors, linewidths, linestyles, antialiaseds, urls): path, transform = path_id transform = transforms.Affine2D(transform.get_matrix()).translate(xo, yo) - self.draw_path(gc, path, transform, rgbFace) + self.draw_path(gc0, path, transform, rgbFace) - def draw_quad_mesh(self, master_transform, cliprect, clippath, - clippath_trans, meshWidth, meshHeight, coordinates, - offsets, offsetTrans, facecolors, antialiased, - showedges): + def draw_quad_mesh(self, gc, master_transform, meshWidth, meshHeight, + coordinates, offsets, offsetTrans, facecolors, + antialiased, showedges): """ This provides a fallback implementation of :meth:`draw_quad_mesh` that generates paths and then calls @@ -166,11 +163,11 @@ linewidths = np.array([0.0], np.float_) return self.draw_path_collection( - master_transform, cliprect, clippath, clippath_trans, - paths, [], offsets, offsetTrans, facecolors, edgecolors, - linewidths, [], [antialiased], [None]) + gc, master_transform, paths, [], offsets, offsetTrans, facecolors, + edgecolors, linewidths, [], [antialiased], [None]) - def _iter_collection_raw_paths(self, master_transform, paths, all_transforms): + def _iter_collection_raw_paths(self, master_transform, paths, + all_transforms): """ This is a helper method (along with :meth:`_iter_collection`) to make it easier to write a space-efficent :meth:`draw_path_collection` @@ -200,9 +197,9 @@ transform = all_transforms[i % Ntransforms] yield path, transform + master_transform - def _iter_collection(self, path_ids, cliprect, clippath, clippath_trans, - offsets, offsetTrans, facecolors, edgecolors, - linewidths, linestyles, antialiaseds, urls): + def _iter_collection(self, gc, path_ids, offsets, offsetTrans, facecolors, + edgecolors, linewidths, linestyles, antialiaseds, + urls): """ This is a helper method (along with :meth:`_iter_collection_raw_paths`) to make it easier to write @@ -243,18 +240,14 @@ if Noffsets: toffsets = offsetTrans.transform(offsets) - gc = self.new_gc() + gc0 = self.new_gc() + gc0.copy_properties(gc) - gc.set_clip_rectangle(cliprect) - if clippath is not None: - clippath = transforms.TransformedPath(clippath, clippath_trans) - gc.set_clip_path(clippath) - if Nfacecolors == 0: rgbFace = None if Nedgecolors == 0: - gc.set_linewidth(0.0) + gc0.set_linewidth(0.0) xo, yo = 0, 0 for i in xrange(N): @@ -264,20 +257,20 @@ if Nfacecolors: rgbFace = facecolors[i % Nfacecolors] if Nedgecolors: - gc.set_foreground(edgecolors[i % Nedgecolors]) + gc0.set_foreground(edgecolors[i % Nedgecolors]) if Nlinewidths: - gc.set_linewidth(linewidths[i % Nlinewidths]) + gc0.set_linewidth(linewidths[i % Nlinewidths]) if Nlinestyles: - gc.set_dashes(*linestyles[i % Nlinestyles]) + gc0.set_dashes(*linestyles[i % Nlinestyles]) if rgbFace is not None and len(rgbFace)==4: - gc.set_alpha(rgbFace[-1]) + gc0.set_alpha(rgbFace[-1]) rgbFace = rgbFace[:3] - gc.set_antialiased(antialiaseds[i % Naa]) + gc0.set_antialiased(antialiaseds[i % Naa]) if Nurls: - gc.set_url(urls[i % Nurls]) + gc0.set_url(urls[i % Nurls]) - yield xo, yo, path_id, gc, rgbFace - gc.restore() + yield xo, yo, path_id, gc0, rgbFace + gc0.restore() def get_image_magnification(self): """ @@ -287,10 +280,13 @@ """ return 1.0 - def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None): + def draw_image(self, gc, x, y, im): """ Draw the image instance into the current axes; + *gc* + a GraphicsContext containing clipping information + *x* is the distance in pixels from the left hand side of the canvas. @@ -301,11 +297,6 @@ *im* the :class:`matplotlib._image.Image` instance - - *bbox* - a :class:`matplotlib.transforms.Bbox` instance for clipping, or - None - """ raise NotImplementedError Modified: trunk/matplotlib/lib/matplotlib/backends/backend_agg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -250,7 +250,7 @@ >>> x1, y1, x2, y2 = region.get_extents() >>> renderer.restore_region(region, bbox=(x1+dx, y1, x2, y2), xy=(x1-dx, y1)) - + """ if bbox is not None or xy is not None: if bbox is None: Modified: trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -151,10 +151,12 @@ 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, gc, x, y, im): # bbox - not currently used if _debug: print '%s.%s()' % (self.__class__.__name__, _fn_name()) + clippath, clippath_trans = gc.get_clip_path() + im.flipud_out() rows, cols, buf = im.color_conv (BYTE_FORMAT) Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -97,7 +97,9 @@ 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, gc, x, y, im): + bbox = gc.get_clip_rectangle() + if bbox != None: l,b,w,h = bbox.bounds #rectangle = (int(l), self.height-int(b+h), Modified: trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -59,12 +59,19 @@ gc.draw_markers(marker_path, marker_trans, path, trans, rgbFace) def draw_path_collection(self, *args): - gc = self.gc - args = args[:13] + # TODO: We should change this in the C code eventually, but this + # re-ordering of arguments should work for now + gc = args[0] + args = tuple([gc, args[1], gc.get_clip_rectangle()] + \ + list(gc.get_clip_path()) + list(args[2:])) gc.draw_path_collection(*args) def draw_quad_mesh(self, *args): - gc = self.gc + # TODO: We should change this in the C code eventually, but this + # re-ordering of arguments should work for now + gc = args[0] + args = [gc, args[1], gc.get_clip_rectangle()] + \ + list(gc.get_clip_path()) + list(args[2:]) gc.draw_quad_mesh(*args) def new_gc(self): @@ -72,12 +79,15 @@ self.gc.set_hatch(None) return self.gc - def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None): + def draw_image(self, gc, x, y, im): + # TODO: We should change this in the C code eventually, but this + # re-ordering of arguments should work for now im.flipud_out() nrows, ncols, data = im.as_rgba_str() - self.gc.draw_image(x, y, nrows, ncols, data, bbox, clippath, clippath_trans) + gc.draw_image(x, y, nrows, ncols, data, gc.get_clip_rectangle(), + *gc.get_clip_path()) im.flipud_out() - + def draw_tex(self, gc, x, y, s, prop, angle): # todo, handle props, angle, origins size = prop.get_size_in_points() @@ -128,7 +138,7 @@ def flipy(self): return False - + def points_to_pixels(self, points): return points/72.0 * self.dpi @@ -168,7 +178,7 @@ _macosx.GraphicsContext.set_clip_path(self, path) ######################################################################## -# +# # The following functions and classes are for pylab and implement # window/figure managers, etc... # @@ -281,7 +291,7 @@ self.toolbar = NavigationToolbar2Mac(canvas) else: self.toolbar = None - if self.toolbar is not None: + if self.toolbar is not None: self.toolbar.update() def notify_axes_change(fig): @@ -300,7 +310,7 @@ Gcf.destroy(self.num) class NavigationToolbarMac(_macosx.NavigationToolbar): - + def __init__(self, canvas): self.canvas = canvas basedir = os.path.join(matplotlib.rcParams['datapath'], "images") @@ -331,7 +341,7 @@ assert magic=="P6" assert len(imagedata)==width*height*3 # 3 colors in RGB return (width, height, imagedata) - + def panx(self, direction): axes = self.canvas.figure.axes selected = self.get_active() @@ -401,9 +411,9 @@ _macosx.NavigationToolbar2.set_message(self, message.encode('utf-8')) ######################################################################## -# +# # Now just provide the standard names that backend.__init__ is expecting -# +# ######################################################################## Modified: trunk/matplotlib/lib/matplotlib/backends/backend_mixed.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_mixed.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/backends/backend_mixed.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -14,7 +14,7 @@ raster_renderer_class=None, bbox_inches_restore=None): """ - figure: The figure instance. + figure: The figure instance. width: The width of the canvas in logical units @@ -49,7 +49,7 @@ self.figure=figure self._bbox_inches_restore = bbox_inches_restore - + self._set_current_renderer(vector_renderer) _methods = """ @@ -88,8 +88,8 @@ mode="png") self._bbox_inches_restore = r - - + + if self._rasterizing == 0: self._raster_renderer = self._raster_renderer_class( self._width*self.dpi, self._height*self.dpi, self.dpi) @@ -117,9 +117,12 @@ image = frombuffer(buffer, w, h, True) image.is_grayscale = False image.flipud_out() - self._renderer.draw_image(int(float(l)/self.dpi*72.), - int((float(height) - b - h)/self.dpi*72.), - image, None) + gc = self._renderer.new_gc() + self._renderer.draw_image( + gc, + int(float(l)/self.dpi*72.), + int((float(height) - b - h)/self.dpi*72.), + image) self._raster_renderer = None self._rasterizing = False Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -1286,13 +1286,7 @@ def get_image_magnification(self): return self.image_dpi/72.0 - def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None): - gc = self.new_gc() - if bbox is not None: - gc.set_clip_rectangle(bbox) - if clippath is not None: - clippath = TransformedPath(clippath, clippath_trans) - gc.set_clip_path(clippath) + def draw_image(self, gc, x, y, im): self.check_gc(gc) h, w = im.get_size_out() Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -374,7 +374,7 @@ """ return self.image_magnification - def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None): + def draw_image(self, gc, x, y, im): """ Draw the Image instance into the current axes; x is the distance in pixels from the left hand side of the canvas and y @@ -400,6 +400,9 @@ figh = self.height*72 #print 'values', origin, flipud, figh, h, y + bbox = gc.get_clip_rectangle() + clippath, clippath_trans = gc.get_clip_path() + clip = [] if bbox is not None: clipx,clipy,clipw,cliph = bbox.bounds @@ -504,10 +507,9 @@ ps = '\n'.join(ps_cmd) self._draw_ps(ps, gc, rgbFace, fill=False, stroke=False) - def draw_path_collection(self, master_transform, cliprect, clippath, - clippath_trans, paths, all_transforms, offsets, - offsetTrans, facecolors, edgecolors, linewidths, - linestyles, antialiaseds, urls): + def draw_path_collection(self, gc, master_transform, paths, all_transforms, + offsets, offsetTrans, facecolors, edgecolors, + linewidths, linestyles, antialiaseds, urls): write = self._pswriter.write path_codes = [] @@ -521,13 +523,11 @@ write('\n'.join(ps_cmd)) path_codes.append(name) - for xo, yo, path_id, gc, rgbFace in self._iter_collection( - path_codes, cliprect, clippath, clippath_trans, - offsets, offsetTrans, facecolors, edgecolors, + for xo, yo, path_id, gc0, rgbFace in self._iter_collection( + gc, path_codes, offsets, offsetTrans, facecolors, edgecolors, linewidths, linestyles, antialiaseds, urls): - ps = "%g %g %s" % (xo, yo, path_id) - self._draw_ps(ps, gc, rgbFace) + self._draw_ps(ps, gc0, rgbFace) self._path_collection_id += 1 @@ -964,7 +964,7 @@ class NullWriter(object): def write(self, *kl, **kwargs): pass - + self._pswriter = NullWriter() else: self._pswriter = StringIO() @@ -1096,7 +1096,7 @@ class NullWriter(object): def write(self, *kl, **kwargs): pass - + self._pswriter = NullWriter() else: self._pswriter = StringIO() Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -262,10 +262,9 @@ self._svgwriter.write ('<use style="%s" %s/>\n' % (style, details)) write('</g>') - def draw_path_collection(self, master_transform, cliprect, clippath, - clippath_trans, paths, all_transforms, offsets, - offsetTrans, facecolors, edgecolors, linewidths, - linestyles, antialiaseds, urls): + def draw_path_collection(self, gc, master_transform, paths, all_transforms, + offsets, offsetTrans, facecolors, edgecolors, + linewidths, linestyles, antialiaseds, urls): write = self._svgwriter.write path_codes = [] @@ -280,18 +279,17 @@ path_codes.append(name) write('</defs>\n') - for xo, yo, path_id, gc, rgbFace in self._iter_collection( - path_codes, cliprect, clippath, clippath_trans, - offsets, offsetTrans, facecolors, edgecolors, + for xo, yo, path_id, gc0, rgbFace in self._iter_collection( + gc, path_codes, offsets, offsetTrans, facecolors, edgecolors, linewidths, linestyles, antialiaseds, urls): - clipid = self._get_gc_clip_svg(gc) - url = gc.get_url() + clipid = self._get_gc_clip_svg(gc0) + url = gc0.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) - style = self._get_style(gc, rgbFace) + style = self._get_style(gc0, rgbFace) self._svgwriter.write ('<use style="%s" %s/>\n' % (style, details)) if clipid is not None: write('</g>') @@ -300,7 +298,7 @@ self._path_collection_id += 1 - def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None): + def draw_image(self, gc, x, y, im): # MGDTODO: Support clippath here trans = [1,0,0,1,0,0] transstr = '' @@ -643,7 +641,7 @@ # the problem. I hope someone who knows the svg backends # take a look at this problem. Meanwhile, the dpi # parameter is ignored and image_dpi is fixed at 72. - JJL - + #image_dpi = kwargs.pop("dpi", 72) image_dpi = 72 _bbox_inches_restore = kwargs.pop("bbox_inches_restore", None) Modified: trunk/matplotlib/lib/matplotlib/backends/backend_template.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_template.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/backends/backend_template.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -87,22 +87,21 @@ # draw_path_collection is optional, and we get more correct # relative timings by leaving it out. backend implementers concerned with # performance will probably want to implement it -# def draw_path_collection(self, master_transform, cliprect, clippath, -# clippath_trans, paths, all_transforms, offsets, -# offsetTrans, facecolors, edgecolors, linewidths, -# linestyles, antialiaseds): +# def draw_path_collection(self, gc, master_transform, paths, +# all_transforms, offsets, offsetTrans, facecolors, +# edgecolors, linewidths, linestyles, +# antialiaseds): # pass # draw_quad_mesh is optional, and we get more correct # relative timings by leaving it out. backend implementers concerned with # performance will probably want to implement it -# def draw_quad_mesh(self, master_transform, cliprect, clippath, -# clippath_trans, meshWidth, meshHeight, coordinates, -# offsets, offsetTrans, facecolors, antialiased, -# showedges): +# def draw_quad_mesh(self, gc, master_transform, meshWidth, meshHeight, +# coordinates, offsets, offsetTrans, facecolors, +# antialiased, showedges): # pass - def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None): + def draw_image(self, gc, x, y, im): pass def draw_text(self, gc, x, y, s, prop, angle, ismath=False): Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wx.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -361,7 +361,8 @@ gfx_ctx.StrokePath(wxpath) gc.unselect() - def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None): + def draw_image(self, gc, x, y, im): + bbox = gc.get_clip_rectangle() if bbox != None: l,b,w,h = bbox.bounds else: @@ -776,7 +777,7 @@ bind(self, wx.EVT_MIDDLE_DOWN, self._onMiddleButtonDown) bind(self, wx.EVT_MIDDLE_DCLICK, self._onMiddleButtonDown) bind(self, wx.EVT_MIDDLE_UP, self._onMiddleButtonUp) - + self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) self.macros = {} # dict from wx id to seq of macros @@ -1257,7 +1258,7 @@ if self.HasCapture(): self.ReleaseMouse() FigureCanvasBase.button_release_event(self, x, y, 1, guiEvent=evt) - #Add middle button events + #Add middle button events def _onMiddleButtonDown(self, evt): """Start measuring on an axis.""" x = evt.GetX() Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/collections.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -204,18 +204,16 @@ self.update_scalarmappable() - clippath, clippath_trans = self.get_transformed_clip_path_and_affine() - if clippath_trans is not None: - clippath_trans = clippath_trans.frozen() - transform, transOffset, offsets, paths = self._prepare_points() + gc = renderer.new_gc() + gc.set_clip_rectangle(self.get_clip_box()) + gc.set_clip_path(self.get_clip_path()) + renderer.draw_path_collection( - transform.frozen(), self.clipbox, clippath, clippath_trans, - paths, self.get_transforms(), - offsets, transOffset, - self.get_facecolor(), self.get_edgecolor(), self._linewidths, - self._linestyles, self._antialiaseds, self._urls) + gc, transform.frozen(), paths, self.get_transforms(), + offsets, transOffset, self.get_facecolor(), self.get_edgecolor(), + self._linewidths, self._linestyles, self._antialiaseds, self._urls) renderer.close_group(self.__class__.__name__) def contains(self, mouseevent): @@ -1149,10 +1147,6 @@ if self.check_update('array'): self.update_scalarmappable() - clippath, clippath_trans = self.get_transformed_clip_path_and_affine() - if clippath_trans is not None: - clippath_trans = clippath_trans.frozen() - if not transform.is_affine: coordinates = self._coordinates.reshape( (self._coordinates.shape[0] * @@ -1168,11 +1162,14 @@ offsets = transOffset.transform_non_affine(offsets) transOffset = transOffset.get_affine() + gc = renderer.new_gc() + gc.set_clip_rectangle(self.get_clip_box()) + gc.set_clip_path(self.get_clip_path()) + renderer.draw_quad_mesh( - transform.frozen(), self.clipbox, clippath, clippath_trans, - self._meshWidth, self._meshHeight, coordinates, - offsets, transOffset, self.get_facecolor(), self._antialiased, - self._showedges) + gc, transform.frozen(), self._meshWidth, self._meshHeight, + coordinates, offsets, transOffset, self.get_facecolor(), + self._antialiased, self._showedges) renderer.close_group(self.__class__.__name__) Modified: trunk/matplotlib/lib/matplotlib/figure.py =================================================================== --- trunk/matplotlib/lib/matplotlib/figure.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/figure.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -766,9 +766,10 @@ im.is_grayscale = False l, b, w, h = self.bbox.bounds - clippath, affine = self.get_transformed_clip_path_and_affine() - renderer.draw_image(l, b, im, self.bbox, - clippath, affine) + gc = renderer.new_gc() + gc.set_clip_rectangle(self.bbox) + gc.set_clip_path(self.get_clip_path()) + renderer.draw_image(gc, l, b, im) # render the axes for a in self.axes: a.draw(renderer) @@ -851,7 +852,7 @@ *fancybox*: [ None | False | True ] if True, draw a frame with a round fancybox. If None, use rc - + *shadow*: [ None | False | True ] If *True*, draw a shadow behind legend. If *None*, use rc settings. Modified: trunk/matplotlib/lib/matplotlib/font_manager.py =================================================================== --- trunk/matplotlib/lib/matplotlib/font_manager.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/font_manager.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -707,7 +707,7 @@ def __hash__(self): l = [(k, getattr(self, "get" + k)()) for k in sorted(self.__dict__)] return hash(repr(l)) - + def __str__(self): return self.get_fontconfig_pattern() Modified: trunk/matplotlib/lib/matplotlib/image.py =================================================================== --- trunk/matplotlib/lib/matplotlib/image.py 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/lib/matplotlib/image.py 2009-08-07 17:02:28 UTC (rev 7417) @@ -235,9 +235,10 @@ im = self.make_image(renderer.get_image_magnification()) im._url = self.get_url() 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(), - clippath, affine) + gc = renderer.new_gc() + gc.set_clip_rectangle(self.axes.bbox.frozen()) + gc.set_clip_path(self.get_clip_path()) + renderer.draw_image(gc, round(l), round(b), im) def contains(self, mouseevent): """ @@ -576,11 +577,13 @@ def draw(self, renderer, *args, **kwargs): if not self.get_visible(): return im = self.make_image(renderer.get_image_magnification()) - renderer.draw_image(round(self.axes.bbox.xmin), + gc = renderer.new_gc() + gc.set_clip_rectangle(self.axes.bbox.frozen()) + gc.set_clip_path(self.get_clip_path()) + renderer.draw_image(gc, + round(self.axes.bbox.xmin), round(self.axes.bbox.ymin), - im, - self.axes.bbox.frozen(), - *self.get_transformed_clip_path_and_affine()) + im) def set_data(self, x, y, A): @@ -730,8 +733,10 @@ if not self.get_visible(): return # todo: we should be able to do some cacheing here im = self.make_image(renderer.get_image_magnification()) - renderer.draw_image(round(self.ox), round(self.oy), im, self.figure.bbox, - *self.get_transformed_clip_path_and_affine()) + gc = renderer.new_gc() + gc.set_clip_rectangle(self.figure.bbox) + gc.set_clip_path(self.get_clip_path()) + renderer.draw_image(gc, round(self.ox), round(self.oy), im) def write_png(self, fname): """Write the image to png file with fname""" Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/src/_backend_agg.cpp 2009-08-07 17:02:28 UTC (rev 7417) @@ -31,6 +31,7 @@ #include "agg_span_image_filter_rgba.h" #include "agg_span_interpolator_linear.h" #include "agg_span_pattern_rgba.h" +#include "agg_span_gouraud_rgba.h" #include "agg_conv_shorten_path.h" #include "util/agg_color_conv_rgb8.h" @@ -799,23 +800,17 @@ RendererAgg::draw_image(const Py::Tuple& args) { _VERBOSE("RendererAgg::draw_image"); - args.verify_length(4, 6); + args.verify_length(4); - double x = Py::Float(args[0]); - double y = Py::Float(args[1]); - Image *image = static_cast<Image*>(args[2].ptr()); - Py::Object box_obj = args[3]; - Py::Object clippath; - agg::trans_affine clippath_trans; + GCAgg gc(args[0], dpi); + double x = Py::Float(args[1]); + double y = Py::Float(args[2]); + Image *image = static_cast<Image*>(args[3].ptr()); bool has_clippath = false; theRasterizer.reset_clipping(); rendererBase.reset_clipping(true); - if (args.size() == 6) { - clippath = args[4]; - clippath_trans = py_to_agg_transformation_matrix(args[5].ptr(), false); - has_clippath = render_clippath(clippath, clippath_trans); - } + has_clippath = render_clippath(gc.clippath, gc.clippath_trans); Py::Tuple empty; image->flipud_out(empty); @@ -855,7 +850,7 @@ theRasterizer.add_path(rect2); agg::render_scanlines(theRasterizer, slineP8, ri); } else { - set_clipbox(box_obj, rendererBase); + set_clipbox(gc.cliprect, rendererBase); rendererBase.blend_from(pixf, 0, (int)x, (int)(height-(y+image->rowsOut))); } @@ -1026,15 +1021,13 @@ _VERBOSE("RendererAgg::draw_path"); args.verify_length(3, 4); - Py::Object gc_obj = args[0]; - Py::Object path_obj = args[1]; + GCAgg gc(args[0], dpi); + PathIterator path(args[1]); agg::trans_affine trans = py_to_agg_transformation_matrix(args[2].ptr()); Py::Object face_obj; if (args.size() == 4) face_obj = args[3]; - PathIterator path(path_obj); - GCAgg gc = GCAgg(gc_obj, dpi); facepair_t face = _get_rgba_face(face_obj, gc.alpha); theRasterizer.reset_clipping(); @@ -1275,32 +1268,29 @@ Py::Object RendererAgg::draw_path_collection(const Py::Tuple& args) { _VERBOSE("RendererAgg::draw_path_collection"); - args.verify_length(14); + args.verify_length(12); - //segments, trans, clipbox, colors, linewidths, antialiaseds - agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[0].ptr()); - Py::Object cliprect = args[1]; - Py::Object clippath = args[2]; - agg::trans_affine clippath_trans = py_to_agg_transformation_matrix(args[3].ptr(), false); - Py::SeqBase<Py::Object> paths = args[4]; - Py::SeqBase<Py::Object> transforms_obj = args[5]; - Py::Object offsets_obj = args[6]; - agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[7].ptr()); - Py::Object facecolors_obj = args[8]; - Py::Object edgecolors_obj = args[9]; - Py::SeqBase<Py::Float> linewidths = args[10]; - Py::SeqBase<Py::Object> linestyles_obj = args[11]; - Py::SeqBase<Py::Int> antialiaseds = args[12]; + GCAgg gc(args[0], dpi); + agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[1].ptr()); + PathListGenerator paths(args[2]); + Py::SeqBase<Py::Object> transforms_obj = args[3]; + Py::Object offsets_obj = args[4]; + agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[5].ptr()); + Py::Object facecolors_obj = args[6]; + Py::Object edgecolors_obj = args[7]; + Py::SeqBase<Py::Float> linewidths = args[8]; + Py::SeqBase<Py::Object> linestyles_obj = args[9]; + Py::SeqBase<Py::Int> antialiaseds = args[10]; // We don't actually care about urls for Agg, so just ignore it. - // Py::SeqBase<Py::Object> urls = args[13]; + // Py::SeqBase<Py::Object> urls = args[11]; PathListGenerator path_generator(paths); try { _draw_path_collection_generic<PathListGenerator, 0, 1> (master_transform, - cliprect, - clippath, - clippath_trans, + gc.cliprect, + gc.clippath, + gc.clippath_trans, path_generator, transforms_obj, offsets_obj, @@ -1390,22 +1380,20 @@ Py::Object RendererAgg::draw_quad_mesh(const Py::Tuple& args) { _VERBOSE("RendererAgg::draw_quad_mesh"); - args.verify_length(12); + args.verify_length(10); //segments, trans, clipbox, colors, linewidths, antialiaseds - agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[0].ptr()); - Py::Object cliprect = args[1]; - Py::Object clippath = args[2]; - agg::trans_affine clippath_trans = py_to_agg_transformation_matrix(args[3].ptr(), false); - size_t mesh_width = Py::Int(args[4]); - size_t mesh_height = Py::Int(args[5]); - PyObject* coordinates = args[6].ptr(); - Py::Object offsets_obj = args[7]; - agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[8].ptr()); - Py::Object facecolors_obj = args[9]; - bool antialiased = (bool)Py::Int(args[10]); - bool showedges = (bool)Py::Int(args[11]); + GCAgg gc(args[0], dpi); + agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[1].ptr()); + size_t mesh_width = Py::Int(args[2]); + size_t mesh_height = Py::Int(args[3]); + PyObject* coordinates = args[4].ptr(); + Py::Object offsets_obj = args[5]; + agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[6].ptr()); + Py::Object facecolors_obj = args[7]; + bool antialiased = (bool)Py::Int(args[8]); + bool showedges = (bool)Py::Int(args[9]); bool free_edgecolors = false; QuadMeshGenerator path_generator(mesh_width, mesh_height, coordinates); @@ -1437,9 +1425,9 @@ try { _draw_path_collection_generic<QuadMeshGenerator, 0, 0> (master_transform, - cliprect, - clippath, - clippath_trans, + gc.cliprect, + gc.clippath, + gc.clippath_trans, path_generator, transforms_obj, offsets_obj, @@ -1467,6 +1455,73 @@ } Py::Object +RendererAgg::draw_gouraud_triangle(const Py::Tuple& args) { + _VERBOSE("RendererAgg::draw_quad_mesh"); + args.verify_length(4); + + typedef agg::rgba8 color_t; + typedef agg::span_gouraud_rgba<color_t> span_gen_t; + typedef agg::span_allocator<color_t> span_alloc_t; + + //segments, trans, clipbox, colors, linewidths, antialiaseds + GCAgg gc(args[0], dpi); + Py::Object points_obj = args[1]; + Py::Object colors_obj = args[2]; + agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[3].ptr()); + + PyArrayObject* points = (PyArrayObject*)PyArray_ContiguousFromAny + (points_obj.ptr(), PyArray_DOUBLE, 2, 2); + if (!points || + PyArray_DIM(points, 0) != 3 || PyArray_DIM(points, 1) != 2) + throw Py::ValueError("points must be a 3x2 numpy array"); + + PyArrayObject* colors = (PyArrayObject*)PyArray_ContiguousFromAny + (colors_obj.ptr(), PyArray_DOUBLE, 2, 2); + if (!colors || + PyArray_DIM(colors, 0) != 3 || PyArray_DIM(colors, 1) != 4) + throw Py::ValueError("colors must be a 3x4 numpy array"); + + try { + double* opoints = (double*)PyArray_DATA(points); + double* c = (double*)PyArray_DATA(colors); + double tpoints[6]; + + for (int i = 0; i < 6; i += 2) { + tpoints[i] = opoints[i]; + tpoints[i+1] = opoints[i+1]; + master_transform.transform(&tpoints[i], &tpoints[i+1]); + } + + span_alloc_t span_alloc; + span_gen_t span_gen; + + span_gen.colors( + agg::rgba(c[0], c[1], c[2], c[3]), + agg::rgba(c[4], c[5], c[6], c[7]), + agg::rgba(c[8], c[9], c[10], c[11])); + span_gen.triangle( + tpoints[0], tpoints[1], + tpoints[2], tpoints[3], + tpoints[4], tpoints[5], + 1.0); + + theRasterizer.add_path(span_gen); + agg::render_scanlines_aa( + theRasterizer, slineP8, rendererBase, span_alloc, span_gen); + } catch (...) { + Py_DECREF(points); + Py_DECREF(colors); + + throw; + } + + Py_DECREF(points); + Py_DECREF(colors); + + return Py::Object(); +} + +Py::Object RendererAgg::write_rgba(const Py::Tuple& args) { _VERBOSE("RendererAgg::write_rgba"); @@ -1802,15 +1857,17 @@ add_varargs_method("draw_path", &RendererAgg::draw_path, "draw_path(gc, path, transform, rgbFace)\n"); add_varargs_method("draw_path_collection", &RendererAgg::draw_path_collection, - "draw_path_collection(master_transform, cliprect, clippath, clippath_trans, paths, transforms, offsets, offsetTrans, facecolors, edgecolors, linewidths, linestyles, antialiaseds)\n"); + "draw_path_collection(gc, master_transform, paths, transforms, offsets, offsetTrans, facecolors, edgecolors, linewidths, linestyles, antialiaseds)\n"); add_varargs_method("draw_quad_mesh", &RendererAgg::draw_quad_mesh, - "draw_quad_mesh(master_transform, cliprect, clippath, clippath_trans, meshWidth, meshHeight, coordinates, offsets, offsetTrans, facecolors, antialiaseds, showedges)\n"); + "draw_quad_mesh(gc, master_transform, meshWidth, meshHeight, coordinates, offsets, offsetTrans, facecolors, antialiaseds, showedges)\n"); + add_varargs_method("draw_gouraud_triangle", &RendererAgg::draw_gouraud_triangle, + "draw_gouraud_triangle(gc, points, colors, master_transform)\n"); add_varargs_method("draw_markers", &RendererAgg::draw_markers, "draw_markers(gc, marker_path, marker_trans, path, rgbFace)\n"); add_varargs_method("draw_text_image", &RendererAgg::draw_text_image, "draw_text_image(font_image, x, y, r, g, b, a)\n"); add_varargs_method("draw_image", &RendererAgg::draw_image, - "draw_image(x, y, im)"); + "draw_image(gc, x, y, im)"); add_varargs_method("write_rgba", &RendererAgg::write_rgba, "write_rgba(fname)"); add_varargs_method("tostring_rgb", &RendererAgg::tostring_rgb, Modified: trunk/matplotlib/src/_backend_agg.h =================================================================== --- trunk/matplotlib/src/_backend_agg.h 2009-08-07 15:40:56 UTC (rev 7416) +++ trunk/matplotlib/src/_backend_agg.h 2009-08-07 17:02:28 UTC (rev 7417) @@ -164,8 +164,8 @@ Py::Object draw_path(const Py::Tuple & args); Py::Object draw_path_collection(const Py::Tuple & args); Py::Object draw_quad_mesh(const Py::Tuple& args); + Py::Object draw_gouraud_triangle(const Py::Tuple& args); - Py::Object write_rgba(const Py::Tuple & args); Py::Object tostring_rgb(const Py::Tuple & args); Py::Object tostring_argb(const Py::Tuple & args); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |