From: <jd...@us...> - 2009-05-17 15:08:13
|
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. |