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

Reply via email to