Revision: 3865 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3865&view=rev Author: mdboom Date: 2007-09-20 06:57:59 -0700 (Thu, 20 Sep 2007)
Log Message: ----------- Go all out with iterator (rather than copy) approach, as it is much faster. Modified Paths: -------------- branches/transforms/lib/matplotlib/backend_bases.py branches/transforms/lib/matplotlib/backends/backend_agg.py branches/transforms/lib/matplotlib/transforms.py branches/transforms/src/_backend_agg.cpp branches/transforms/src/_backend_agg.h Modified: branches/transforms/lib/matplotlib/backend_bases.py =================================================================== --- branches/transforms/lib/matplotlib/backend_bases.py 2007-09-20 13:57:32 UTC (rev 3864) +++ branches/transforms/lib/matplotlib/backend_bases.py 2007-09-20 13:57:59 UTC (rev 3865) @@ -17,11 +17,6 @@ class RendererBase: """An abstract base class to handle drawing/rendering operations """ - # This will cache paths across rendering instances - # Each subclass of RenderBase should define this a weak-keyed - # dictionary to hold native paths - # _native_paths = weakref.WeakKeyDictionary() - def __init__(self): self._texmanager = None @@ -37,43 +32,16 @@ """ pass - def _get_cached_native_path(self, path): - native_path = self._native_paths.get(path) - if native_path is None: - print "CACHE MISS", path - native_path = self.convert_to_native_path(path) - self._native_paths[path] = native_path - return native_path - def draw_path(self, gc, path, transform, rgbFace=None): """ Handles the caching of the native path associated with the given path and calls the underlying backend's _draw_path to actually do the drawing. """ - native_path = self._get_cached_native_path(path) - self._draw_native_path(gc, native_path, transform, rgbFace) + # MGDTODO: Update docstring + raise NotImplementedError - def _draw_native_path(self, gc, native_path, transform, rgbFace): - """ - Draw the native path object with the given GraphicsContext and - transform. The transform passed in will always be affine. - """ - raise NotImplementedError - - def convert_to_native_path(self, path): - """ - Backends will normally will override this, but if they don't need any - special optimizations, they can just have the generic path data - passed to them in draw_path. - """ - return path - def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None): - native_marker_path = self._get_cached_native_path(marker_path) - self._draw_native_markers(gc, native_marker_path, marker_trans, path, trans, rgbFace) - - def _draw_native_markers(self, gc, native_marker_path, marker_trans, path, trans, rgbFace=None): """ This method is currently underscore hidden because the draw_markers method is being used as a sentinel for newstyle @@ -94,7 +62,11 @@ vec6 = transform.as_vec6_val() ...backend dependent affine... """ + # MGDTODO: Update docstring raise NotImplementedError + + def _draw_native_markers(self, gc, native_marker_path, marker_trans, path, trans, rgbFace=None): + raise NotImplementedError def get_image_magnification(self): """ Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py =================================================================== --- branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-09-20 13:57:32 UTC (rev 3864) +++ branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-09-20 13:57:59 UTC (rev 3865) @@ -117,8 +117,8 @@ debug=False) if __debug__: verbose.report('RendererAgg.__init__ _RendererAgg done', 'debug-annoying') - - self.convert_to_native_path = self._renderer.convert_to_native_path + self.draw_path = self._renderer.draw_path + self.draw_markers = self._renderer.draw_markers self.draw_image = self._renderer.draw_image self.copy_from_bbox = self._renderer.copy_from_bbox self.restore_region = self._renderer.restore_region @@ -129,16 +129,6 @@ if __debug__: verbose.report('RendererAgg.__init__ done', 'debug-annoying') - def _draw_native_path(self, gc, path, transform, rgbFace): - return self._renderer.draw_path(gc, path, transform.get_matrix(), rgbFace) - - def _draw_native_markers(self, gc, native_marker_path, marker_trans, path, trans, rgbFace=None): - return self._renderer.draw_markers( - gc, - native_marker_path, marker_trans.get_matrix(), - path.vertices, path.codes, trans.get_matrix(), - rgbFace) - def draw_mathtext(self, gc, x, y, s, prop, angle): """ Draw the math text using matplotlib.mathtext Modified: branches/transforms/lib/matplotlib/transforms.py =================================================================== --- branches/transforms/lib/matplotlib/transforms.py 2007-09-20 13:57:32 UTC (rev 3864) +++ branches/transforms/lib/matplotlib/transforms.py 2007-09-20 13:57:59 UTC (rev 3865) @@ -365,7 +365,7 @@ Transform.__init__(self) self._inverted = None - def __array__(self): + def __array__(self, *args, **kwargs): return self.get_matrix() def _do_invalidation(self): Modified: branches/transforms/src/_backend_agg.cpp =================================================================== --- branches/transforms/src/_backend_agg.cpp 2007-09-20 13:57:32 UTC (rev 3864) +++ branches/transforms/src/_backend_agg.cpp 2007-09-20 13:57:59 UTC (rev 3865) @@ -48,59 +48,42 @@ agg::trans_affine py_to_agg_transformation_matrix(const Py::Object& obj) { PyArrayObject* matrix = NULL; - double a = 1.0, b = 0.0, c = 0.0, d = 1.0, e = 0.0, f = 0.0; - try { - matrix = (PyArrayObject*) PyArray_ContiguousFromObject(obj.ptr(), PyArray_DOUBLE, 2, 2); - if (!matrix || matrix->nd != 2 || matrix->dimensions[0] != 3 || matrix->dimensions[1] != 3) { - throw Py::ValueError("Invalid affine transformation matrix."); + matrix = (PyArrayObject*) PyArray_FromObject(obj.ptr(), PyArray_DOUBLE, 2, 2); + if (!matrix) { + throw Py::Exception(); } - - size_t stride0 = matrix->strides[0]; - size_t stride1 = matrix->strides[1]; - char* row0 = matrix->data; - char* row1 = row0 + stride0; - - a = *(double*)(row0); - row0 += stride1; - c = *(double*)(row0); - row0 += stride1; - e = *(double*)(row0); - - b = *(double*)(row1); - row1 += stride1; - d = *(double*)(row1); - row1 += stride1; - f = *(double*)(row1); + if (matrix->nd == 2 || matrix->dimensions[0] == 3 || matrix->dimensions[1] == 3) { + size_t stride0 = matrix->strides[0]; + size_t stride1 = matrix->strides[1]; + char* row0 = matrix->data; + char* row1 = row0 + stride0; + + double a = *(double*)(row0); + row0 += stride1; + double c = *(double*)(row0); + row0 += stride1; + double e = *(double*)(row0); + + double b = *(double*)(row1); + row1 += stride1; + double d = *(double*)(row1); + row1 += stride1; + double f = *(double*)(row1); + + Py_XDECREF(matrix); + + return agg::trans_affine(a, b, c, d, e, f); + } } catch (...) { - Py_XDECREF(matrix); + } Py_XDECREF(matrix); - - return agg::trans_affine(a, b, c, d, e, f); + throw Py::TypeError("Invalid affine transformation matrix"); } -/** Helper function to get the next vertex in a Numpy array of vertices. - * Will generally be used through the GET_NEXT_VERTEX macro. - */ -inline void get_next_vertex(const char* & vertex_i, const char* vertex_end, - double& x, double& y, - size_t next_vertex_stride, - size_t next_axis_stride, - const char* & code_i, size_t code_stride) { - if (vertex_i + next_axis_stride >= vertex_end) - throw Py::ValueError("Error parsing path. Read past end of vertices"); - x = *(double*)vertex_i; - y = *(double*)(vertex_i + next_axis_stride); - vertex_i += next_vertex_stride; - code_i += code_stride; -} - -#define GET_NEXT_VERTEX(x, y) get_next_vertex(vertex_i, vertex_end, x, y, next_vertex_stride, next_axis_stride, code_i, code_stride) - Py::Object BufferRegion::to_string(const Py::Tuple &args) { - // owned=true to prevent memory leak return Py::String(PyString_FromStringAndSize((const char*)aggbuf.data,aggbuf.height*aggbuf.stride), true); } @@ -145,7 +128,6 @@ double* pv = (double*)(vertices->data + (idx * vertices->strides[0])); *x = *pv++; *y = *pv; - // MGDTODO: Range check return code_map[(unsigned int)*(codes->data + (idx * codes->strides[0]))]; } @@ -170,9 +152,43 @@ agg::path_cmd_curve4, agg::path_cmd_end_poly | agg::path_flags_close}; +template<class VertexSource> class conv_quantize +{ +public: + conv_quantize(VertexSource& source, bool quantize) : + m_source(&source), m_quantize(quantize) {} + + void set_source(VertexSource& source) { m_source = &source; } + + void rewind(unsigned path_id) + { + m_source->rewind(path_id); + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd = m_source->vertex(x, y); + if(m_quantize && agg::is_vertex(cmd)) + { + *x = (int)(*x); + *y = (int)(*y); + } + return cmd; + } + + void activate(bool quantize) { + m_quantize = quantize; + } + +private: + VertexSource* m_source; + bool m_quantize; +}; + + GCAgg::GCAgg(const Py::Object &gc, double dpi, bool snapto) : dpi(dpi), snapto(snapto), isaa(true), linewidth(1.0), alpha(1.0), - cliprect(NULL), clippath(NULL), + cliprect(NULL), Ndash(0), dashOffset(0.0), dasha(NULL) { _VERBOSE("GCAgg::GCAgg"); @@ -316,15 +332,7 @@ _VERBOSE("GCAgg::_set_clip_path"); - Py_XINCREF(clippath); - clippath = NULL; - - Py::Object o = gc.getAttr("_clippath"); - if (o.ptr()==Py_None) { - return; - } - - clippath = new PathAgg(o); + clippath = gc.getAttr("_clippath"); } @@ -337,8 +345,7 @@ height(height), dpi(dpi), NUMBYTES(width*height*4), - debug(debug), - lastclippath(NULL) + debug(debug) { _VERBOSE("RendererAgg::RendererAgg"); unsigned stride(width*4); @@ -599,7 +606,7 @@ Py::Object RendererAgg::draw_markers(const Py::Tuple& args) { - typedef agg::conv_transform<agg::path_storage> transformed_path_t; + typedef agg::conv_transform<PathIterator> transformed_path_t; typedef agg::conv_curve<transformed_path_t> curve_t; typedef agg::conv_stroke<curve_t> stroke_t; typedef agg::conv_dash<curve_t> dash_t; @@ -607,27 +614,29 @@ theRasterizer->reset_clipping(); - args.verify_length(7); + args.verify_length(5, 6); GCAgg gc = GCAgg(args[0], dpi); Py::Object marker_path_obj = args[1]; - if (!PathAgg::check(marker_path_obj)) - throw Py::TypeError("Native path object is not of correct type"); - PathAgg* marker_path = static_cast<PathAgg*>(marker_path_obj.ptr()); agg::trans_affine marker_trans = py_to_agg_transformation_matrix(args[2]); - Py::Object vertices_obj = args[3]; - Py::Object codes_obj = args[4]; - agg::trans_affine trans = py_to_agg_transformation_matrix(args[5]); - facepair_t face = _get_rgba_face(args[6], gc.alpha); + Py::Object path_obj = args[3]; + agg::trans_affine trans = py_to_agg_transformation_matrix(args[4]); + Py::Object face_obj; + if (args.size() == 6) + face_obj = args[5]; + facepair_t face = _get_rgba_face(face_obj, gc.alpha); // Deal with the difference in y-axis direction marker_trans *= agg::trans_affine_scaling(1.0, -1.0); trans *= agg::trans_affine_scaling(1.0, -1.0); trans *= agg::trans_affine_translation(0.0, (double)height); - marker_path->rewind(0); - transformed_path_t marker_path_transformed(*marker_path, marker_trans); + PathIterator marker_path(marker_path_obj); + transformed_path_t marker_path_transformed(marker_path, marker_trans); curve_t marker_path_curve(marker_path_transformed); + + PathIterator path(path_obj); + transformed_path_t path_transformed(path, trans); //maxim's suggestions for cached scanlines agg::scanline_storage_aa8 scanlines; @@ -635,19 +644,8 @@ agg::int8u* fillCache = NULL; agg::int8u* strokeCache = NULL; - PyArrayObject* vertices = NULL; - PyArrayObject* codes = NULL; try { - vertices = (PyArrayObject*)PyArray_ContiguousFromObject - (vertices_obj.ptr(), PyArray_DOUBLE, 2, 2); - if (!vertices || vertices->nd != 2 || vertices->dimensions[1] != 2) - throw Py::ValueError("Invalid vertices array."); - codes = (PyArrayObject*)PyArray_ContiguousFromObject - (codes_obj.ptr(), PyArray_UINT8, 1, 1); - if (!codes) - throw Py::ValueError("Invalid codes array."); - unsigned fillSize = 0; if (face.first) { theRasterizer->add_path(marker_path_curve); @@ -681,53 +679,29 @@ rendererBase->clip_box(l, height-(b+h),l+w, height-b); } - size_t next_vertex_stride = vertices->strides[0]; - size_t next_axis_stride = vertices->strides[1]; - size_t code_stride = codes->strides[0]; - - const char* vertex_i = vertices->data; - const char* code_i = codes->data; - const char* vertex_end = vertex_i + (vertices->dimensions[0] * vertices->strides[0]); - - size_t N = codes->dimensions[0]; double x, y; agg::serialized_scanlines_adaptor_aa8 sa; agg::serialized_scanlines_adaptor_aa8::embedded_scanline sl; - for (size_t i=0; i < N; i++) { - size_t num_vertices = NUM_VERTICES[(int)(*code_i)]; - if (num_vertices) { - for (size_t j=0; j<num_vertices; ++j) - GET_NEXT_VERTEX(x, y); - if (*code_i == STOP || *code_i == CLOSEPOLY) - continue; - - trans.transform(&x, &y); - - if (face.first) { - //render the fill - sa.init(fillCache, fillSize, x, y); - rendererAA->color(face.second); - agg::render_scanlines(sa, sl, *rendererAA); - } - - //render the stroke - sa.init(strokeCache, strokeSize, x, y); - rendererAA->color(gc.color); + while (path_transformed.vertex(&x, &y) != agg::path_cmd_stop) { + if (face.first) { + //render the fill + sa.init(fillCache, fillSize, x, y); + rendererAA->color(face.second); agg::render_scanlines(sa, sl, *rendererAA); } - code_i += code_stride; + + //render the stroke + sa.init(strokeCache, strokeSize, x, y); + rendererAA->color(gc.color); + agg::render_scanlines(sa, sl, *rendererAA); } } catch(...) { - Py_XDECREF(vertices); - Py_XDECREF(codes); delete[] fillCache; delete[] strokeCache; } - Py_XDECREF(vertices); - Py_XDECREF(codes); delete [] fillCache; delete [] strokeCache; @@ -888,98 +862,12 @@ } -Py::Object -RendererAgg::convert_to_native_path(const Py::Tuple& args) { - _VERBOSE("RendererAgg::draw_image"); - args.verify_length(1); - - Py::Object path = args[0]; - return Py::asObject(new PathAgg(path)); -} - - -PathAgg::PathAgg(const Py::Object& path_obj) : curvy(false) { - Py::Object vertices_obj = path_obj.getAttr("vertices"); - Py::Object codes_obj = path_obj.getAttr("codes"); - - PyArrayObject* vertices = NULL; - PyArrayObject* codes = NULL; - - try { - vertices = (PyArrayObject*)PyArray_ContiguousFromObject - (vertices_obj.ptr(), PyArray_DOUBLE, 2, 2); - if (!vertices || vertices->nd != 2 || vertices->dimensions[1] != 2) - throw Py::ValueError("Invalid vertices array."); - codes = (PyArrayObject*)PyArray_ContiguousFromObject - (codes_obj.ptr(), PyArray_UINT8, 1, 1); - if (!codes) - throw Py::ValueError("Invalid codes array."); - - size_t next_vertex_stride = vertices->strides[0]; - size_t next_axis_stride = vertices->strides[1]; - size_t code_stride = codes->strides[0]; - - const char* vertex_i = vertices->data; - const char* code_i = codes->data; - const char* vertex_end = vertex_i + (vertices->dimensions[0] * vertices->strides[0]); - - size_t N = codes->dimensions[0]; - double x0, y0, x1, y1, x2, y2; - - for (size_t i = 0; i < N; ++i) { - switch (*(unsigned char*)(code_i)) { - case STOP: - GET_NEXT_VERTEX(x0, y0); - _VERBOSE("STOP"); - // MGDTODO: If this isn't the end, we should raise an error - break; - case MOVETO: - GET_NEXT_VERTEX(x0, y0); - move_to(x0, y0); - _VERBOSE("MOVETO"); - break; - case LINETO: - GET_NEXT_VERTEX(x0, y0); - line_to(x0, y0); - _VERBOSE("LINETO"); - break; - case CURVE3: - GET_NEXT_VERTEX(x0, y0); - GET_NEXT_VERTEX(x1, y1); - curve3(x0, y0, x1, y1); - curvy = true; - _VERBOSE("CURVE3"); - break; - case CURVE4: - GET_NEXT_VERTEX(x0, y0); - GET_NEXT_VERTEX(x1, y1); - GET_NEXT_VERTEX(x2, y2); - curve4(x0, y0, x1, y1, x2, y2); - curvy = true; - _VERBOSE("CURVE4"); - break; - case CLOSEPOLY: - close_polygon(); - GET_NEXT_VERTEX(x0, y0); - _VERBOSE("CLOSEPOLY"); - break; - } - } - } catch(...) { - Py_XDECREF(vertices); - Py_XDECREF(codes); - throw; - } - - Py_XDECREF(vertices); - Py_XDECREF(codes); -} - Py::Object RendererAgg::draw_path(const Py::Tuple& args) { typedef agg::conv_transform<PathIterator> transformed_path_t; - typedef agg::conv_curve<transformed_path_t> curve_t; + typedef conv_quantize<transformed_path_t> quantize_t; + typedef agg::conv_curve<quantize_t> curve_t; typedef agg::conv_stroke<curve_t> stroke_t; typedef agg::conv_dash<curve_t> dash_t; typedef agg::conv_stroke<dash_t> stroke_dash_t; @@ -991,61 +879,59 @@ theRasterizer->reset_clipping(); _VERBOSE("RendererAgg::draw_path"); - args.verify_length(4); + args.verify_length(3, 4); - GCAgg gc = GCAgg(args[0], dpi); + Py::Object gc_obj = args[0]; Py::Object path_obj = args[1]; -// if (!PathAgg::check(path_obj)) -// throw Py::TypeError("Native path object is not of correct type"); - // PathAgg* path = static_cast<PathAgg*>(path_obj.ptr()); PathIterator path(path_obj); agg::trans_affine trans = py_to_agg_transformation_matrix(args[2]); - facepair_t face = _get_rgba_face(args[3], gc.alpha); trans *= agg::trans_affine_scaling(1.0, -1.0); trans *= agg::trans_affine_translation(0.0, (double)height); - transformed_path_t* tpath = NULL; - agg::path_storage new_path; + bool snap = false; + if (path.total_vertices() == 2) { + double x0, y0, x1, y1; + path.vertex(0, &x0, &y0); + trans.transform(&x0, &y0); + path.vertex(1, &x1, &y1); + trans.transform(&x1, &y1); + snap = ((int)x0 == (int)x1) || ((int)y0 == (int)y1); + } - bool has_clippath = (gc.clippath != NULL); + GCAgg gc = GCAgg(gc_obj, dpi, snap); + Py::Object face_obj; + if (args.size() == 4) + face_obj = args[3]; + facepair_t face = _get_rgba_face(face_obj, gc.alpha); - if (has_clippath && (gc.clippath != lastclippath || trans != lastclippath_transform)) { -// rendererBaseAlphaMask->clear(agg::gray8(0, 0)); -// gc.clippath->rewind(0); -// transformed_path_t transformed_clippath(*(gc.clippath), trans); -// theRasterizer->add_path(transformed_clippath); -// rendererAlphaMask->color(agg::gray8(255, 255)); -// agg::render_scanlines(*theRasterizer, *scanlineAlphaMask, *rendererAlphaMask); -// lastclippath = gc.clippath; -// lastclippath_transform = trans; + bool has_clippath = (gc.clippath.ptr() != Py_None); + + if (has_clippath && + (gc.clippath.ptr() != lastclippath.ptr() || trans != lastclippath_transform)) { + PathIterator clippath(gc.clippath); + rendererBaseAlphaMask->clear(agg::gray8(0, 0)); + transformed_path_t transformed_clippath(clippath, trans); + agg::conv_curve<transformed_path_t> curved_clippath(transformed_clippath); + theRasterizer->add_path(curved_clippath); + rendererAlphaMask->color(agg::gray8(255, 255)); + agg::render_scanlines(*theRasterizer, *scanlineAlphaMask, *rendererAlphaMask); + lastclippath = gc.clippath; + lastclippath_transform = trans; } try { // If this is a straight horizontal or vertical line, quantize to nearest // pixels -// if (path.total_vertices() == 2) { -// double x0, y0, x1, y1; -// path.vertex(0, &x0, &y0); -// trans.transform(&x0, &y0); -// path.vertex(1, &x1, &y1); -// trans.transform(&x1, &y1); -// if (((int)x0 == (int)x1) || ((int)y0 == (int)y1)) { -// new_path.move_to((int)x0 + 0.5, (int)y0 + 0.5); -// new_path.line_to((int)x1 + 0.5, (int)y1 + 0.5); -// tpath = new transformed_path_t(new_path, agg::trans_affine()); -// } -// } - if (!tpath) { - tpath = new transformed_path_t(path, trans); - } + transformed_path_t tpath(path, trans); + quantize_t quantized(tpath, snap); // Benchmarking shows that there is no noticable slowdown to always // treating paths as having curved segments. Doing so greatly // simplifies the code - curve_t curve(*tpath); + curve_t curve(quantized); set_clipbox_rasterizer(gc.cliprect); @@ -1106,12 +992,11 @@ } } } catch (...) { - delete tpath; + // MGDTODO: We don't have anything on the heap, so this catch + // clause isn't really necessary, but we might again soon... throw; } - delete tpath; - return Py::Object(); } @@ -1446,11 +1331,9 @@ behaviors().doc("The agg backend extension module"); add_varargs_method("draw_path", &RendererAgg::draw_path, - "draw_path(gc, rgbFace, native_path, transform)\n"); - add_varargs_method("convert_to_native_path", &RendererAgg::convert_to_native_path, - "convert_to_native_path(vertices, codes)\n"); + "draw_path(gc, path, transform, rgbFace)\n"); add_varargs_method("draw_markers", &RendererAgg::draw_markers, - "draw_markers(gc, marker_path, marker_trans, vertices, codes, rgbFace)\n"); + "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, @@ -1476,12 +1359,6 @@ "restore_region(region)"); } -void PathAgg::init_type() -{ - behaviors().name("PathAgg"); - behaviors().doc("A native Agg path object"); -} - extern "C" DL_EXPORT(void) init_backend_agg(void) Modified: branches/transforms/src/_backend_agg.h =================================================================== --- branches/transforms/src/_backend_agg.h 2007-09-20 13:57:32 UTC (rev 3864) +++ branches/transforms/src/_backend_agg.h 2007-09-20 13:57:59 UTC (rev 3865) @@ -105,20 +105,6 @@ }; }; -// A completely opaque data type used only to pass native path -// data to/from Python. Python can't do anything with the data -// other than create and then use it. -class PathAgg : - public agg::path_storage, - public Py::PythonExtension<PathAgg> { -public: - static void init_type(void); - - PathAgg(const Py::Object& path_obj); - - bool curvy; -}; - class GCAgg { public: GCAgg(const Py::Object& gc, double dpi, bool snapto=false); @@ -126,7 +112,6 @@ ~GCAgg() { delete [] dasha; delete [] cliprect; - Py_XINCREF(clippath); } double dpi; @@ -142,7 +127,7 @@ agg::rgba color; double *cliprect; - PathAgg *clippath; + Py::Object clippath; //dashes size_t Ndash; double dashOffset; @@ -183,7 +168,6 @@ Py::Object draw_text_image(const Py::Tuple & args); Py::Object draw_image(const Py::Tuple & args); Py::Object draw_path(const Py::Tuple & args); - Py::Object convert_to_native_path(const Py::Tuple & args); Py::Object write_rgba(const Py::Tuple & args); Py::Object write_png(const Py::Tuple & args); @@ -240,7 +224,7 @@ void set_clipbox_rasterizer( double *cliprect); private: - PathAgg *lastclippath; + Py::Object lastclippath; agg::trans_affine lastclippath_transform; }; @@ -253,7 +237,6 @@ : Py::ExtensionModule<_backend_agg_module>( "_backend_agg" ) { RendererAgg::init_type(); - PathAgg::init_type(); add_keyword_method("RendererAgg", &_backend_agg_module::new_renderer, "RendererAgg(width, height, dpi)"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ Matplotlib-checkins mailing list Matplotlib-checkins@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins