Revision: 4473
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4473&view=rev
Author:   mdboom
Date:     2007-11-27 12:03:48 -0800 (Tue, 27 Nov 2007)

Log Message:
-----------
Improve speed of quad mesh drawing (by about 25%)

Modified Paths:
--------------
    branches/transforms/src/_backend_agg.cpp
    branches/transforms/src/_backend_agg.h

Modified: branches/transforms/src/_backend_agg.cpp
===================================================================
--- branches/transforms/src/_backend_agg.cpp    2007-11-27 18:34:38 UTC (rev 
4472)
+++ branches/transforms/src/_backend_agg.cpp    2007-11-27 20:03:48 UTC (rev 
4473)
@@ -348,10 +348,13 @@
 
 template<class Path>
 bool should_snap(Path& path, const agg::trans_affine& trans) {
-  // If this is a straight horizontal or vertical line, quantize to nearest
+  // If this contains only straight horizontal or vertical lines, quantize to 
nearest
   // pixels
   double x0, y0, x1, y1;
   unsigned code;
+  if (path.total_vertices() > 5)
+    return false;
+
   code = path.vertex(&x0, &y0);
   trans.transform(&x0, &y0);
 
@@ -742,38 +745,20 @@
   return Py::Object();
 }
 
-template<class PathIteratorType>
-void RendererAgg::_draw_path(PathIteratorType& path, agg::trans_affine trans,
-                            bool has_clippath, const facepair_t& face,
-                            const GCAgg& gc, bool check_snap) {
-  typedef agg::conv_transform<PathIteratorType>                     
transformed_path_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;
+template<class path_t>
+void RendererAgg::_draw_path(path_t& path, bool has_clippath,
+                            const facepair_t& face, const GCAgg& gc) {
+  typedef agg::conv_stroke<path_t>                          stroke_t;
+  typedef agg::conv_dash<path_t>                            dash_t;
   typedef agg::conv_stroke<dash_t>                          stroke_dash_t;
   typedef agg::pixfmt_amask_adaptor<pixfmt, alpha_mask_type> pixfmt_amask_type;
   typedef agg::renderer_base<pixfmt_amask_type>                     
amask_ren_type;
   typedef agg::renderer_scanline_aa_solid<amask_ren_type>    
amask_aa_renderer_type;
   typedef agg::renderer_scanline_bin_solid<amask_ren_type>   
amask_bin_renderer_type;
 
-  trans *= agg::trans_affine_scaling(1.0, -1.0);
-  trans *= agg::trans_affine_translation(0.0, (double)height);
-
-  // Build the transform stack
-  bool snap = false;
-  if (check_snap)
-    snap = should_snap(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(quantized);
-
   // Render face
   if (face.first) {
-    theRasterizer->add_path(curve);
+    theRasterizer->add_path(path);
 
     if (gc.isaa) {
       if (has_clippath) {
@@ -803,22 +788,21 @@
   // Render stroke
   if (gc.linewidth != 0.0) {
     double linewidth = gc.linewidth;
-    if (snap)
+    if (!gc.isaa)
       linewidth = round(linewidth);
-
     if (gc.dashes.size() == 0) {
-      stroke_t stroke(curve);
+      stroke_t stroke(path);
       stroke.width(linewidth);
       stroke.line_cap(gc.cap);
       stroke.line_join(gc.join);
       theRasterizer->add_path(stroke);
     } else {
-      dash_t dash(curve);
+      dash_t dash(path);
       for (GCAgg::dash_t::const_iterator i = gc.dashes.begin();
           i != gc.dashes.end(); ++i) {
        double val0 = i->first;
        double val1 = i->second;
-       if (snap) {
+       if (!gc.isaa) {
          val0 = (int)val0 + 0.5;
          val1 = (int)val1 + 0.5;
        }
@@ -831,7 +815,7 @@
       theRasterizer->add_path(stroke);
     }
 
-    if (gc.isaa && !(snap)) {
+    if (gc.isaa) {
       if (has_clippath) {
        pixfmt_amask_type pfa(*pixFmt, *alphaMask);
        amask_ren_type r(pfa);
@@ -859,6 +843,10 @@
 
 Py::Object
 RendererAgg::draw_path(const Py::Tuple& args) {
+  typedef agg::conv_transform<PathIterator>    transformed_path_t;
+  typedef conv_quantize<transformed_path_t>    quantize_t;
+  typedef agg::conv_curve<quantize_t>          curve_t;
+
   _VERBOSE("RendererAgg::draw_path");
   args.verify_length(3, 4);
 
@@ -878,15 +866,24 @@
   set_clipbox(gc.cliprect, theRasterizer);
   bool has_clippath = render_clippath(gc.clippath, gc.clippath_trans);
 
-  _draw_path(path, trans, has_clippath, face, gc, true);
+  trans *= agg::trans_affine_scaling(1.0, -1.0);
+  trans *= agg::trans_affine_translation(0.0, (double)height);
+  bool snap = should_snap(path, trans);
+  transformed_path_t tpath(path, trans);
+  quantize_t quantized(tpath, snap);
+  curve_t curve(quantized);
+  if (snap)
+    gc.isaa = false;
 
+  _draw_path(curve, has_clippath, face, gc);
+
   return Py::Object();
 }
 
-template<class PathGenerator>
+template<class PathGenerator, int check_snap, int has_curves>
 Py::Object
 RendererAgg::_draw_path_collection_generic
-  (const agg::trans_affine&      master_transform,
+  (agg::trans_affine             master_transform,
    const Py::Object&             cliprect,
    const Py::Object&             clippath,
    const agg::trans_affine&       clippath_trans,
@@ -898,8 +895,12 @@
    const Py::Object&              edgecolors_obj,
    const Py::SeqBase<Py::Float>&  linewidths,
    const Py::SeqBase<Py::Object>& linestyles_obj,
-   const Py::SeqBase<Py::Int>&    antialiaseds,
-   bool                           check_snap) {
+   const Py::SeqBase<Py::Int>&    antialiaseds) {
+  typedef agg::conv_transform<typename PathGenerator::path_iterator> 
transformed_path_t;
+  typedef conv_quantize<transformed_path_t>                         quantize_t;
+  typedef agg::conv_curve<quantize_t>                               
quantized_curve_t;
+  typedef agg::conv_curve<transformed_path_t>                       curve_t;
+
   GCAgg gc(dpi);
 
   PyArrayObject* offsets    = NULL;
@@ -944,6 +945,9 @@
     size_t i = 0;
 
     // Convert all of the transforms up front
+    master_transform *= agg::trans_affine_scaling(1.0, -1.0);
+    master_transform *= agg::trans_affine_translation(0.0, (double)height);
+
     typedef std::vector<agg::trans_affine> transforms_t;
     transforms_t transforms;
     transforms.reserve(Ntransforms);
@@ -975,6 +979,7 @@
     facepair_t face;
     face.first = Nfacecolors != 0;
     agg::trans_affine trans;
+    bool snap = false;
 
     for (i = 0; i < N; ++i) {
       typename PathGenerator::path_iterator path = path_generator(i);
@@ -1016,9 +1021,32 @@
        }
       }
 
-      gc.isaa = bool(Py::Int(antialiaseds[i % Naa]));
+      if (check_snap) {
+       snap = should_snap(path, trans);
+       if (snap)
+         gc.isaa = false;
+       else
+         gc.isaa = bool(Py::Int(antialiaseds[i % Naa]));
 
-      _draw_path(path, trans, has_clippath, face, gc, check_snap);
+       transformed_path_t tpath(path, trans);
+       quantize_t quantized(tpath, snap);
+       if (has_curves) {
+         quantized_curve_t curve(quantized);
+         _draw_path(curve, has_clippath, face, gc);
+       } else {
+         _draw_path(quantized, has_clippath, face, gc);
+       }
+      } else {
+       gc.isaa = bool(Py::Int(antialiaseds[i % Naa]));
+
+       transformed_path_t tpath(path, trans);
+       if (has_curves) {
+         curve_t curve(tpath);
+         _draw_path(curve, has_clippath, face, gc);
+       } else {
+         _draw_path(tpath, has_clippath, face, gc);
+       }
+      }
     }
   } catch (...) {
     Py_XDECREF(offsets);
@@ -1075,7 +1103,7 @@
 
   PathListGenerator path_generator(paths);
 
-  _draw_path_collection_generic
+  _draw_path_collection_generic<PathListGenerator, 1, 1>
     (master_transform,
      cliprect,
      clippath,
@@ -1088,8 +1116,7 @@
      edgecolors_obj,
      linewidths,
      linestyles_obj,
-     antialiaseds,
-     true);
+     antialiaseds);
 
   return Py::Object();
 }
@@ -1108,19 +1135,18 @@
       m_iterator(0), m_m(m), m_n(n), m_coordinates(coordinates) {
     }
 
-    static const size_t offsets[5][2];
-
     inline unsigned vertex(unsigned idx, double* x, double* y) {
-      size_t m = m_m + offsets[idx][0];
-      size_t n = m_n + offsets[idx][1];
+      size_t m = (idx   & 0x2) ? (m_m + 1) : m_m;
+      size_t n = (idx+1 & 0x2) ? (m_n + 1) : m_n;
       double* pair = (double*)PyArray_GETPTR2(m_coordinates, m, n);
       *x = *pair++;
       *y = *pair;
-      return (idx == 0) ? agg::path_cmd_move_to : agg::path_cmd_line_to;
+      return (idx) ? agg::path_cmd_line_to : agg::path_cmd_move_to;
     }
 
     inline unsigned vertex(double* x, double* y) {
-      if (m_iterator >= total_vertices()) return agg::path_cmd_stop;
+      if (m_iterator >= total_vertices()) 
+       return agg::path_cmd_stop;
       return vertex(m_iterator++, x, y);
     }
 
@@ -1159,13 +1185,6 @@
   }
 };
 
-const size_t QuadMeshGenerator::QuadMeshPathIterator::offsets[5][2] = {
-      { 0, 0 },
-      { 0, 1 },
-      { 1, 1 },
-      { 1, 0 },
-      { 0, 0 } };
-
 Py::Object
 RendererAgg::draw_quad_mesh(const Py::Tuple& args) {
   _VERBOSE("RendererAgg::draw_quad_mesh");
@@ -1208,7 +1227,7 @@
     }
   }
 
-  _draw_path_collection_generic
+  _draw_path_collection_generic<QuadMeshGenerator, 0, 0>
     (master_transform,
      cliprect,
      clippath,
@@ -1221,8 +1240,7 @@
      edgecolors_obj,
      linewidths,
      linestyles_obj,
-     antialiaseds,
-     false);
+     antialiaseds);
 
   return Py::Object();
 }

Modified: branches/transforms/src/_backend_agg.h
===================================================================
--- branches/transforms/src/_backend_agg.h      2007-11-27 18:34:38 UTC (rev 
4472)
+++ branches/transforms/src/_backend_agg.h      2007-11-27 20:03:48 UTC (rev 
4473)
@@ -226,16 +226,16 @@
   void set_clipbox(const Py::Object& cliprect, R rasterizer);
   bool render_clippath(const Py::Object& clippath, const agg::trans_affine& 
clippath_trans);
   template<class PathIteratorType>
-  void _draw_path(PathIteratorType& path, agg::trans_affine trans, 
-                 bool has_clippath, const facepair_t& face, const GCAgg& gc, 
bool check_snap);
-  template<class PathGenerator>
+  void _draw_path(PathIteratorType& path, bool has_clippath,
+                 const facepair_t& face, const GCAgg& gc);
+  template<class PathGenerator, int check_snap, int has_curves>
   Py::Object
   _draw_path_collection_generic
-    (const agg::trans_affine&      master_transform,
+    (agg::trans_affine                     master_transform,
      const Py::Object&             cliprect,
      const Py::Object&             clippath,
      const agg::trans_affine&       clippath_trans,
-     const PathGenerator&          path_finder,
+     const PathGenerator&          path_generator,
      const Py::SeqBase<Py::Object>& transforms_obj,
      const Py::Object&              offsets_obj,
      const agg::trans_affine&       offset_trans,
@@ -243,8 +243,7 @@
      const Py::Object&              edgecolors_obj,
      const Py::SeqBase<Py::Float>&  linewidths,
      const Py::SeqBase<Py::Object>& linestyles_obj,
-     const Py::SeqBase<Py::Int>&    antialiaseds,
-     bool                           check_snap);
+     const Py::SeqBase<Py::Int>&    antialiaseds);
 
 private:
   Py::Object lastclippath;


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
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to