Revision: 7112
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7112&view=rev
Author:   jdh2358
Date:     2009-05-17 15:08:07 +0000 (Sun, 17 May 2009)

Log Message:
-----------
applied Michiel's sf patch 2792742 to speed up Cairo and macosx collections

Modified Paths:
--------------
    trunk/matplotlib/CHANGELOG
    trunk/matplotlib/lib/matplotlib/backend_bases.py
    trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py
    trunk/matplotlib/lib/matplotlib/backends/backend_gtkcairo.py
    trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py
    trunk/matplotlib/lib/matplotlib/lines.py
    trunk/matplotlib/lib/matplotlib/patches.py
    trunk/matplotlib/lib/matplotlib/text.py
    trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py
    trunk/matplotlib/src/_macosx.m

Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG  2009-05-17 14:54:57 UTC (rev 7111)
+++ trunk/matplotlib/CHANGELOG  2009-05-17 15:08:07 UTC (rev 7112)
@@ -1,4 +1,8 @@
+2009-05-19 applied Michiel's sf patch 2792742 to speed up Cairo and
+           macosx collections; speedups can be 20x
+
 ======================================================================
+
 2008-05-17 Release 0.98.5.3 at r7107 from the branch - JDH
 
 2009-05-13 An optional offset and bbox support in restore_bbox.

Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backend_bases.py    2009-05-17 14:54:57 UTC 
(rev 7111)
+++ trunk/matplotlib/lib/matplotlib/backend_bases.py    2009-05-17 15:08:07 UTC 
(rev 7112)
@@ -277,6 +277,7 @@
                 gc.set_url(urls[i % Nurls])
 
             yield xo, yo, path_id, gc, rgbFace
+        gc.restore()
 
     def get_image_magnification(self):
         """
@@ -459,6 +460,13 @@
         self._url = gc._url
         self._snap = gc._snap
 
+    def restore(self):
+        """
+        Restore the graphics context from the stack - needed only
+        for backends that save graphics contexts on a stack
+        """
+        pass
+
     def get_alpha(self):
         """
         Return the alpha value used for blending - not supported on

