Revision: 3860 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3860&view=rev Author: mdboom Date: 2007-09-19 12:48:17 -0700 (Wed, 19 Sep 2007)
Log Message: ----------- Use iterator rather than caching approach for paths Modified Paths: -------------- branches/transforms/lib/matplotlib/backends/backend_agg.py branches/transforms/src/_backend_agg.cpp branches/transforms/src/_backend_agg.h Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py =================================================================== --- branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-09-19 19:46:34 UTC (rev 3859) +++ branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-09-19 19:48:17 UTC (rev 3860) @@ -112,8 +112,7 @@ self.dpi = dpi self.width = width self.height = height - if __debug__: verbose.report('RendererAgg.__init__ width=%s, \ - height=%s'%(width, height), 'debug-annoying') + if __debug__: verbose.report('RendererAgg.__init__ width=%s, height=%s'%(width, height), 'debug-annoying') self._renderer = _RendererAgg(int(width), int(height), dpi, debug=False) if __debug__: verbose.report('RendererAgg.__init__ _RendererAgg done', Modified: branches/transforms/src/_backend_agg.cpp =================================================================== --- branches/transforms/src/_backend_agg.cpp 2007-09-19 19:46:34 UTC (rev 3859) +++ branches/transforms/src/_backend_agg.cpp 2007-09-19 19:48:17 UTC (rev 3860) @@ -87,15 +87,17 @@ 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) { + 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) +#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) { @@ -103,7 +105,71 @@ return Py::String(PyString_FromStringAndSize((const char*)aggbuf.data,aggbuf.height*aggbuf.stride), true); } +class PathIterator { + PyArrayObject* vertices; + PyArrayObject* codes; + size_t m_iterator; + size_t m_total_vertices; +public: + PathIterator(const Py::Object& path_obj) : + vertices(NULL), codes(NULL), m_iterator(0) { + Py::Object vertices_obj = path_obj.getAttr("vertices"); + Py::Object codes_obj = path_obj.getAttr("codes"); + + 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."); + + if (codes->dimensions[0] != vertices->dimensions[0]) + throw Py::ValueError("Vertices and codes array are not the same length."); + + m_total_vertices = codes->dimensions[0]; + } + + ~PathIterator() { + Py_XDECREF(vertices); + Py_XDECREF(codes); + } + + static const char code_map[]; + + inline unsigned vertex(unsigned idx, double* x, double* y) { + if (idx > m_total_vertices) + throw Py::RuntimeError("Requested vertex past end"); + 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]))]; + } + + inline unsigned vertex(double* x, double* y) { + if(m_iterator >= m_total_vertices) return agg::path_cmd_stop; + return vertex(m_iterator++, x, y); + } + + inline void rewind(unsigned path_id) { + m_iterator = path_id; + } + + inline unsigned total_vertices() { + return m_total_vertices; + } +}; + +const char PathIterator::code_map[] = {0, + agg::path_cmd_move_to, + agg::path_cmd_line_to, + agg::path_cmd_curve3, + agg::path_cmd_curve4, + agg::path_cmd_end_poly | agg::path_flags_close}; + 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), @@ -634,7 +700,7 @@ if (num_vertices) { for (size_t j=0; j<num_vertices; ++j) GET_NEXT_VERTEX(x, y); - if (code_i == IGNORE) + if (*code_i == STOP || *code_i == CLOSEPOLY) continue; trans.transform(&x, &y); @@ -863,9 +929,10 @@ for (size_t i = 0; i < N; ++i) { switch (*(unsigned char*)(code_i)) { - case IGNORE: + case STOP: GET_NEXT_VERTEX(x0, y0); - _VERBOSE("IGNORE"); + _VERBOSE("STOP"); + // MGDTODO: If this isn't the end, we should raise an error break; case MOVETO: GET_NEXT_VERTEX(x0, y0); @@ -894,10 +961,10 @@ break; case CLOSEPOLY: close_polygon(); + GET_NEXT_VERTEX(x0, y0); _VERBOSE("CLOSEPOLY"); break; } - code_i += code_stride; } } catch(...) { Py_XDECREF(vertices); @@ -911,7 +978,7 @@ Py::Object RendererAgg::draw_path(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; @@ -928,9 +995,11 @@ GCAgg gc = GCAgg(args[0], dpi); 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()); +// 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); @@ -943,34 +1012,34 @@ bool has_clippath = (gc.clippath != NULL); 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; +// 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; } 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 (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); + tpath = new transformed_path_t(path, trans); } // Benchmarking shows that there is no noticable slowdown to always Modified: branches/transforms/src/_backend_agg.h =================================================================== --- branches/transforms/src/_backend_agg.h 2007-09-19 19:46:34 UTC (rev 3859) +++ branches/transforms/src/_backend_agg.h 2007-09-19 19:48:17 UTC (rev 3860) @@ -40,14 +40,14 @@ #include "agg_vcgen_markers_term.h" // These are copied directly from path.py, and must be kept in sync -#define IGNORE 0 +#define STOP 0 #define MOVETO 1 #define LINETO 2 #define CURVE3 3 #define CURVE4 4 #define CLOSEPOLY 5 -const size_t NUM_VERTICES[] = { 1, 1, 1, 2, 3, 0 }; +const size_t NUM_VERTICES[] = { 1, 1, 1, 2, 3, 1 }; typedef agg::pixfmt_rgba32 pixfmt; typedef agg::renderer_base<pixfmt> renderer_base; 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