Modified: trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py   2009-05-17 
14:54:57 UTC (rev 7111)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py   2009-05-17 
15:08:07 UTC (rev 7112)
@@ -91,13 +91,13 @@
         """
         if _debug: print '%s.%s()' % (self.__class__.__name__, _fn_name())
         self.dpi = dpi
+        self.gc = GraphicsContextCairo (renderer=self)
         self.text_ctx = cairo.Context (
            cairo.ImageSurface (cairo.FORMAT_ARGB32,1,1))
         self.mathtext_parser = MathTextParser('Cairo')
 
     def set_ctx_from_surface (self, surface):
-        self.ctx = cairo.Context (surface)
-        self.ctx.save() # restore, save  - when call new_gc()
+        self.gc.ctx = cairo.Context (surface)
 
 
     def set_width_height(self, width, height):
@@ -109,22 +109,6 @@
         # font transform?
 
 
-    def _do_clip(self, ctx, cliprect, clippath):
-        if cliprect is not None:
-            x,y,w,h = cliprect.bounds
-            # pixel-aligned clip-regions are faster
-            x,y,w,h = round(x), round(y), round(w), round(h)
-            ctx.new_path()
-            ctx.rectangle (x, self.height - h - y, w, h)
-            ctx.clip ()
-
-        if clippath is not None:
-            tpath, affine = clippath.get_transformed_path_and_affine()
-            ctx.new_path()
-            affine = affine + Affine2D().scale(1.0, -1.0).translate(0.0, 
self.height)
-            RendererCairo.convert_path(ctx, tpath, affine)
-            ctx.clip()
-
     def _fill_and_stroke (self, ctx, fill_c, alpha):
         if fill_c is not None:
             ctx.save()
@@ -158,8 +142,6 @@
            raise ValueError("The Cairo backend can not draw paths longer than 
18980 points.")
 
         ctx = gc.ctx
-        ctx.save()
-        self._do_clip(ctx, gc._cliprect, gc._clippath)
 
         transform = transform + \
             Affine2D().scale(1.0, -1.0).translate(0, self.height)
@@ -168,7 +150,6 @@
         self.convert_path(ctx, path, transform)
 
         self._fill_and_stroke(ctx, rgbFace, gc.get_alpha())
-        ctx.restore()
 
     def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
         # bbox - not currently used
@@ -180,7 +161,7 @@
         surface = cairo.ImageSurface.create_for_data (
                       buf, cairo.FORMAT_ARGB32, cols, rows, cols*4)
         # function does not pass a 'gc' so use renderer.ctx
-        ctx = self.ctx
+        ctx = self.gc.ctx
         ctx.save()
         if clippath is not None:
             ctx.new_path()
@@ -297,9 +278,8 @@
 
     def new_gc(self):
         if _debug: print '%s.%s()' % (self.__class__.__name__, _fn_name())
-        self.ctx.restore()  # matches save() in set_ctx_from_surface()
-        self.ctx.save()
-        return GraphicsContextCairo (renderer=self)
+        self.gc.ctx.save()
+        return self.gc
 
 
     def points_to_pixels(self, points):
@@ -324,9 +304,12 @@
     def __init__(self, renderer):
         GraphicsContextBase.__init__(self)
         self.renderer = renderer
-        self.ctx = renderer.ctx
 
 
+    def restore(self):
+        self.ctx.restore()
+
+
     def set_alpha(self, alpha):
         self._alpha = alpha
         rgb = self._rgb
@@ -346,10 +329,23 @@
 
 
     def set_clip_rectangle(self, rectangle):
-        self._cliprect = rectangle
+        if not rectangle: return
+        x,y,w,h = rectangle.bounds
+        # pixel-aligned clip-regions are faster
+        x,y,w,h = round(x), round(y), round(w), round(h)
+        ctx = self.ctx
+        ctx.new_path()
+        ctx.rectangle (x, self.renderer.height - h - y, w, h)
+        ctx.clip ()
 
     def set_clip_path(self, path):
-        self._clippath = path
+        if not path: return
+        tpath, affine = path.get_transformed_path_and_affine()
+        ctx = self.ctx
+        ctx.new_path()
+        affine = affine + Affine2D().scale(1.0, -1.0).translate(0.0, 
self.renderer.height)
+        RendererCairo.convert_path(ctx, tpath, affine)
+        ctx.clip()
 
     def set_dashes(self, offset, dashes):
         self._dashes = offset, dashes
@@ -468,7 +464,7 @@
         renderer = RendererCairo (self.figure.dpi)
         renderer.set_width_height (width_in_points, height_in_points)
         renderer.set_ctx_from_surface (surface)
-        ctx = renderer.ctx
+        ctx = renderer.gc.ctx
 
         if orientation == 'landscape':
             ctx.rotate (npy.pi/2)

Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gtkcairo.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_gtkcairo.py        
2009-05-17 14:54:57 UTC (rev 7111)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_gtkcairo.py        
2009-05-17 15:08:07 UTC (rev 7112)
@@ -31,12 +31,10 @@
 class RendererGTKCairo (backend_cairo.RendererCairo):
     if gtk.pygtk_version >= (2,7,0):
         def set_pixmap (self, pixmap):
-            self.ctx = pixmap.cairo_create()
-            self.ctx.save()  # restore, save  - when call new_gc()
+            self.gc.ctx = pixmap.cairo_create()
     else:
         def set_pixmap (self, pixmap):
-            self.ctx = cairo.gtk.gdk_cairo_create (pixmap)
-            self.ctx.save()  # restore, save  - when call new_gc()
+            self.gc.ctx = cairo.gtk.gdk_cairo_create (pixmap)
 
 
 class FigureCanvasGTKCairo(backend_cairo.FigureCanvasCairo, FigureCanvasGTK):

Modified: trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py  2009-05-17 
14:54:57 UTC (rev 7111)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py  2009-05-17 
15:08:07 UTC (rev 7112)
@@ -51,19 +51,11 @@
     def draw_path(self, gc, path, transform, rgbFace=None):
         if rgbFace is not None:
             rgbFace = tuple(rgbFace)
-        if gc!=self.gc:
-            n = self.gc.level() - gc.level()
-            for i in range(n): self.gc.restore()
-            self.gc = gc
         gc.draw_path(path, transform, rgbFace)
 
     def draw_markers(self, gc, marker_path, marker_trans, path, trans, 
rgbFace=None):
         if rgbFace is not None:
             rgbFace = tuple(rgbFace)
-        if gc!=self.gc:
-            n = self.gc.level() - gc.level()
-            for i in range(n): self.gc.restore()
-            self.gc = gc
         gc.draw_markers(marker_path, marker_trans, path, trans, rgbFace)
 
     def draw_path_collection(self, *args):
@@ -76,7 +68,7 @@
         gc.draw_quad_mesh(*args)
 
     def new_gc(self):
-        self.gc.reset()
+        self.gc.save()
         self.gc.set_hatch(None)
         return self.gc
 
@@ -87,10 +79,6 @@
         im.flipud_out()
     
     def draw_tex(self, gc, x, y, s, prop, angle):
-        if gc!=self.gc:
-            n = self.gc.level() - gc.level()
-            for i in range(n): self.gc.restore()
-            self.gc = gc
         # todo, handle props, angle, origins
         size = prop.get_size_in_points()
         texmanager = self.get_texmanager()
@@ -103,19 +91,11 @@
         gc.draw_mathtext(x, y, angle, Z)
 
     def _draw_mathtext(self, gc, x, y, s, prop, angle):
-        if gc!=self.gc:
-            n = self.gc.level() - gc.level()
-            for i in range(n): self.gc.restore()
-            self.gc = gc
         ox, oy, width, height, descent, image, used_characters = \
             self.mathtext_parser.parse(s, self.dpi, prop)
         gc.draw_mathtext(x, y, angle, 255 - image.as_array())
 
     def draw_text(self, gc, x, y, s, prop, angle, ismath=False):
-        if gc!=self.gc:
-            n = self.gc.level() - gc.level()
-            for i in range(n): self.gc.restore()
-            self.gc = gc
         if ismath:
            self._draw_mathtext(gc, x, y, s, prop, angle)
         else:

Modified: trunk/matplotlib/lib/matplotlib/lines.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/lines.py    2009-05-17 14:54:57 UTC (rev 
7111)
+++ trunk/matplotlib/lib/matplotlib/lines.py    2009-05-17 15:08:07 UTC (rev 
7112)
@@ -540,7 +540,9 @@
 
                     markerFunc = getattr(self, funcname)
                     markerFunc(renderer, gc, subsampled, affine.frozen())
+            gc.restore()
 
+        gc.restore()
         renderer.close_group('line2d')
 
     def get_antialiased(self): return self._antialiased

Modified: trunk/matplotlib/lib/matplotlib/patches.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/patches.py  2009-05-17 14:54:57 UTC (rev 
7111)
+++ trunk/matplotlib/lib/matplotlib/patches.py  2009-05-17 15:08:07 UTC (rev 
7112)
@@ -302,6 +302,7 @@
 
         renderer.draw_path(gc, tpath, affine, rgbFace)
 
+        gc.restore()
         renderer.close_group('patch')
 
     def get_path(self):
@@ -3705,4 +3706,5 @@
                 renderer.draw_path(gc, p, affine, None)
 
 
+        gc.restore()
         renderer.close_group('patch')

Modified: trunk/matplotlib/lib/matplotlib/text.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/text.py     2009-05-17 14:54:57 UTC (rev 
7111)
+++ trunk/matplotlib/lib/matplotlib/text.py     2009-05-17 15:08:07 UTC (rev 
7112)
@@ -507,6 +507,7 @@
                                self._fontproperties, angle,
                                ismath=ismath)
 
+        gc.restore()
         renderer.close_group('text')
 
     def get_color(self):

Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py
===================================================================
--- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py    2009-05-17 
14:54:57 UTC (rev 7111)
+++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py    2009-05-17 
15:08:07 UTC (rev 7112)
@@ -65,6 +65,7 @@
             lineFunc = getattr(self, funcname)
             lineFunc(renderer, gc, tpath, affine.frozen())
 
+        gc.restore()
         renderer.close_group('line2d')
 
 
@@ -548,6 +549,7 @@
             renderer.draw_markers(gc, self._tickvert_path, marker_transform,
                                   Path(locs), path_trans.get_affine())
 
+        gc.restore()
 
 
 

Modified: trunk/matplotlib/src/_macosx.m
===================================================================
--- trunk/matplotlib/src/_macosx.m      2009-05-17 14:54:57 UTC (rev 7111)
+++ trunk/matplotlib/src/_macosx.m      2009-05-17 15:08:07 UTC (rev 7112)
@@ -374,6 +374,7 @@
     PyObject_HEAD
     CGContextRef cr;
     NSSize size;
+    int level;
 } GraphicsContext;
 
 static CGMutablePathRef _create_path(void* iterator)
@@ -437,6 +438,7 @@
     GraphicsContext* self = (GraphicsContext*)type->tp_alloc(type, 0);
     if (!self) return NULL;
     self->cr = NULL;
+    self->level = 0;
 
     if (ngc==0)
     {
@@ -467,7 +469,7 @@
 }
 
 static PyObject*
-GraphicsContext_reset (GraphicsContext* self)
+GraphicsContext_save (GraphicsContext* self)
 {
     CGContextRef cr = self->cr;
     if (!cr)
@@ -475,9 +477,29 @@
         PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
         return NULL;
     }
+    CGContextSaveGState(cr);
+    self->level++;
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
+static PyObject*
+GraphicsContext_restore (GraphicsContext* self)
+{
+    CGContextRef cr = self->cr;
+    if (!cr)
+    {
+        PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
+        return NULL;
+    }
+    if (self->level==0)
+    {
+        PyErr_SetString(PyExc_RuntimeError,
+            "Attempting to execute CGContextRestoreGState on an empty stack");
+        return NULL;
+    }
     CGContextRestoreGState(cr);
-    CGContextSaveGState(cr);
+    self->level--;
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1543,11 +1565,15 @@
             const double b = *(double*)PyArray_GETPTR2(facecolors, fi, 2);
             const double a = *(double*)PyArray_GETPTR2(facecolors, fi, 3);
             CGContextSetRGBFillColor(cr, r, g, b, a);
-            CGContextDrawPath(cr, kCGPathFillStroke);
+            if (Nedgecolors > 0) CGContextDrawPath(cr, kCGPathFillStroke);
+            else CGContextFillPath(cr);
         }
         else if (Nfacecolors==1)
-            CGContextDrawPath(cr, kCGPathFillStroke);
-        else
+        {
+            if (Nedgecolors > 0) CGContextDrawPath(cr, kCGPathFillStroke);
+            else CGContextFillPath(cr);
+        }
+        else /* We checked Nedgecolors != 0 above */
             CGContextStrokePath(cr);
         CGContextRestoreGState(cr);
     }
@@ -2480,11 +2506,16 @@
 
 
 static PyMethodDef GraphicsContext_methods[] = {
-    {"reset",
-     (PyCFunction)GraphicsContext_reset,
+    {"save",
+     (PyCFunction)GraphicsContext_save,
      METH_NOARGS,
-     "Resets the current graphics context by restoring it from the stack and 
copying it back onto the stack."
+     "Saves the current graphics context onto the stack."
     },
+    {"restore",
+     (PyCFunction)GraphicsContext_restore,
+     METH_NOARGS,
+     "Restores the current graphics context from the stack."
+    },
     {"get_text_width_height_descent",
      (PyCFunction)GraphicsContext_get_text_width_height_descent,
      METH_VARARGS,
@@ -4293,17 +4324,14 @@
 
     CGContextRef cr = (CGContextRef) [[NSGraphicsContext currentContext] 
graphicsPort];
     gc->cr = cr;
+    gc->level = 0;
 
-    CGContextSaveGState(cr);
-    CGContextSetTextMatrix(cr, CGAffineTransformIdentity);
-
     result = PyObject_CallMethod(figure, "draw", "O", renderer);
     if(result)
         Py_DECREF(result);
     else
         PyErr_Print();
 
-    CGContextRestoreGState(cr);
     gc->cr = nil;
 
     if (!NSIsEmptyRect(rubberband)) NSFrameRect(rubberband);


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables 
unlimited royalty-free distribution of the report engine 
for externally facing server and web deployment. 
http://p.sf.net/sfu/businessobjects
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to