From: <md...@us...> - 2007-10-24 17:11:12
|
Revision: 3993 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3993&view=rev Author: mdboom Date: 2007-10-24 10:11:00 -0700 (Wed, 24 Oct 2007) Log Message: ----------- Forgot to svn add these files in last commit. Added Paths: ----------- branches/transforms/src/_path.cpp branches/transforms/src/agg_py_transforms.h Added: branches/transforms/src/_path.cpp =================================================================== --- branches/transforms/src/_path.cpp (rev 0) +++ branches/transforms/src/_path.cpp 2007-10-24 17:11:00 UTC (rev 3993) @@ -0,0 +1,384 @@ +#include "agg_py_path_iterator.h" +#include "agg_py_transforms.h" + +#include "CXX/Extensions.hxx" + +#include "agg_conv_curve.h" +#include "agg_conv_stroke.h" +#include "agg_conv_transform.h" +#include "agg_path_storage.h" +#include "agg_trans_affine.h" + +// the extension module +class _path_module : public Py::ExtensionModule<_path_module> +{ +public: + _path_module() + : Py::ExtensionModule<_path_module>( "_path" ) + { + add_varargs_method("point_in_path", &_path_module::point_in_path, + "point_in_path(x, y, path, trans)"); + add_varargs_method("point_on_path", &_path_module::point_on_path, + "point_on_path(x, y, r, path, trans)"); + add_varargs_method("get_path_extents", &_path_module::get_path_extents, + "get_path_extents(path, trans)"); + add_varargs_method("get_path_collection_extents", &_path_module::get_path_collection_extents, + "get_path_collection_extents(trans, paths, transforms, offsets, offsetTrans)"); + add_varargs_method("point_in_path_collection", &_path_module::point_in_path_collection, + "point_in_path_collection(x, y, r, trans, paths, transforms, offsets, offsetTrans, filled)"); + + initialize("Helper functions for paths"); + } + + virtual ~_path_module() {} + +private: + + Py::Object point_in_path(const Py::Tuple& args); + Py::Object point_on_path(const Py::Tuple& args); + Py::Object get_path_extents(const Py::Tuple& args); + Py::Object get_path_collection_extents(const Py::Tuple& args); + Py::Object point_in_path_collection(const Py::Tuple& args); +}; + +// +// The following function was found in the Agg 2.3 examples (interactive_polygon.cpp). +// It has been generalized to work on (possibly curved) polylines, rather than +// just polygons. The original comments have been kept intact. +// -- Michael Droettboom 2007-10-02 +// +//======= Crossings Multiply algorithm of InsideTest ======================== +// +// By Eric Haines, 3D/Eye Inc, er...@ey... +// +// This version is usually somewhat faster than the original published in +// Graphics Gems IV; by turning the division for testing the X axis crossing +// into a tricky multiplication test this part of the test became faster, +// which had the additional effect of making the test for "both to left or +// both to right" a bit slower for triangles than simply computing the +// intersection each time. The main increase is in triangle testing speed, +// which was about 15% faster; all other polygon complexities were pretty much +// the same as before. On machines where division is very expensive (not the +// case on the HP 9000 series on which I tested) this test should be much +// faster overall than the old code. Your mileage may (in fact, will) vary, +// depending on the machine and the test data, but in general I believe this +// code is both shorter and faster. This test was inspired by unpublished +// Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson. +// Related work by Samosky is in: +// +// Samosky, Joseph, "SectionView: A system for interactively specifying and +// visualizing sections through three-dimensional medical image data", +// M.S. Thesis, Department of Electrical Engineering and Computer Science, +// Massachusetts Institute of Technology, 1993. +// +// Shoot a test ray along +X axis. The strategy is to compare vertex Y values +// to the testing point's Y and quickly discard edges which are entirely to one +// side of the test ray. Note that CONVEX and WINDING code can be added as +// for the CrossingsTest() code; it is left out here for clarity. +// +// Input 2D polygon _pgon_ with _numverts_ number of vertices and test point +// _point_, returns 1 if inside, 0 if outside. +template<class T> +bool point_in_path_impl(double tx, double ty, T& path) { + int yflag0, yflag1, inside_flag; + double vtx0, vty0, vtx1, vty1, sx, sy; + double x, y; + + path.rewind(0); + unsigned code = path.vertex(&x, &y); + if (code == agg::path_cmd_stop) + return false; + + while (true) { + sx = vtx0 = x; + sy = vty0 = y; + + // get test bit for above/below X axis + yflag0 = (vty0 >= ty); + + vtx1 = x; + vty1 = x; + + inside_flag = 0; + while (true) { + code = path.vertex(&x, &y); + + // The following cases denote the beginning on a new subpath + if ((code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) { + x = sx; y = sy; + } else if (code == agg::path_cmd_move_to) + break; + + yflag1 = (vty1 >= ty); + // Check if endpoints straddle (are on opposite sides) of X axis + // (i.e. the Y's differ); if so, +X ray could intersect this edge. + // The old test also checked whether the endpoints are both to the + // right or to the left of the test point. However, given the faster + // intersection point computation used below, this test was found to + // be a break-even proposition for most polygons and a loser for + // triangles (where 50% or more of the edges which survive this test + // will cross quadrants and so have to have the X intersection computed + // anyway). I credit Joseph Samosky with inspiring me to try dropping + // the "both left or both right" part of my code. + if (yflag0 != yflag1) { + // Check intersection of pgon segment with +X ray. + // Note if >= point's X; if so, the ray hits it. + // The division operation is avoided for the ">=" test by checking + // the sign of the first vertex wrto the test point; idea inspired + // by Joseph Samosky's and Mark Haigh-Hutchinson's different + // polygon inclusion tests. + if ( ((vty1-ty) * (vtx0-vtx1) >= + (vtx1-tx) * (vty0-vty1)) == yflag1 ) { + inside_flag ^= 1; + } + } + + // Move to the next pair of vertices, retaining info as possible. + yflag0 = yflag1; + vtx0 = vtx1; + vty0 = vty1; + + vtx1 = x; + vty1 = y; + + if (code == agg::path_cmd_stop || + (code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) + break; + } + + if (inside_flag != 0) + return true; + + if (code == agg::path_cmd_stop) + return false; + } + + return false; +} + +bool point_in_path(double x, double y, PathIterator& path, agg::trans_affine& trans) { + typedef agg::conv_transform<PathIterator> transformed_path_t; + typedef agg::conv_curve<transformed_path_t> curve_t; + + transformed_path_t trans_path(path, trans); + curve_t curved_path(trans_path); + return point_in_path_impl(x, y, curved_path); +} + +bool point_on_path(double x, double y, double r, PathIterator& path, agg::trans_affine& trans) { + 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; + + transformed_path_t trans_path(path, trans); + curve_t curved_path(trans_path); + stroke_t stroked_path(curved_path); + stroked_path.width(r * 2.0); + return point_in_path_impl(x, y, stroked_path); +} + +Py::Object _path_module::point_in_path(const Py::Tuple& args) { + args.verify_length(4); + + double x = Py::Float(args[0]); + double y = Py::Float(args[1]); + PathIterator path(args[2]); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[3]); + + if (::point_in_path(x, y, path, trans)) + return Py::Int(1); + return Py::Int(0); +} + +Py::Object _path_module::point_on_path(const Py::Tuple& args) { + args.verify_length(5); + + double x = Py::Float(args[0]); + double y = Py::Float(args[1]); + double r = Py::Float(args[2]); + PathIterator path(args[3]); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[4]); + + if (::point_on_path(x, y, r, path, trans)) + return Py::Int(1); + return Py::Int(0); +} + +void get_path_extents(PathIterator& path, agg::trans_affine& trans, + double* x0, double* y0, double* x1, double* y1) { + typedef agg::conv_transform<PathIterator> transformed_path_t; + typedef agg::conv_curve<transformed_path_t> curve_t; + double x, y; + unsigned code; + + transformed_path_t tpath(path, trans); + curve_t curved_path(tpath); + + curved_path.rewind(0); + + while ((code = curved_path.vertex(&x, &y)) != agg::path_cmd_stop) { + if ((code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) + continue; + if (x < *x0) *x0 = x; + if (y < *y0) *y0 = y; + if (x > *x1) *x1 = x; + if (y > *y1) *y1 = y; + } +} + +Py::Object _path_module::get_path_extents(const Py::Tuple& args) { + args.verify_length(2); + + PathIterator path(args[0]); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[1]); + + double x0 = std::numeric_limits<double>::infinity(); + double y0 = std::numeric_limits<double>::infinity(); + double x1 = -std::numeric_limits<double>::infinity(); + double y1 = -std::numeric_limits<double>::infinity(); + + ::get_path_extents(path, trans, &x0, &y0, &x1, &y1); + + Py::Tuple result(4); + result[0] = Py::Float(x0); + result[1] = Py::Float(y0); + result[2] = Py::Float(x1); + result[3] = Py::Float(y1); + return result; +} + +Py::Object _path_module::get_path_collection_extents(const Py::Tuple& args) { + args.verify_length(5); + + //segments, trans, clipbox, colors, linewidths, antialiaseds + agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[0]); + Py::SeqBase<Py::Object> paths = args[1]; + Py::SeqBase<Py::Object> transforms_obj = args[2]; + Py::Object offsets_obj = args[3]; + agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[4], false); + + PyArrayObject* offsets = NULL; + double x0, y0, x1, y1; + + try { + offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj.ptr(), PyArray_DOUBLE, 2, 2); + if (!offsets || offsets->dimensions[1] != 2) + throw Py::ValueError("Offsets array must be Nx2"); + + size_t Npaths = paths.length(); + size_t Noffsets = offsets->dimensions[0]; + size_t N = std::max(Npaths, Noffsets); + size_t Ntransforms = std::min(transforms_obj.length(), N); + size_t i; + + // Convert all of the transforms up front + typedef std::vector<agg::trans_affine> transforms_t; + transforms_t transforms; + transforms.reserve(Ntransforms); + for (i = 0; i < Ntransforms; ++i) { + agg::trans_affine trans = py_to_agg_transformation_matrix + (transforms_obj[i], false); + trans *= master_transform; + transforms.push_back(trans); + } + + // The offset each of those and collect the mins/maxs + x0 = std::numeric_limits<double>::infinity(); + y0 = std::numeric_limits<double>::infinity(); + x1 = -std::numeric_limits<double>::infinity(); + y1 = -std::numeric_limits<double>::infinity(); + for (i = 0; i < N; ++i) { + PathIterator path(paths[i % Npaths]); + + double xo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 0); + double yo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 1); + offset_trans.transform(&xo, &yo); + agg::trans_affine_translation transOffset(xo, yo); + agg::trans_affine trans = transforms[i % Ntransforms]; + trans *= transOffset; + + ::get_path_extents(path, trans, &x0, &y0, &x1, &y1); + } + } catch (...) { + Py_XDECREF(offsets); + throw; + } + + Py_XDECREF(offsets); + + Py::Tuple result(4); + result[0] = Py::Float(x0); + result[1] = Py::Float(y0); + result[2] = Py::Float(x1); + result[3] = Py::Float(y1); + return result; +} + +Py::Object _path_module::point_in_path_collection(const Py::Tuple& args) { + args.verify_length(9); + + //segments, trans, clipbox, colors, linewidths, antialiaseds + double x = Py::Float(args[0]); + double y = Py::Float(args[1]); + double radius = Py::Float(args[2]); + agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[3]); + Py::SeqBase<Py::Object> paths = args[4]; + Py::SeqBase<Py::Object> transforms_obj = args[5]; + Py::SeqBase<Py::Object> offsets_obj = args[6]; + agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[7]); + bool filled = Py::Int(args[8]); + + PyArrayObject* offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj.ptr(), PyArray_DOUBLE, 2, 2); + if (!offsets || offsets->dimensions[1] != 2) + throw Py::ValueError("Offsets array must be Nx2"); + + size_t Npaths = paths.length(); + size_t Noffsets = offsets->dimensions[0]; + size_t N = std::max(Npaths, Noffsets); + size_t Ntransforms = std::min(transforms_obj.length(), N); + size_t i; + + // Convert all of the transforms up front + typedef std::vector<agg::trans_affine> transforms_t; + transforms_t transforms; + transforms.reserve(Ntransforms); + for (i = 0; i < Ntransforms; ++i) { + agg::trans_affine trans = py_to_agg_transformation_matrix + (transforms_obj[i], false); + trans *= master_transform; + transforms.push_back(trans); + } + + Py::List result; + + for (i = 0; i < N; ++i) { + PathIterator path(paths[i % Npaths]); + + double xo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 0); + double yo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 1); + offset_trans.transform(&xo, &yo); + agg::trans_affine_translation transOffset(xo, yo); + agg::trans_affine trans = transforms[i % Ntransforms]; + trans *= transOffset; + + if (filled) { + if (::point_in_path(x, y, path, trans)) + result.append(Py::Int((int)i)); + } else { + if (::point_on_path(x, y, radius, path, trans)) + result.append(Py::Int((int)i)); + } + } + + return result; +} + +extern "C" +DL_EXPORT(void) + init_path(void) +{ + import_array(); + + static _path_module* _path = NULL; + _path = new _path_module; +}; Added: branches/transforms/src/agg_py_transforms.h =================================================================== --- branches/transforms/src/agg_py_transforms.h (rev 0) +++ branches/transforms/src/agg_py_transforms.h 2007-10-24 17:11:00 UTC (rev 3993) @@ -0,0 +1,58 @@ +#ifndef __AGG_PY_TRANSFORMS_H__ +#define __AGG_PY_TRANSFORMS_H__ + +#define PY_ARRAY_TYPES_PREFIX NumPy +#include "numpy/arrayobject.h" + +#include "CXX/Objects.hxx" +#include "agg_trans_affine.h" + + +/** A helper function to convert from a Numpy affine transformation matrix + * to an agg::trans_affine. + */ +agg::trans_affine py_to_agg_transformation_matrix(const Py::Object& obj, bool errors = true) { + PyArrayObject* matrix = NULL; + + try { + if (obj.ptr() == Py_None) + throw std::exception(); + matrix = (PyArrayObject*) PyArray_FromObject(obj.ptr(), PyArray_DOUBLE, 2, 2); + if (!matrix) + throw std::exception(); + 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); + } + + throw std::exception(); + } catch (...) { + if (errors) { + Py_XDECREF(matrix); + throw Py::TypeError("Invalid affine transformation matrix"); + } + } + + Py_XDECREF(matrix); + return agg::trans_affine(); +} + +#endif // __AGG_PY_TRANSFORMS_H__ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-11-07 20:38:49
|
Revision: 4153 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4153&view=rev Author: mdboom Date: 2007-11-07 12:38:46 -0800 (Wed, 07 Nov 2007) Log Message: ----------- Update to use modern Numpy C API Modified Paths: -------------- branches/transforms/src/_backend_agg.cpp branches/transforms/src/_path.cpp Modified: branches/transforms/src/_backend_agg.cpp =================================================================== --- branches/transforms/src/_backend_agg.cpp 2007-11-07 20:13:35 UTC (rev 4152) +++ branches/transforms/src/_backend_agg.cpp 2007-11-07 20:38:46 UTC (rev 4153) @@ -280,7 +280,7 @@ if (bbox_obj.ptr() != Py_None) { bbox = (PyArrayObject*) PyArray_FromObject(bbox_obj.ptr(), PyArray_DOUBLE, 2, 2); - if (!bbox || bbox->nd != 2 || bbox->dimensions[0] != 2 || bbox->dimensions[1] != 2) { + if (!bbox || PyArray_NDIM(bbox) != 2 || PyArray_DIM(bbox, 0) != 2 || PyArray_DIM(bbox, 1) != 2) { Py_XDECREF(bbox); throw Py::TypeError ("Expected a Bbox object."); @@ -942,23 +942,23 @@ try { offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj.ptr(), PyArray_DOUBLE, 0, 2); if (!offsets || - (offsets->nd == 2 && offsets->dimensions[1] != 2) || - (offsets->nd == 1 && offsets->dimensions[0])) { + (PyArray_NDIM(offsets) == 2 && PyArray_DIM(offsets, 1) != 2) || + (PyArray_NDIM(offsets) == 1 && PyArray_DIM(offsets, 0) != 0)) { throw Py::ValueError("Offsets array must be Nx2"); } PyArrayObject* facecolors = (PyArrayObject*)PyArray_FromObject (facecolors_obj.ptr(), PyArray_DOUBLE, 1, 2); if (!facecolors || - (facecolors->nd == 1 && facecolors->dimensions[0] != 0) || - (facecolors->nd == 2 && facecolors->dimensions[1] != 4)) + (PyArray_NDIM(facecolors) == 1 && PyArray_DIM(facecolors, 0) != 0) || + (PyArray_NDIM(facecolors) == 2 && PyArray_DIM(facecolors, 1) != 4)) throw Py::ValueError("Facecolors must be a Nx4 numpy array or empty"); PyArrayObject* edgecolors = (PyArrayObject*)PyArray_FromObject (edgecolors_obj.ptr(), PyArray_DOUBLE, 1, 2); if (!edgecolors || - (edgecolors->nd == 1 && edgecolors->dimensions[0] != 0) || - (edgecolors->nd == 2 && edgecolors->dimensions[1] != 4)) + (PyArray_NDIM(edgecolors) == 1 && PyArray_DIM(edgecolors, 0) != 0) || + (PyArray_NDIM(edgecolors) == 2 && PyArray_DIM(edgecolors, 1) != 4)) throw Py::ValueError("Edgecolors must be a Nx4 numpy array"); size_t Npaths = path_generator.num_paths(); @@ -1178,11 +1178,11 @@ throw Py::ValueError("Invalid coordinates array."); } - Py::Tuple shape(3); - shape[0] = Py::Int((int)meshHeight + 1); - shape[1] = Py::Int((int)meshWidth + 1); - shape[2] = Py::Int(2); - m_coordinates = (PyArrayObject*)PyArray_Reshape(coordinates_array, shape.ptr()); + PyArray_Dims shape; + npy_intp dims[] = { meshHeight + 1, meshWidth + 1, 2 }; + shape.ptr = dims; + shape.len = 3; + m_coordinates = (PyArrayObject*)PyArray_Newshape(coordinates_array, &shape, PyArray_CORDER); } inline ~QuadMeshGenerator() { @@ -1237,13 +1237,13 @@ if (showedges) { int dims[] = { 1, 4, 0 }; double data[] = { 0, 0, 0, 1 }; - edgecolors_obj = PyArray_FromDimsAndData(2, dims, PyArray_DOUBLE, (char*)data); + edgecolors_obj = PyArray_SimpleNewFromData(2, dims, PyArray_DOUBLE, (char*)data); } else { if (antialiased) { edgecolors_obj = facecolors_obj; } else { int dims[] = { 0, 0 }; - edgecolors_obj = PyArray_FromDims(1, dims, PyArray_DOUBLE); + edgecolors_obj = PyArray_SimpleNew(1, dims, PyArray_DOUBLE); } } Modified: branches/transforms/src/_path.cpp =================================================================== --- branches/transforms/src/_path.cpp 2007-11-07 20:13:35 UTC (rev 4152) +++ branches/transforms/src/_path.cpp 2007-11-07 20:38:46 UTC (rev 4153) @@ -263,8 +263,8 @@ try { offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj.ptr(), PyArray_DOUBLE, 0, 2); if (!offsets || - (offsets->nd == 2 && offsets->dimensions[1] != 2) || - (offsets->nd == 1 && offsets->dimensions[0])) { + (PyArray_NDIM(offsets) == 2 && PyArray_DIM(offsets, 1) != 2) || + (PyArray_NDIM(offsets) == 1 && PyArray_DIM(offsets, 0) != 0)) { throw Py::ValueError("Offsets array must be Nx2"); } @@ -338,9 +338,12 @@ agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[7]); bool filled = Py::Int(args[8]); - PyArrayObject* offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj.ptr(), PyArray_DOUBLE, 2, 2); - if (!offsets || offsets->dimensions[1] != 2) + PyArrayObject* offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj.ptr(), PyArray_DOUBLE, 0, 2); + if (!offsets || + (PyArray_NDIM(offsets) == 2 && PyArray_DIM(offsets, 1) != 2) || + (PyArray_NDIM(offsets) == 1 && PyArray_DIM(offsets, 0) != 0)) { throw Py::ValueError("Offsets array must be Nx2"); + } size_t Npaths = paths.length(); size_t Noffsets = offsets->dimensions[0]; @@ -360,17 +363,24 @@ } Py::List result; + agg::trans_affine trans; for (i = 0; i < N; ++i) { PathIterator path(paths[i % Npaths]); - - double xo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 0); - double yo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 1); - offset_trans.transform(&xo, &yo); - agg::trans_affine_translation transOffset(xo, yo); - agg::trans_affine trans = transforms[i % Ntransforms]; - trans *= transOffset; + if (Ntransforms) { + trans = transforms[i % Ntransforms]; + } else { + trans = master_transform; + } + + if (Noffsets) { + double xo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 0); + double yo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 1); + offset_trans.transform(&xo, &yo); + trans *= agg::trans_affine_translation(xo, yo); + } + if (filled) { if (::point_in_path(x, y, path, trans)) result.append(Py::Int((int)i)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-11-08 14:06:27
|
Revision: 4159 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4159&view=rev Author: mdboom Date: 2007-11-08 06:06:25 -0800 (Thu, 08 Nov 2007) Log Message: ----------- Get wxagg extension working again. Factor out the new Bbox conversion code into agg_py_transforms.h Modified Paths: -------------- branches/transforms/src/_backend_agg.cpp branches/transforms/src/_backend_agg.h branches/transforms/src/_gtkagg.cpp branches/transforms/src/_tkagg.cpp branches/transforms/src/_wxagg.cpp branches/transforms/src/agg_py_transforms.h Modified: branches/transforms/src/_backend_agg.cpp =================================================================== --- branches/transforms/src/_backend_agg.cpp 2007-11-08 14:05:18 UTC (rev 4158) +++ branches/transforms/src/_backend_agg.cpp 2007-11-08 14:06:25 UTC (rev 4159) @@ -273,33 +273,6 @@ }; -bool -RendererAgg::bbox_to_rect(const Py::Object& bbox_obj, double* l, double* b, double* r, double* t) { - PyArrayObject* bbox = NULL; - - if (bbox_obj.ptr() != Py_None) { - bbox = (PyArrayObject*) PyArray_FromObject(bbox_obj.ptr(), PyArray_DOUBLE, 2, 2); - - if (!bbox || PyArray_NDIM(bbox) != 2 || PyArray_DIM(bbox, 0) != 2 || PyArray_DIM(bbox, 1) != 2) { - Py_XDECREF(bbox); - throw Py::TypeError - ("Expected a Bbox object."); - } - - *l = *(double*)PyArray_GETPTR2(bbox, 0, 0); - double _b = *(double*)PyArray_GETPTR2(bbox, 0, 1); - *r = *(double*)PyArray_GETPTR2(bbox, 1, 0); - double _t = *(double*)PyArray_GETPTR2(bbox, 1, 1); - *b = height - _t; - *t = height - _b; - - Py_XDECREF(bbox); - return true; - } - - return false; -} - template<class R> void RendererAgg::set_clipbox(const Py::Object& cliprect, R rasterizer) { @@ -308,7 +281,7 @@ _VERBOSE("RendererAgg::set_clipbox"); double l, b, r, t; - if (bbox_to_rect(cliprect, &l, &b, &r, &t)) { + if (py_convert_bbox(cliprect.ptr(), l, b, r, t)) { rasterizer->clip_box((int)l, (int)b, (int)r, (int)t); } @@ -408,7 +381,7 @@ Py::Object box_obj = args[0]; double l, b, r, t; - if (!bbox_to_rect(box_obj, &l, &b, &r, &t)) + if (!py_convert_bbox(box_obj.ptr(), l, b, r, t)) throw Py::TypeError("Invalid bbox provided to copy_from_bbox"); agg::rect rect((int)l, (int)b, (int)r, (int)t); Modified: branches/transforms/src/_backend_agg.h =================================================================== --- branches/transforms/src/_backend_agg.h 2007-11-08 14:05:18 UTC (rev 4158) +++ branches/transforms/src/_backend_agg.h 2007-11-08 14:06:25 UTC (rev 4159) @@ -215,7 +215,6 @@ double points_to_pixels_snapto( const Py::Object& points); agg::rgba rgb_to_color(const Py::SeqBase<Py::Object>& rgb, double alpha); facepair_t _get_rgba_face(const Py::Object& rgbFace, double alpha); - bool bbox_to_rect(const Py::Object& bbox, double* l, double* b, double* r, double* t); template<class R> void set_clipbox(const Py::Object& cliprect, R rasterizer); bool render_clippath(const Py::Object& clippath, const agg::trans_affine& clippath_trans); Modified: branches/transforms/src/_gtkagg.cpp =================================================================== --- branches/transforms/src/_gtkagg.cpp 2007-11-08 14:05:18 UTC (rev 4158) +++ branches/transforms/src/_gtkagg.cpp 2007-11-08 14:06:25 UTC (rev 4159) @@ -14,6 +14,7 @@ #include "_backend_agg.h" #define PY_ARRAY_TYPES_PREFIX NumPy #include "numpy/arrayobject.h" +#include "agg_py_transforms.h" // the extension module class _gtkagg_module : public Py::ExtensionModule<_gtkagg_module> @@ -71,31 +72,12 @@ else { //bbox is not None; copy the image in the bbox PyObject* clipbox = args[2].ptr(); - PyArrayObject* bbox = NULL; double l, b, r, t; - try { - bbox = (PyArrayObject*) PyArray_FromObject(clipbox, PyArray_DOUBLE, 2, 2); - - if (!bbox || bbox->nd != 2 || bbox->dimensions[0] != 2 || bbox->dimensions[1] != 2) { - throw Py::TypeError - ("Argument 3 to agg_to_gtk_drawable must be a Bbox object."); - } - - l = *(double*)PyArray_GETPTR2(bbox, 0, 0); - b = *(double*)PyArray_GETPTR2(bbox, 0, 1); - r = *(double*)PyArray_GETPTR2(bbox, 1, 0); - t = *(double*)PyArray_GETPTR2(bbox, 1, 1); - - Py_XDECREF(bbox); - bbox = NULL; - } catch (...) { - Py_XDECREF(bbox); - bbox = NULL; - throw; + if (!py_convert_bbox(clipbox, l, b, r, t)) { + throw Py::TypeError + ("Argument 3 to agg_to_gtk_drawable must be a Bbox object."); } - //std::cout << b << " " - // << t << " "; destx = (int)l; desty = srcheight-(int)t; @@ -118,11 +100,8 @@ agg::rect_base<int> region(destx, desty, (int)r, srcheight-(int)b); destrb.copy_from(*aggRenderer->renderingBuffer, ®ion, -destx, -desty); - - } - /*std::cout << desty << " " << destheight << " " << srcheight << std::endl;*/ Modified: branches/transforms/src/_tkagg.cpp =================================================================== --- branches/transforms/src/_tkagg.cpp 2007-11-08 14:05:18 UTC (rev 4158) +++ branches/transforms/src/_tkagg.cpp 2007-11-08 14:06:25 UTC (rev 4159) @@ -14,6 +14,7 @@ #include "agg_basics.h" #include "_backend_agg.h" +#include "agg_py_transforms.h" extern "C" { #ifdef __APPLE__ @@ -85,30 +86,9 @@ /* check for bbox/blitting */ bboxo = (PyObject*)atol(argv[4]); - if (bboxo != Py_None) { + if (py_convert_bbox(bboxo, l, b, r, t)) { has_bbox = true; - PyArrayObject* bbox = NULL; - try { - bbox = (PyArrayObject*) PyArray_FromObject(bboxo, PyArray_DOUBLE, 2, 2); - - if (!bbox || bbox->nd != 2 || bbox->dimensions[0] != 2 || bbox->dimensions[1] != 2) { - throw Py::TypeError - ("Argument 3 to agg_to_gtk_drawable must be a Bbox object."); - } - - l = *(double*)PyArray_GETPTR2(bbox, 0, 0); - b = *(double*)PyArray_GETPTR2(bbox, 0, 1); - r = *(double*)PyArray_GETPTR2(bbox, 1, 0); - t = *(double*)PyArray_GETPTR2(bbox, 1, 1); - Py_XDECREF(bbox); - bbox = NULL; - } catch (...) { - Py_XDECREF(bbox); - bbox = NULL; - throw; - } - destx = (int)l; desty = srcheight-(int)t; destwidth = (int)(r-l); Modified: branches/transforms/src/_wxagg.cpp =================================================================== --- branches/transforms/src/_wxagg.cpp 2007-11-08 14:05:18 UTC (rev 4158) +++ branches/transforms/src/_wxagg.cpp 2007-11-08 14:06:25 UTC (rev 4159) @@ -46,9 +46,9 @@ #include "agg_basics.h" #include "_backend_agg.h" -#include "_transforms.h" #include "agg_pixfmt_rgba.h" #include "util/agg_color_conv_rgb8.h" +#include "agg_py_transforms.h" #include <wx/image.h> #include <wx/bitmap.h> @@ -56,8 +56,8 @@ // forward declarations -static wxImage *convert_agg2image(RendererAgg *aggRenderer, Bbox *clipbox); -static wxBitmap *convert_agg2bitmap(RendererAgg *aggRenderer, Bbox *clipbox); +static wxImage *convert_agg2image(RendererAgg *aggRenderer, Py::Object clipbox); +static wxBitmap *convert_agg2bitmap(RendererAgg *aggRenderer, Py::Object clipbox); // the extension module @@ -94,9 +94,7 @@ RendererAgg* aggRenderer = static_cast<RendererAgg*>( args[0].getAttr("_renderer").ptr()); - Bbox *clipbox = NULL; - if (args[1].ptr() != Py_None) - clipbox = static_cast<Bbox*>(args[1].ptr()); + Py::Object clipbox = args[1]; // convert the buffer wxImage *image = convert_agg2image(aggRenderer, clipbox); @@ -118,9 +116,7 @@ RendererAgg* aggRenderer = static_cast<RendererAgg*>( args[0].getAttr("_renderer").ptr()); - Bbox *clipbox = NULL; - if (args[1].ptr() != Py_None) - clipbox = static_cast<Bbox*>(args[1].ptr()); + Py::Object clipbox = args[1]; // convert the buffer wxBitmap *bitmap = convert_agg2bitmap(aggRenderer, clipbox); @@ -141,7 +137,7 @@ // Implementation Functions // -static wxImage *convert_agg2image(RendererAgg *aggRenderer, Bbox *clipbox) +static wxImage *convert_agg2image(RendererAgg *aggRenderer, Py::Object clipbox) { int srcWidth = 1; int srcHeight = 1; @@ -150,7 +146,9 @@ bool deleteSrcBuffer = false; agg::int8u *srcBuffer = NULL; - if (clipbox == NULL) { + double l, b, r, t; + + if (!py_convert_bbox(clipbox.ptr(), l, b, r, t)) { // Convert everything: rgba => rgb -> image srcBuffer = aggRenderer->pixBuffer; srcWidth = (int) aggRenderer->get_width(); @@ -158,11 +156,6 @@ srcStride = (int) aggRenderer->get_width()*4; } else { // Convert a region: rgba => clipped rgba => rgb -> image - double l = clipbox->ll_api()->x_api()->val() ; - double b = clipbox->ll_api()->y_api()->val(); - double r = clipbox->ur_api()->x_api()->val() ; - double t = clipbox->ur_api()->y_api()->val() ; - srcWidth = (int) (r-l); srcHeight = (int) (t-b); srcStride = srcWidth*4; @@ -230,7 +223,7 @@ } -static wxBitmap *convert_agg2bitmap(RendererAgg *aggRenderer, Bbox *clipbox) +static wxBitmap *convert_agg2bitmap(RendererAgg *aggRenderer, Py::Object clipbox) { // Convert everything: rgba => rgb -> image => bitmap // Convert a region: rgba => clipped rgba => rgb -> image => bitmap Modified: branches/transforms/src/agg_py_transforms.h =================================================================== --- branches/transforms/src/agg_py_transforms.h 2007-11-08 14:05:18 UTC (rev 4158) +++ branches/transforms/src/agg_py_transforms.h 2007-11-08 14:06:25 UTC (rev 4159) @@ -7,7 +7,6 @@ #include "CXX/Objects.hxx" #include "agg_trans_affine.h" - /** A helper function to convert from a Numpy affine transformation matrix * to an agg::trans_affine. */ @@ -20,10 +19,10 @@ matrix = (PyArrayObject*) PyArray_FromObject(obj.ptr(), PyArray_DOUBLE, 2, 2); if (!matrix) throw std::exception(); - 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; + if (PyArray_NDIM(matrix) == 2 || PyArray_DIM(matrix, 0) == 3 || PyArray_DIM(matrix, 1) == 3) { + size_t stride0 = PyArray_STRIDE(matrix, 0); + size_t stride1 = PyArray_STRIDE(matrix, 1); + char* row0 = PyArray_BYTES(matrix); char* row1 = row0 + stride0; double a = *(double*)(row0); @@ -55,4 +54,35 @@ return agg::trans_affine(); } +bool py_convert_bbox(PyObject* bbox_obj, double& l, double& b, double& r, double& t) { + PyArrayObject* bbox = NULL; + + if (bbox_obj == Py_None) + return false; + + try { + bbox = (PyArrayObject*) PyArray_FromObject(bbox_obj, PyArray_DOUBLE, 2, 2); + + if (!bbox || bbox->nd != 2 || bbox->dimensions[0] != 2 || bbox->dimensions[1] != 2) { + throw Py::TypeError + ("Argument 3 to agg_to_gtk_drawable must be a Bbox object."); + } + + l = *(double*)PyArray_GETPTR2(bbox, 0, 0); + b = *(double*)PyArray_GETPTR2(bbox, 0, 1); + r = *(double*)PyArray_GETPTR2(bbox, 1, 0); + t = *(double*)PyArray_GETPTR2(bbox, 1, 1); + + Py_XDECREF(bbox); + bbox = NULL; + return true; + } catch (...) { + Py_XDECREF(bbox); + bbox = NULL; + throw; + } + + return false; +} + #endif // __AGG_PY_TRANSFORMS_H__ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-11-14 18:43:41
|
Revision: 4284 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4284&view=rev Author: mdboom Date: 2007-11-14 10:42:52 -0800 (Wed, 14 Nov 2007) Log Message: ----------- Update to use new numpy macros. Modified Paths: -------------- branches/transforms/src/agg_py_path_iterator.h branches/transforms/src/agg_py_transforms.h Modified: branches/transforms/src/agg_py_path_iterator.h =================================================================== --- branches/transforms/src/agg_py_path_iterator.h 2007-11-14 18:38:05 UTC (rev 4283) +++ branches/transforms/src/agg_py_path_iterator.h 2007-11-14 18:42:52 UTC (rev 4284) @@ -20,7 +20,7 @@ m_vertices = (PyArrayObject*)PyArray_FromObject (vertices_obj.ptr(), PyArray_DOUBLE, 2, 2); - if (!m_vertices || m_vertices->nd != 2 || m_vertices->dimensions[1] != 2) + if (!m_vertices || PyArray_NDIM(m_vertices) != 2 || PyArray_DIM(m_vertices, 1) != 2) throw Py::ValueError("Invalid vertices array."); if (codes_obj.ptr() != Py_None) { Modified: branches/transforms/src/agg_py_transforms.h =================================================================== --- branches/transforms/src/agg_py_transforms.h 2007-11-14 18:38:05 UTC (rev 4283) +++ branches/transforms/src/agg_py_transforms.h 2007-11-14 18:42:52 UTC (rev 4284) @@ -63,7 +63,7 @@ try { bbox = (PyArrayObject*) PyArray_FromObject(bbox_obj, PyArray_DOUBLE, 2, 2); - if (!bbox || bbox->nd != 2 || bbox->dimensions[0] != 2 || bbox->dimensions[1] != 2) { + if (!bbox || PyArray_NDIM(bbox) != 2 || PyArray_DIM(bbox, 0) != 2 || PyArray_DIM(bbox, 1) != 2) { throw Py::TypeError ("Argument 3 to agg_to_gtk_drawable must be a Bbox object."); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-11-26 17:23:26
|
Revision: 4448 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4448&view=rev Author: mdboom Date: 2007-11-26 09:23:18 -0800 (Mon, 26 Nov 2007) Log Message: ----------- Still trying to fix compile error on 64-bit platforms... Modified Paths: -------------- branches/transforms/src/_backend_agg.cpp branches/transforms/src/_path.cpp Modified: branches/transforms/src/_backend_agg.cpp =================================================================== --- branches/transforms/src/_backend_agg.cpp 2007-11-26 16:59:29 UTC (rev 4447) +++ branches/transforms/src/_backend_agg.cpp 2007-11-26 17:23:18 UTC (rev 4448) @@ -1203,14 +1203,14 @@ antialiaseds[0] = Py::Int(antialiased ? 1 : 0); if (showedges) { - int dims[] = { 1, 4, 0 }; + npy_intp dims[] = { 1, 4, 0 }; double data[] = { 0, 0, 0, 1 }; edgecolors_obj = PyArray_SimpleNewFromData(2, dims, PyArray_DOUBLE, (char*)data); } else { if (antialiased) { edgecolors_obj = facecolors_obj; } else { - int dims[] = { 0, 0 }; + npy_intp dims[] = { 0, 0 }; edgecolors_obj = PyArray_SimpleNew(1, dims, PyArray_DOUBLE); } } Modified: branches/transforms/src/_path.cpp =================================================================== --- branches/transforms/src/_path.cpp 2007-11-26 16:59:29 UTC (rev 4447) +++ branches/transforms/src/_path.cpp 2007-11-26 17:23:18 UTC (rev 4448) @@ -696,10 +696,12 @@ f = *(double*)(row1); } - result = (PyArrayObject*)PyArray_NewFromDescr - (&PyArray_Type, PyArray_DescrFromType(PyArray_DOUBLE), - PyArray_NDIM(vertices), PyArray_DIMS(vertices), - NULL, NULL, 0, NULL); + // I would have preferred to use PyArray_FromDims here, but on + // 64-bit platforms, PyArray_DIMS() does not return the same thing + // that PyArray_FromDims wants, requiring a copy, which I would + // like to avoid in this critical section. + result = (PyArrayObject*)PyArray_SimpleNew + (PyArray_NDIM(vertices), PyArray_DIMS(vertices), PyArray_DOUBLE); if (PyArray_NDIM(vertices) == 2) { size_t n = PyArray_DIM(vertices, 0); char* vertex_in = PyArray_BYTES(vertices); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-11-27 20:03:50
|
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. |
From: <md...@us...> - 2007-11-28 18:26:45
|
Revision: 4488 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4488&view=rev Author: mdboom Date: 2007-11-28 10:26:40 -0800 (Wed, 28 Nov 2007) Log Message: ----------- Increase performance of draw_markers in Agg backend Modified Paths: -------------- branches/transforms/src/_backend_agg.cpp branches/transforms/src/agg_py_path_iterator.h Modified: branches/transforms/src/_backend_agg.cpp =================================================================== --- branches/transforms/src/_backend_agg.cpp 2007-11-28 18:18:11 UTC (rev 4487) +++ branches/transforms/src/_backend_agg.cpp 2007-11-28 18:26:40 UTC (rev 4488) @@ -549,8 +549,8 @@ agg::serialized_scanlines_adaptor_aa8 sa; agg::serialized_scanlines_adaptor_aa8::embedded_scanline sl; - while (path_quantized.vertex(&x, &y) != agg::path_cmd_stop) { - if (has_clippath) { + if (has_clippath) { + while (path_quantized.vertex(&x, &y) != agg::path_cmd_stop) { pixfmt_amask_type pfa(*pixFmt, *alphaMask); amask_ren_type r(pfa); amask_aa_renderer_type ren(r); @@ -563,7 +563,9 @@ ren.color(gc.color); sa.init(strokeCache, strokeSize, x, y); agg::render_scanlines(sa, sl, ren); - } else { + } + } else { + while (path_quantized.vertex(&x, &y) != agg::path_cmd_stop) { if (face.first) { rendererAA->color(face.second); sa.init(fillCache, fillSize, x, y); @@ -1139,6 +1141,7 @@ m_iterator(0), m_m(m), m_n(n), m_coordinates(coordinates) { } + private: inline unsigned vertex(unsigned idx, double* x, double* y) { size_t m = (idx & 0x2) ? (m_m + 1) : m_m; size_t n = (idx+1 & 0x2) ? (m_n + 1) : m_n; @@ -1148,8 +1151,9 @@ return (idx) ? agg::path_cmd_line_to : agg::path_cmd_move_to; } + public: inline unsigned vertex(double* x, double* y) { - if (m_iterator >= total_vertices()) + if (m_iterator >= total_vertices()) return agg::path_cmd_stop; return vertex(m_iterator++, x, y); } @@ -1496,7 +1500,7 @@ int ymin = height; int xmax = 0; int ymax = 0; - + // Looks at the alpha channel to find the minimum extents of the image unsigned char* pixel = pixBuffer + 3; for (int y = 0; y < (int)height; ++y) { @@ -1520,11 +1524,11 @@ ymin = std::max(0, ymin - 1); xmax = std::min(xmax, (int)width); ymax = std::min(ymax, (int)height); - + newwidth = xmax - xmin; newheight = ymax - ymin; int newsize = newwidth * newheight * 4; - + unsigned char* buf = new unsigned char[newsize]; unsigned int* dst = (unsigned int*)buf; unsigned int* src = (unsigned int*)pixBuffer; @@ -1540,7 +1544,7 @@ bounds[1] = Py::Int(ymin); bounds[2] = Py::Int(newwidth); bounds[3] = Py::Int(newheight); - + Py::Tuple result(2); result[0] = data; result[1] = bounds; Modified: branches/transforms/src/agg_py_path_iterator.h =================================================================== --- branches/transforms/src/agg_py_path_iterator.h 2007-11-28 18:18:11 UTC (rev 4487) +++ branches/transforms/src/agg_py_path_iterator.h 2007-11-28 18:26:40 UTC (rev 4488) @@ -17,7 +17,7 @@ m_vertices(NULL), m_codes(NULL), m_iterator(0) { Py::Object vertices_obj = path_obj.getAttr("vertices"); Py::Object codes_obj = path_obj.getAttr("codes"); - + m_vertices = (PyArrayObject*)PyArray_FromObject (vertices_obj.ptr(), PyArray_DOUBLE, 2, 2); if (!m_vertices || PyArray_NDIM(m_vertices) != 2 || PyArray_DIM(m_vertices, 1) != 2) @@ -26,7 +26,7 @@ if (codes_obj.ptr() != Py_None) { m_codes = (PyArrayObject*)PyArray_FromObject (codes_obj.ptr(), PyArray_UINT8, 1, 1); - if (!m_codes) + if (!m_codes) throw Py::ValueError("Invalid codes array."); } @@ -40,11 +40,11 @@ static const char code_map[]; + private: inline unsigned vertex(unsigned idx, double* x, double* y) { - if (idx > m_total_vertices) - throw Py::RuntimeError("Requested vertex past end"); - *x = *(double*)PyArray_GETPTR2(m_vertices, idx, 0); - *y = *(double*)PyArray_GETPTR2(m_vertices, idx, 1); + char* pair = (char*)PyArray_GETPTR2(m_vertices, idx, 0); + *x = *(double*)pair; + *y = *(double*)(pair + PyArray_STRIDE(m_vertices, 1)); if (m_codes) { return code_map[(int)*(char *)PyArray_GETPTR1(m_codes, idx)]; } else { @@ -52,6 +52,7 @@ } } + public: inline unsigned vertex(double* x, double* y) { if (m_iterator >= m_total_vertices) return agg::path_cmd_stop; return vertex(m_iterator++, x, y); @@ -71,10 +72,10 @@ }; // Maps path codes on the Python side to agg path commands -const char PathIterator::code_map[] = - {0, - agg::path_cmd_move_to, - agg::path_cmd_line_to, +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}; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-11-29 15:40:44
|
Revision: 4501 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4501&view=rev Author: mdboom Date: 2007-11-29 07:40:42 -0800 (Thu, 29 Nov 2007) Log Message: ----------- Ran "astyle --style=ansi" to convert to ANSI style. Modified Paths: -------------- branches/transforms/src/_path.cpp branches/transforms/src/agg_py_path_iterator.h branches/transforms/src/agg_py_transforms.h Modified: branches/transforms/src/_path.cpp =================================================================== --- branches/transforms/src/_path.cpp 2007-11-29 13:50:25 UTC (rev 4500) +++ branches/transforms/src/_path.cpp 2007-11-29 15:40:42 UTC (rev 4501) @@ -11,61 +11,61 @@ // MGDTODO: Un-CXX-ify this module -struct XY { - double x; - double y; +struct XY +{ + double x; + double y; - XY(double x_, double y_) : x(x_), y(y_) {} + XY(double x_, double y_) : x(x_), y(y_) {} }; // the extension module class _path_module : public Py::ExtensionModule<_path_module> { public: - _path_module() - : Py::ExtensionModule<_path_module>( "_path" ) - { - add_varargs_method("point_in_path", &_path_module::point_in_path, - "point_in_path(x, y, path, trans)"); - add_varargs_method("point_on_path", &_path_module::point_on_path, - "point_on_path(x, y, r, path, trans)"); - add_varargs_method("get_path_extents", &_path_module::get_path_extents, - "get_path_extents(path, trans)"); - add_varargs_method("update_path_extents", &_path_module::update_path_extents, - "update_path_extents(path, trans, bbox, minpos)"); - add_varargs_method("get_path_collection_extents", &_path_module::get_path_collection_extents, - "get_path_collection_extents(trans, paths, transforms, offsets, offsetTrans)"); - add_varargs_method("point_in_path_collection", &_path_module::point_in_path_collection, - "point_in_path_collection(x, y, r, trans, paths, transforms, offsets, offsetTrans, filled)"); - add_varargs_method("path_in_path", &_path_module::path_in_path, - "path_in_path(a, atrans, b, btrans)"); - add_varargs_method("clip_path_to_rect", &_path_module::clip_path_to_rect, - "clip_path_to_rect(path, bbox, inside)"); - add_varargs_method("affine_transform", &_path_module::affine_transform, - "affine_transform(vertices, transform)"); - add_varargs_method("count_bboxes_overlapping_bbox", &_path_module::count_bboxes_overlapping_bbox, - "count_bboxes_overlapping_bbox(bbox, bboxes)"); - add_varargs_method("path_intersects_path", &_path_module::path_intersects_path, - "path_intersects_path(p1, p2)"); + _path_module() + : Py::ExtensionModule<_path_module>( "_path" ) + { + add_varargs_method("point_in_path", &_path_module::point_in_path, + "point_in_path(x, y, path, trans)"); + add_varargs_method("point_on_path", &_path_module::point_on_path, + "point_on_path(x, y, r, path, trans)"); + add_varargs_method("get_path_extents", &_path_module::get_path_extents, + "get_path_extents(path, trans)"); + add_varargs_method("update_path_extents", &_path_module::update_path_extents, + "update_path_extents(path, trans, bbox, minpos)"); + add_varargs_method("get_path_collection_extents", &_path_module::get_path_collection_extents, + "get_path_collection_extents(trans, paths, transforms, offsets, offsetTrans)"); + add_varargs_method("point_in_path_collection", &_path_module::point_in_path_collection, + "point_in_path_collection(x, y, r, trans, paths, transforms, offsets, offsetTrans, filled)"); + add_varargs_method("path_in_path", &_path_module::path_in_path, + "path_in_path(a, atrans, b, btrans)"); + add_varargs_method("clip_path_to_rect", &_path_module::clip_path_to_rect, + "clip_path_to_rect(path, bbox, inside)"); + add_varargs_method("affine_transform", &_path_module::affine_transform, + "affine_transform(vertices, transform)"); + add_varargs_method("count_bboxes_overlapping_bbox", &_path_module::count_bboxes_overlapping_bbox, + "count_bboxes_overlapping_bbox(bbox, bboxes)"); + add_varargs_method("path_intersects_path", &_path_module::path_intersects_path, + "path_intersects_path(p1, p2)"); - initialize("Helper functions for paths"); - } + initialize("Helper functions for paths"); + } - virtual ~_path_module() {} + virtual ~_path_module() {} private: - - Py::Object point_in_path(const Py::Tuple& args); - Py::Object point_on_path(const Py::Tuple& args); - Py::Object get_path_extents(const Py::Tuple& args); - Py::Object update_path_extents(const Py::Tuple& args); - Py::Object get_path_collection_extents(const Py::Tuple& args); - Py::Object point_in_path_collection(const Py::Tuple& args); - Py::Object path_in_path(const Py::Tuple& args); - Py::Object clip_path_to_rect(const Py::Tuple& args); - Py::Object affine_transform(const Py::Tuple& args); - Py::Object count_bboxes_overlapping_bbox(const Py::Tuple& args); - Py::Object path_intersects_path(const Py::Tuple& args); + Py::Object point_in_path(const Py::Tuple& args); + Py::Object point_on_path(const Py::Tuple& args); + Py::Object get_path_extents(const Py::Tuple& args); + Py::Object update_path_extents(const Py::Tuple& args); + Py::Object get_path_collection_extents(const Py::Tuple& args); + Py::Object point_in_path_collection(const Py::Tuple& args); + Py::Object path_in_path(const Py::Tuple& args); + Py::Object clip_path_to_rect(const Py::Tuple& args); + Py::Object affine_transform(const Py::Tuple& args); + Py::Object count_bboxes_overlapping_bbox(const Py::Tuple& args); + Py::Object path_intersects_path(const Py::Tuple& args); }; // @@ -106,466 +106,528 @@ // Input 2D polygon _pgon_ with _numverts_ number of vertices and test point // _point_, returns 1 if inside, 0 if outside. template<class T> -bool point_in_path_impl(double tx, double ty, T& path) { - int yflag0, yflag1, inside_flag; - double vtx0, vty0, vtx1, vty1, sx, sy; - double x, y; +bool point_in_path_impl(double tx, double ty, T& path) +{ + int yflag0, yflag1, inside_flag; + double vtx0, vty0, vtx1, vty1, sx, sy; + double x, y; - path.rewind(0); + path.rewind(0); - inside_flag = 0; + inside_flag = 0; - unsigned code = 0; - do { - if (code != agg::path_cmd_move_to) - code = path.vertex(&x, &y); + unsigned code = 0; + do + { + if (code != agg::path_cmd_move_to) + code = path.vertex(&x, &y); - sx = vtx0 = x; - sy = vty0 = y; + sx = vtx0 = x; + sy = vty0 = y; - // get test bit for above/below X axis - yflag0 = (vty0 >= ty); + // get test bit for above/below X axis + yflag0 = (vty0 >= ty); - vtx1 = x; - vty1 = x; + vtx1 = x; + vty1 = x; - inside_flag = 0; - do { - code = path.vertex(&x, &y); + inside_flag = 0; + do + { + code = path.vertex(&x, &y); - // The following cases denote the beginning on a new subpath - if (code == agg::path_cmd_stop || (code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) { - x = sx; y = sy; - } else if (code == agg::path_cmd_move_to) - break; + // The following cases denote the beginning on a new subpath + if (code == agg::path_cmd_stop || + (code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) + { + x = sx; + y = sy; + } + else if (code == agg::path_cmd_move_to) + break; - yflag1 = (vty1 >= ty); - // Check if endpoints straddle (are on opposite sides) of X axis - // (i.e. the Y's differ); if so, +X ray could intersect this edge. - // The old test also checked whether the endpoints are both to the - // right or to the left of the test point. However, given the faster - // intersection point computation used below, this test was found to - // be a break-even proposition for most polygons and a loser for - // triangles (where 50% or more of the edges which survive this test - // will cross quadrants and so have to have the X intersection computed - // anyway). I credit Joseph Samosky with inspiring me to try dropping - // the "both left or both right" part of my code. - if (yflag0 != yflag1) { - // Check intersection of pgon segment with +X ray. - // Note if >= point's X; if so, the ray hits it. - // The division operation is avoided for the ">=" test by checking - // the sign of the first vertex wrto the test point; idea inspired - // by Joseph Samosky's and Mark Haigh-Hutchinson's different - // polygon inclusion tests. - if ( ((vty1-ty) * (vtx0-vtx1) >= - (vtx1-tx) * (vty0-vty1)) == yflag1 ) { - inside_flag ^= 1; - } - } + yflag1 = (vty1 >= ty); + // Check if endpoints straddle (are on opposite sides) of X axis + // (i.e. the Y's differ); if so, +X ray could intersect this edge. + // The old test also checked whether the endpoints are both to the + // right or to the left of the test point. However, given the faster + // intersection point computation used below, this test was found to + // be a break-even proposition for most polygons and a loser for + // triangles (where 50% or more of the edges which survive this test + // will cross quadrants and so have to have the X intersection computed + // anyway). I credit Joseph Samosky with inspiring me to try dropping + // the "both left or both right" part of my code. + if (yflag0 != yflag1) + { + // Check intersection of pgon segment with +X ray. + // Note if >= point's X; if so, the ray hits it. + // The division operation is avoided for the ">=" test by checking + // the sign of the first vertex wrto the test point; idea inspired + // by Joseph Samosky's and Mark Haigh-Hutchinson's different + // polygon inclusion tests. + if ( ((vty1-ty) * (vtx0-vtx1) >= + (vtx1-tx) * (vty0-vty1)) == yflag1 ) + { + inside_flag ^= 1; + } + } - // Move to the next pair of vertices, retaining info as possible. - yflag0 = yflag1; - vtx0 = vtx1; - vty0 = vty1; + // Move to the next pair of vertices, retaining info as possible. + yflag0 = yflag1; + vtx0 = vtx1; + vty0 = vty1; - vtx1 = x; - vty1 = y; - } while (code != agg::path_cmd_stop && - (code & agg::path_cmd_end_poly) != agg::path_cmd_end_poly); + vtx1 = x; + vty1 = y; + } + while (code != agg::path_cmd_stop && + (code & agg::path_cmd_end_poly) != agg::path_cmd_end_poly); - yflag1 = (vty1 >= ty); - if (yflag0 != yflag1) { - if ( ((vty1-ty) * (vtx0-vtx1) >= - (vtx1-tx) * (vty0-vty1)) == yflag1 ) { - inside_flag ^= 1; - } + yflag1 = (vty1 >= ty); + if (yflag0 != yflag1) + { + if ( ((vty1-ty) * (vtx0-vtx1) >= + (vtx1-tx) * (vty0-vty1)) == yflag1 ) + { + inside_flag ^= 1; + } + } + + if (inside_flag != 0) + return true; } + while (code != agg::path_cmd_stop); - if (inside_flag != 0) - return true; - } while (code != agg::path_cmd_stop); - - return (inside_flag != 0); + return (inside_flag != 0); } -inline bool point_in_path(double x, double y, PathIterator& path, const agg::trans_affine& trans) { - typedef agg::conv_transform<PathIterator> transformed_path_t; - typedef agg::conv_curve<transformed_path_t> curve_t; +inline bool point_in_path(double x, double y, PathIterator& path, const agg::trans_affine& trans) +{ + typedef agg::conv_transform<PathIterator> transformed_path_t; + typedef agg::conv_curve<transformed_path_t> curve_t; - if (path.total_vertices() < 3) - return false; + if (path.total_vertices() < 3) + return false; - transformed_path_t trans_path(path, trans); - curve_t curved_path(trans_path); - return point_in_path_impl(x, y, curved_path); + transformed_path_t trans_path(path, trans); + curve_t curved_path(trans_path); + return point_in_path_impl(x, y, curved_path); } -inline bool point_on_path(double x, double y, double r, PathIterator& path, const agg::trans_affine& trans) { - 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; +inline bool point_on_path(double x, double y, double r, PathIterator& path, const agg::trans_affine& trans) +{ + 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; - transformed_path_t trans_path(path, trans); - curve_t curved_path(trans_path); - stroke_t stroked_path(curved_path); - stroked_path.width(r * 2.0); - return point_in_path_impl(x, y, stroked_path); + transformed_path_t trans_path(path, trans); + curve_t curved_path(trans_path); + stroke_t stroked_path(curved_path); + stroked_path.width(r * 2.0); + return point_in_path_impl(x, y, stroked_path); } -Py::Object _path_module::point_in_path(const Py::Tuple& args) { - args.verify_length(4); +Py::Object _path_module::point_in_path(const Py::Tuple& args) +{ + args.verify_length(4); - double x = Py::Float(args[0]); - double y = Py::Float(args[1]); - PathIterator path(args[2]); - agg::trans_affine trans = py_to_agg_transformation_matrix(args[3]); + double x = Py::Float(args[0]); + double y = Py::Float(args[1]); + PathIterator path(args[2]); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[3]); - if (::point_in_path(x, y, path, trans)) - return Py::Int(1); - return Py::Int(0); + if (::point_in_path(x, y, path, trans)) + return Py::Int(1); + return Py::Int(0); } -Py::Object _path_module::point_on_path(const Py::Tuple& args) { - args.verify_length(5); +Py::Object _path_module::point_on_path(const Py::Tuple& args) +{ + args.verify_length(5); - double x = Py::Float(args[0]); - double y = Py::Float(args[1]); - double r = Py::Float(args[2]); - PathIterator path(args[3]); - agg::trans_affine trans = py_to_agg_transformation_matrix(args[4]); + double x = Py::Float(args[0]); + double y = Py::Float(args[1]); + double r = Py::Float(args[2]); + PathIterator path(args[3]); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[4]); - if (::point_on_path(x, y, r, path, trans)) - return Py::Int(1); - return Py::Int(0); + if (::point_on_path(x, y, r, path, trans)) + return Py::Int(1); + return Py::Int(0); } void get_path_extents(PathIterator& path, const agg::trans_affine& trans, - double* x0, double* y0, double* x1, double* y1, - double* xm, double* ym) { - typedef agg::conv_transform<PathIterator> transformed_path_t; - typedef agg::conv_curve<transformed_path_t> curve_t; - double x, y; - unsigned code; + double* x0, double* y0, double* x1, double* y1, + double* xm, double* ym) +{ + typedef agg::conv_transform<PathIterator> transformed_path_t; + typedef agg::conv_curve<transformed_path_t> curve_t; + double x, y; + unsigned code; - transformed_path_t tpath(path, trans); - curve_t curved_path(tpath); + transformed_path_t tpath(path, trans); + curve_t curved_path(tpath); - curved_path.rewind(0); + curved_path.rewind(0); - while ((code = curved_path.vertex(&x, &y)) != agg::path_cmd_stop) { - if ((code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) - continue; - if (x < *x0) { - *x0 = x; - if (x > 0.0) - *xm = x; + while ((code = curved_path.vertex(&x, &y)) != agg::path_cmd_stop) + { + if ((code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) + continue; + if (x < *x0) + { + *x0 = x; + if (x > 0.0) + *xm = x; + } + if (y < *y0) + { + *y0 = y; + if (y > 0.0) + *ym = y; + } + if (x > *x1) *x1 = x; + if (y > *y1) *y1 = y; } - if (y < *y0) { - *y0 = y; - if (y > 0.0) - *ym = y; - } - if (x > *x1) *x1 = x; - if (y > *y1) *y1 = y; - } } -Py::Object _path_module::get_path_extents(const Py::Tuple& args) { - args.verify_length(2); +Py::Object _path_module::get_path_extents(const Py::Tuple& args) +{ + args.verify_length(2); - PathIterator path(args[0]); - agg::trans_affine trans = py_to_agg_transformation_matrix(args[1], false); + PathIterator path(args[0]); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[1], false); - npy_intp extent_dims[] = { 2, 2, 0 }; - double* extents_data = new double[4]; - double xm, ym; - PyArrayObject* extents = NULL; - try { - extents_data[0] = std::numeric_limits<double>::infinity(); - extents_data[1] = std::numeric_limits<double>::infinity(); - extents_data[2] = -std::numeric_limits<double>::infinity(); - extents_data[3] = -std::numeric_limits<double>::infinity(); + npy_intp extent_dims[] = { 2, 2, 0 }; + double* extents_data = new double[4]; + double xm, ym; + PyArrayObject* extents = NULL; + try + { + extents_data[0] = std::numeric_limits<double>::infinity(); + extents_data[1] = std::numeric_limits<double>::infinity(); + extents_data[2] = -std::numeric_limits<double>::infinity(); + extents_data[3] = -std::numeric_limits<double>::infinity(); - ::get_path_extents(path, trans, - &extents_data[0], &extents_data[1], &extents_data[2], &extents_data[3], - &xm, &ym); + ::get_path_extents(path, trans, + &extents_data[0], &extents_data[1], &extents_data[2], &extents_data[3], + &xm, &ym); - extents = (PyArrayObject*)PyArray_SimpleNewFromData - (2, extent_dims, PyArray_DOUBLE, extents_data); - } catch (...) { - if (extents) - Py_XDECREF(extents); - else - delete[] extents_data; - throw; - } + extents = (PyArrayObject*)PyArray_SimpleNewFromData + (2, extent_dims, PyArray_DOUBLE, extents_data); + } + catch (...) + { + if (extents) + Py_XDECREF(extents); + else + delete[] extents_data; + throw; + } - return Py::Object((PyObject*)extents); + return Py::Object((PyObject*)extents); } -Py::Object _path_module::update_path_extents(const Py::Tuple& args) { - args.verify_length(5); +Py::Object _path_module::update_path_extents(const Py::Tuple& args) +{ + args.verify_length(5); - double x0, y0, x1, y1; - PathIterator path(args[0]); - agg::trans_affine trans = py_to_agg_transformation_matrix(args[1], false); - if (!py_convert_bbox(args[2].ptr(), x0, y0, x1, y1)) { - throw Py::ValueError("Must pass Bbox object as arg 3 of update_path_extents"); - } - Py::Object minpos_obj = args[3]; - bool ignore = bool(Py::Int(args[4])); + double x0, y0, x1, y1; + PathIterator path(args[0]); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[1], false); + if (!py_convert_bbox(args[2].ptr(), x0, y0, x1, y1)) + { + throw Py::ValueError("Must pass Bbox object as arg 3 of update_path_extents"); + } + Py::Object minpos_obj = args[3]; + bool ignore = bool(Py::Int(args[4])); - double xm, ym; - PyArrayObject* input_minpos = NULL; - try { - input_minpos = (PyArrayObject*)PyArray_FromObject(minpos_obj.ptr(), PyArray_DOUBLE, 1, 1); - if (!input_minpos || PyArray_DIM(input_minpos, 0) != 2) { - throw Py::TypeError("Argument 4 to update_path_extents must be a length-2 numpy array."); + double xm, ym; + PyArrayObject* input_minpos = NULL; + try + { + input_minpos = (PyArrayObject*)PyArray_FromObject(minpos_obj.ptr(), PyArray_DOUBLE, 1, 1); + if (!input_minpos || PyArray_DIM(input_minpos, 0) != 2) + { + throw Py::TypeError("Argument 4 to update_path_extents must be a length-2 numpy array."); + } + xm = *(double*)PyArray_GETPTR1(input_minpos, 0); + ym = *(double*)PyArray_GETPTR1(input_minpos, 1); } - xm = *(double*)PyArray_GETPTR1(input_minpos, 0); - ym = *(double*)PyArray_GETPTR1(input_minpos, 1); - } catch (...) { + catch (...) + { + Py_XDECREF(input_minpos); + throw; + } Py_XDECREF(input_minpos); - throw; - } - Py_XDECREF(input_minpos); - npy_intp extent_dims[] = { 2, 2, 0 }; - double* extents_data = new double[4]; - npy_intp minpos_dims[] = { 2, 0 }; - double* minpos_data = new double[2]; - PyArrayObject* extents = NULL; - PyArrayObject* minpos = NULL; - bool changed = false; + npy_intp extent_dims[] = { 2, 2, 0 }; + double* extents_data = new double[4]; + npy_intp minpos_dims[] = { 2, 0 }; + double* minpos_data = new double[2]; + PyArrayObject* extents = NULL; + PyArrayObject* minpos = NULL; + bool changed = false; - try { - if (ignore) { - extents_data[0] = std::numeric_limits<double>::infinity(); - extents_data[1] = std::numeric_limits<double>::infinity(); - extents_data[2] = -std::numeric_limits<double>::infinity(); - extents_data[3] = -std::numeric_limits<double>::infinity(); - minpos_data[0] = std::numeric_limits<double>::infinity(); - minpos_data[1] = std::numeric_limits<double>::infinity(); - } else { - extents_data[0] = std::min(x0, x1); - extents_data[1] = std::min(y0, y1); - extents_data[2] = std::max(x0, x1); - extents_data[3] = std::max(y0, y1); - minpos_data[0] = xm; - minpos_data[1] = ym; - } + try + { + if (ignore) + { + extents_data[0] = std::numeric_limits<double>::infinity(); + extents_data[1] = std::numeric_limits<double>::infinity(); + extents_data[2] = -std::numeric_limits<double>::infinity(); + extents_data[3] = -std::numeric_limits<double>::infinity(); + minpos_data[0] = std::numeric_limits<double>::infinity(); + minpos_data[1] = std::numeric_limits<double>::infinity(); + } + else + { + extents_data[0] = std::min(x0, x1); + extents_data[1] = std::min(y0, y1); + extents_data[2] = std::max(x0, x1); + extents_data[3] = std::max(y0, y1); + minpos_data[0] = xm; + minpos_data[1] = ym; + } - ::get_path_extents(path, trans, - &extents_data[0], &extents_data[1], &extents_data[2], &extents_data[3], - &minpos_data[0], &minpos_data[1]); + ::get_path_extents(path, trans, + &extents_data[0], &extents_data[1], &extents_data[2], &extents_data[3], + &minpos_data[0], &minpos_data[1]); - changed = (extents_data[0] != x0 || - extents_data[1] != y0 || - extents_data[2] != x1 || - extents_data[3] != y1 || - minpos_data[0] != xm || - minpos_data[1] != ym); + changed = (extents_data[0] != x0 || + extents_data[1] != y0 || + extents_data[2] != x1 || + extents_data[3] != y1 || + minpos_data[0] != xm || + minpos_data[1] != ym); - extents = (PyArrayObject*)PyArray_SimpleNewFromData - (2, extent_dims, PyArray_DOUBLE, extents_data); - minpos = (PyArrayObject*)PyArray_SimpleNewFromData - (1, minpos_dims, PyArray_DOUBLE, minpos_data); - } catch(...) { - if (extents) - Py_XDECREF(extents); - else - delete[] extents_data; - if (minpos) - Py_XDECREF(minpos); - else - delete[] minpos_data; - throw; - } + extents = (PyArrayObject*)PyArray_SimpleNewFromData + (2, extent_dims, PyArray_DOUBLE, extents_data); + minpos = (PyArrayObject*)PyArray_SimpleNewFromData + (1, minpos_dims, PyArray_DOUBLE, minpos_data); + } + catch (...) + { + if (extents) + Py_XDECREF(extents); + else + delete[] extents_data; + if (minpos) + Py_XDECREF(minpos); + else + delete[] minpos_data; + throw; + } - Py::Tuple result(3); - result[0] = Py::Object((PyObject*) extents); - result[1] = Py::Object((PyObject*) minpos); - result[2] = Py::Int(changed ? 1 : 0); + Py::Tuple result(3); + result[0] = Py::Object((PyObject*) extents); + result[1] = Py::Object((PyObject*) minpos); + result[2] = Py::Int(changed ? 1 : 0); - return result; + return result; } -Py::Object _path_module::get_path_collection_extents(const Py::Tuple& args) { - args.verify_length(5); +Py::Object _path_module::get_path_collection_extents(const Py::Tuple& args) +{ + args.verify_length(5); - //segments, trans, clipbox, colors, linewidths, antialiaseds - agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[0]); - Py::SeqBase<Py::Object> paths = args[1]; - Py::SeqBase<Py::Object> transforms_obj = args[2]; - Py::Object offsets_obj = args[3]; - agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[4], false); + //segments, trans, clipbox, colors, linewidths, antialiaseds + agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[0]); + Py::SeqBase<Py::Object> paths = args[1]; + Py::SeqBase<Py::Object> transforms_obj = args[2]; + Py::Object offsets_obj = args[3]; + agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[4], false); - PyArrayObject* offsets = NULL; - double x0, y0, x1, y1, xm, ym; + PyArrayObject* offsets = NULL; + double x0, y0, x1, y1, xm, ym; - try { - offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj.ptr(), PyArray_DOUBLE, 0, 2); - if (!offsets || - (PyArray_NDIM(offsets) == 2 && PyArray_DIM(offsets, 1) != 2) || - (PyArray_NDIM(offsets) == 1 && PyArray_DIM(offsets, 0) != 0)) { - throw Py::ValueError("Offsets array must be Nx2"); - } + try + { + offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj.ptr(), PyArray_DOUBLE, 0, 2); + if (!offsets || + (PyArray_NDIM(offsets) == 2 && PyArray_DIM(offsets, 1) != 2) || + (PyArray_NDIM(offsets) == 1 && PyArray_DIM(offsets, 0) != 0)) + { + throw Py::ValueError("Offsets array must be Nx2"); + } - size_t Npaths = paths.length(); - size_t Noffsets = offsets->dimensions[0]; - size_t N = std::max(Npaths, Noffsets); - size_t Ntransforms = std::min(transforms_obj.length(), N); - size_t i; + size_t Npaths = paths.length(); + size_t Noffsets = offsets->dimensions[0]; + size_t N = std::max(Npaths, Noffsets); + size_t Ntransforms = std::min(transforms_obj.length(), N); + size_t i; - // Convert all of the transforms up front - typedef std::vector<agg::trans_affine> transforms_t; - transforms_t transforms; - transforms.reserve(Ntransforms); - for (i = 0; i < Ntransforms; ++i) { - agg::trans_affine trans = py_to_agg_transformation_matrix - (transforms_obj[i], false); - trans *= master_transform; - transforms.push_back(trans); - } + // Convert all of the transforms up front + typedef std::vector<agg::trans_affine> transforms_t; + transforms_t transforms; + transforms.reserve(Ntransforms); + for (i = 0; i < Ntransforms; ++i) + { + agg::trans_affine trans = py_to_agg_transformation_matrix + (transforms_obj[i], false); + trans *= master_transform; + transforms.push_back(trans); + } - // The offset each of those and collect the mins/maxs - x0 = std::numeric_limits<double>::infinity(); - y0 = std::numeric_limits<double>::infinity(); - x1 = -std::numeric_limits<double>::infinity(); - y1 = -std::numeric_limits<double>::infinity(); - agg::trans_affine trans; + // The offset each of those and collect the mins/maxs + x0 = std::numeric_limits<double>::infinity(); + y0 = std::numeric_limits<double>::infinity(); + x1 = -std::numeric_limits<double>::infinity(); + y1 = -std::numeric_limits<double>::infinity(); + agg::trans_affine trans; - for (i = 0; i < N; ++i) { - PathIterator path(paths[i % Npaths]); - if (Ntransforms) { - trans = transforms[i % Ntransforms]; - } else { - trans = master_transform; - } + for (i = 0; i < N; ++i) + { + PathIterator path(paths[i % Npaths]); + if (Ntransforms) + { + trans = transforms[i % Ntransforms]; + } + else + { + trans = master_transform; + } - if (Noffsets) { - double xo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 0); - double yo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 1); - offset_trans.transform(&xo, &yo); - trans *= agg::trans_affine_translation(xo, yo); - } + if (Noffsets) + { + double xo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 0); + double yo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 1); + offset_trans.transform(&xo, &yo); + trans *= agg::trans_affine_translation(xo, yo); + } - ::get_path_extents(path, trans, &x0, &y0, &x1, &y1, &xm, &ym); + ::get_path_extents(path, trans, &x0, &y0, &x1, &y1, &xm, &ym); + } } - } catch (...) { + catch (...) + { + Py_XDECREF(offsets); + throw; + } + Py_XDECREF(offsets); - throw; - } - Py_XDECREF(offsets); - - Py::Tuple result(4); - result[0] = Py::Float(x0); - result[1] = Py::Float(y0); - result[2] = Py::Float(x1); - result[3] = Py::Float(y1); - return result; + Py::Tuple result(4); + result[0] = Py::Float(x0); + result[1] = Py::Float(y0); + result[2] = Py::Float(x1); + result[3] = Py::Float(y1); + return result; } -Py::Object _path_module::point_in_path_collection(const Py::Tuple& args) { - args.verify_length(9); +Py::Object _path_module::point_in_path_collection(const Py::Tuple& args) +{ + args.verify_length(9); - //segments, trans, clipbox, colors, linewidths, antialiaseds - double x = Py::Float(args[0]); - double y = Py::Float(args[1]); - double radius = Py::Float(args[2]); - agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[3]); - Py::SeqBase<Py::Object> paths = args[4]; - Py::SeqBase<Py::Object> transforms_obj = args[5]; - Py::SeqBase<Py::Object> offsets_obj = args[6]; - agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[7]); - bool filled = Py::Int(args[8]); + //segments, trans, clipbox, colors, linewidths, antialiaseds + double x = Py::Float(args[0]); + double y = Py::Float(args[1]); + double radius = Py::Float(args[2]); + agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[3]); + Py::SeqBase<Py::Object> paths = args[4]; + Py::SeqBase<Py::Object> transforms_obj = args[5]; + Py::SeqBase<Py::Object> offsets_obj = args[6]; + agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[7]); + bool filled = Py::Int(args[8]); - PyArrayObject* offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj.ptr(), PyArray_DOUBLE, 0, 2); - if (!offsets || - (PyArray_NDIM(offsets) == 2 && PyArray_DIM(offsets, 1) != 2) || - (PyArray_NDIM(offsets) == 1 && PyArray_DIM(offsets, 0) != 0)) { - throw Py::ValueError("Offsets array must be Nx2"); - } + PyArrayObject* offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj.ptr(), PyArray_DOUBLE, 0, 2); + if (!offsets || + (PyArray_NDIM(offsets) == 2 && PyArray_DIM(offsets, 1) != 2) || + (PyArray_NDIM(offsets) == 1 && PyArray_DIM(offsets, 0) != 0)) + { + throw Py::ValueError("Offsets array must be Nx2"); + } - size_t Npaths = paths.length(); - size_t Noffsets = offsets->dimensions[0]; - size_t N = std::max(Npaths, Noffsets); - size_t Ntransforms = std::min(transforms_obj.length(), N); - size_t i; + size_t Npaths = paths.length(); + size_t Noffsets = offsets->dimensions[0]; + size_t N = std::max(Npaths, Noffsets); + size_t Ntransforms = std::min(transforms_obj.length(), N); + size_t i; - // Convert all of the transforms up front - typedef std::vector<agg::trans_affine> transforms_t; - transforms_t transforms; - transforms.reserve(Ntransforms); - for (i = 0; i < Ntransforms; ++i) { - agg::trans_affine trans = py_to_agg_transformation_matrix - (transforms_obj[i], false); - trans *= master_transform; - transforms.push_back(trans); - } + // Convert all of the transforms up front + typedef std::vector<agg::trans_affine> transforms_t; + transforms_t transforms; + transforms.reserve(Ntransforms); + for (i = 0; i < Ntransforms; ++i) + { + agg::trans_affine trans = py_to_agg_transformation_matrix + (transforms_obj[i], false); + trans *= master_transform; + transforms.push_back(trans); + } - Py::List result; - agg::trans_affine trans; + Py::List result; + agg::trans_affine trans; - for (i = 0; i < N; ++i) { - PathIterator path(paths[i % Npaths]); + for (i = 0; i < N; ++i) + { + PathIterator path(paths[i % Npaths]); - if (Ntransforms) { - trans = transforms[i % Ntransforms]; - } else { - trans = master_transform; - } + if (Ntransforms) + { + trans = transforms[i % Ntransforms]; + } + else + { + trans = master_transform; + } - if (Noffsets) { - double xo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 0); - double yo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 1); - offset_trans.transform(&xo, &yo); - trans *= agg::trans_affine_translation(xo, yo); - } + if (Noffsets) + { + double xo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 0); + double yo = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 1); + offset_trans.transform(&xo, &yo); + trans *= agg::trans_affine_translation(xo, yo); + } - if (filled) { - if (::point_in_path(x, y, path, trans)) - result.append(Py::Int((int)i)); - } else { - if (::point_on_path(x, y, radius, path, trans)) - result.append(Py::Int((int)i)); + if (filled) + { + if (::point_in_path(x, y, path, trans)) + result.append(Py::Int((int)i)); + } + else + { + if (::point_on_path(x, y, radius, path, trans)) + result.append(Py::Int((int)i)); + } } - } - return result; + return result; } bool path_in_path(PathIterator& a, const agg::trans_affine& atrans, - PathIterator& b, const agg::trans_affine& btrans) { - typedef agg::conv_transform<PathIterator> transformed_path_t; - typedef agg::conv_curve<transformed_path_t> curve_t; + PathIterator& b, const agg::trans_affine& btrans) +{ + typedef agg::conv_transform<PathIterator> transformed_path_t; + typedef agg::conv_curve<transformed_path_t> curve_t; - if (a.total_vertices() < 3) - return false; + if (a.total_vertices() < 3) + return false; - transformed_path_t b_path_trans(b, btrans); - curve_t b_curved(b_path_trans); + transformed_path_t b_path_trans(b, btrans); + curve_t b_curved(b_path_trans); - double x, y; - b_curved.rewind(0); - while (b_curved.vertex(&x, &y) != agg::path_cmd_stop) { - if (!::point_in_path(x, y, a, atrans)) - return false; - } + double x, y; + b_curved.rewind(0); + while (b_curved.vertex(&x, &y) != agg::path_cmd_stop) + { + if (!::point_in_path(x, y, a, atrans)) + return false; + } - return true; + return true; } -Py::Object _path_module::path_in_path(const Py::Tuple& args) { - args.verify_length(4); +Py::Object _path_module::path_in_path(const Py::Tuple& args) +{ + args.verify_length(4); - PathIterator a(args[0]); - agg::trans_affine atrans = py_to_agg_transformation_matrix(args[1]); - PathIterator b(args[2]); - agg::trans_affine btrans = py_to_agg_transformation_matrix(args[3]); + PathIterator a(args[0]); + agg::trans_affine atrans = py_to_agg_transformation_matrix(args[1]); + PathIterator b(args[2]); + agg::trans_affine btrans = py_to_agg_transformation_matrix(args[3]); - return Py::Int(::path_in_path(a, atrans, b, btrans)); + return Py::Int(::path_in_path(a, atrans, b, btrans)); } /** The clip_path_to_rect code here is a clean-room implementation of the @@ -576,398 +638,465 @@ typedef std::vector<XY> Polygon; -namespace clip_to_rect_filters { - /* There are four different passes needed to create/remove vertices - (one for each side of the rectangle). The differences between those - passes are encapsulated in these functor classes. - */ - struct bisectx { +namespace clip_to_rect_filters +{ +/* There are four different passes needed to create/remove vertices + (one for each side of the rectangle). The differences between those + passes are encapsulated in these functor classes. +*/ +struct bisectx +{ double m_x; bisectx(double x) : m_x(x) {} - void bisect(double sx, double sy, double px, double py, double* bx, double* by) const { - *bx = m_x; - double dx = px - sx; - double dy = py - sy; - *by = sy + dy * ((m_x - sx) / dx); + void bisect(double sx, double sy, double px, double py, double* bx, double* by) const + { + *bx = m_x; + double dx = px - sx; + double dy = py - sy; + *by = sy + dy * ((m_x - sx) / dx); } - }; +}; - struct xlt : public bisectx { +struct xlt : public bisectx +{ xlt(double x) : bisectx(x) {} - bool is_inside(double x, double y) const { - return x <= m_x; + bool is_inside(double x, double y) const + { + return x <= m_x; } - }; +}; - struct xgt : public bisectx { +struct xgt : public bisectx +{ xgt(double x) : bisectx(x) {} - bool is_inside(double x, double y) const { - return x >= m_x; + bool is_inside(double x, double y) const + { + return x >= m_x; } - }; +}; - struct bisecty { +struct bisecty +{ double m_y; bisecty(double y) : m_y(y) {} - void bisect(double sx, double sy, double px, double py, double* bx, double* by) const { - *by = m_y; - double dx = px - sx; - double dy = py - sy; - *bx = sx + dx * ((m_y - sy) / dy); + void bisect(double sx, double sy, double px, double py, double* bx, double* by) const + { + *by = m_y; + double dx = px - sx; + double dy = py - sy; + *bx = sx + dx * ((m_y - sy) / dy); } - }; +}; - struct ylt : public bisecty { +struct ylt : public bisecty +{ ylt(double y) : bisecty(y) {} - bool is_inside(double x, double y) const { - return y <= m_y; + bool is_inside(double x, double y) const + { + return y <= m_y; } - }; +}; - struct ygt : public bisecty { +struct ygt : public bisecty +{ ygt(double y) : bisecty(y) {} - bool is_inside(double x, double y) const { - return y >= m_y; + bool is_inside(double x, double y) const + { + return y >= m_y; } - }; +}; } template<class Filter> -void clip_to_rect_one_step(const Polygon& polygon, Polygon& result, const Filter& filter) { - double sx, sy, px, py, bx, by; - bool sinside, pinside; - result.clear(); +void clip_to_rect_one_step(const Polygon& polygon, Polygon& result, const Filter& filter) +{ + double sx, sy, px, py, bx, by; + bool sinside, pinside; + result.clear(); - if (polygon.size() == 0) - return; + if (polygon.size() == 0) + return; - sx = polygon.back().x; - sy = polygon.back().y; - for (Polygon::const_iterator i = polygon.begin(); i != polygon.end(); ++i) { - px = i->x; - py = i->y; + sx = polygon.back().x; + sy = polygon.back().y; + for (Polygon::const_iterator i = polygon.begin(); i != polygon.end(); ++i) + { + px = i->x; + py = i->y; - sinside = filter.is_inside(sx, sy); - pinside = filter.is_inside(px, py); + sinside = filter.is_inside(sx, sy); + pinside = filter.is_inside(px, py); - if (sinside ^ pinside) { - filter.bisect(sx, sy, px, py, &bx, &by); - result.push_back(XY(bx, by)); - } + if (sinside ^ pinside) + { + filter.bisect(sx, sy, px, py, &bx, &by); + result.push_back(XY(bx, by)); + } - if (pinside) { - result.push_back(XY(px, py)); + if (pinside) + { + result.push_back(XY(px, py)); + } + + sx = px; + sy = py; } - - sx = px; sy = py; - } } void clip_to_rect(PathIterator& path, - double x0, double y0, double x1, double y1, - bool inside, std::vector<Polygon>& results) { - double xmin, ymin, xmax, ymax; - if (x0 < x1) { - xmin = x0; xmax = x1; - } else { - xmin = x1; xmax = x0; - } + double x0, double y0, double x1, double y1, + bool inside, std::vector<Polygon>& results) +{ + double xmin, ymin, xmax, ymax; + if (x0 < x1) + { + xmin = x0; + xmax = x1; + } + else + { + xmin = x1; + xmax = x0; + } - if (y0 < y1) { - ymin = y0; ymax = y1; - } else { - ymin = y1; ymax = y0; - } + if (y0 < y1) + { + ymin = y0; + ymax = y1; + } + else + { + ymin = y1; + ymax = y0; + } - if (!inside) { - std::swap(xmin, xmax); - std::swap(ymin, ymax); - } + if (!inside) + { + std::swap(xmin, xmax); + std::swap(ymin, ymax); + } - Polygon polygon1, polygon2; - double x, y; - unsigned code = 0; - path.rewind(0); + Polygon polygon1, polygon2; + double x, y; + unsigned code = 0; + path.rewind(0); - do { - // Grab the next subpath and store it in polygon1 - polygon1.clear(); - do { - if (code == agg::path_cmd_move_to) - polygon1.push_back(XY(x, y)); + do + { + // Grab the next subpath and store it in polygon1 + polygon1.clear(); + do + { + if (code == agg::path_cmd_move_to) + polygon1.push_back(XY(x, y)); - code = path.vertex(&x, &y); + code = path.vertex(&x, &y); - if (code == agg::path_cmd_stop) - break; + if (code == agg::path_cmd_stop) + break; - if (code != agg::path_cmd_move_to) - polygon1.push_back(XY(x, y)); - } while ((code & agg::path_cmd_end_poly) != agg::path_cmd_end_poly); + if (code != agg::path_cmd_move_to) + polygon1.push_back(XY(x, y)); + } + while ((code & agg::path_cmd_end_poly) != agg::path_cmd_end_poly); - // The result of each step is fed into the next (note the - // swapping of polygon1 and polygon2 at each step). - clip_to_rect_one_step(polygon1, polygon2, clip_to_rect_filters::xlt(xmax)); - clip_to_rect_one_step(polygon2, polygon1, clip_to_rect_filters::xgt(xmin)); - clip_to_rect_one_step(polygon1, polygon2, clip_to_rect_filters::ylt(ymax)); - clip_to_rect_one_step(polygon2, polygon1, clip_to_rect_filters::ygt(ymin)); + // The result of each step is fed into the next (note the + // swapping of polygon1 and polygon2 at each step). + clip_to_rect_one_step(polygon1, polygon2, clip_to_rect_filters::xlt(xmax)); + clip_to_rect_one_step(polygon2, polygon1, clip_to_rect_filters::xgt(xmin)); + clip_to_rect_one_step(polygon1, polygon2, clip_to_rect_filters::ylt(ymax)); + clip_to_rect_one_step(polygon2, polygon1, clip_to_rect_filters::ygt(ymin)); - // Empty polygons aren't very useful, so skip them - if (polygon1.size()) - results.push_back(polygon1); - } while (code != agg::path_cmd_stop); + // Empty polygons aren't very useful, so skip them + if (polygon1.size()) + results.push_back(polygon1); + } + while (code != agg::path_cmd_stop); } -Py::Object _path_module::clip_path_to_rect(const Py::Tuple &args) { - args.verify_length(3); +Py::Object _path_module::clip_path_to_rect(const Py::Tuple &args) +{ + args.verify_length(3); - PathIterator path(args[0]); - Py::Object bbox_obj = args[1]; - bool inside = Py::Int(args[2]); + PathIterator path(args[0]); + Py::Object bbox_obj = args[1]; + bool inside = Py::Int(args[2]); - double x0, y0, x1, y1; - if (!py_convert_bbox(bbox_obj.ptr(), x0, y0, x1, y1)) - throw Py::TypeError("Argument 2 to clip_to_rect must be a Bbox object."); + double x0, y0, x1, y1; + if (!py_convert_bbox(bbox_obj.ptr(), x0, y0, x1, y1)) + throw Py::TypeError("Argument 2 to clip_to_rect must be a Bbox object."); - std::vector<Polygon> results; + std::vector<Polygon> results; - ::clip_to_rect(path, x0, y0, x1, y1, inside, results); + ::clip_to_rect(path, x0, y0, x1, y1, inside, results); - int dims[2]; - dims[1] = 2; - PyObject* py_results = PyList_New(results.size()); - if (!py_results) - throw Py::RuntimeError("Error creating results list"); - try { - for (std::vector<Polygon>::const_iterator p = results.begin(); p != results.end(); ++p) { - size_t size = p->size(); - dims[0] = p->size(); - PyArrayObject* pyarray = (PyArrayObject*)PyArray_FromDims(2, dims, PyArray_DOUBLE); - for (size_t i = 0; i < size; ++i) { - ((double *)pyarray->data)[2*i] = (*p)[i].x; - ((double *)pyarray->data)[2*i+1] = (*p)[i].y; - } - if (PyList_SetItem(py_results, p - results.begin(), (PyObject *)pyarray) != -1) { - throw Py::RuntimeError("Error creating results list"); - } + int dims[2]; + dims[1] = 2; + PyObject* py_results = PyList_New(results.size()); + if (!py_results) + throw Py::RuntimeError("Error creating results list"); + try + { + for (std::vector<Polygon>::const_iterator p = results.begin(); p != results.end(); ++p) + { + size_t size = p->size(); + dims[0] = p->size(); + PyArrayObject* pyarray = (PyArrayObject*)PyArray_FromDims(2, dims, PyArray_DOUBLE); + for (size_t i = 0; i < size; ++i) + { + ((double *)pyarray->data)[2*i] = (*p)[i].x; + ((double *)pyarray->data)[2*i+1] = (*p)[i].y; + } + if (PyList_SetItem(py_results, p - results.begin(), (PyObject *)pyarray) != -1) + { + throw Py::RuntimeError("Error creating results list"); + } + } } - } catch (...) { - Py_XDECREF(py_results); - throw; - } + catch (...) + { + Py_XDECREF(py_results); + throw; + } - return Py::Object(py_results, true); + return Py::Object(py_results, true); } -Py::Object _path_module::affine_transform(const Py::Tuple& args) { - args.verify_length(2); +Py::Object _path_module::affine_transform(const Py::Tuple& args) +{ + args.verify_length(2); - Py::Object vertices_obj = args[0]; - Py::Object transform_obj = args[1]; + Py::Object vertices_obj = args[0]; + Py::Object transform_obj = args[1]; - PyArrayObject* vertices = NULL; - PyArrayObject* transform = NULL; - PyArrayObject* result = NULL; + PyArrayObject* vertices = NULL; + PyArrayObject* transform = NULL; + PyArrayObject* result = NULL; - try { - vertices = (PyArrayObject*)PyArray_FromObject - (vertices_obj.ptr(), PyArray_DOUBLE, 1, 2); - if (!vertices || - (PyArray_NDIM(vertices) == 2 && PyArray_DIM(vertices, 1) != 2) || - (PyArray_NDIM(vertices) == 1 && PyArray_DIM(vertices, 0) != 2)) - throw Py::ValueError("Invalid vertices array."); + try + { + vertices = (PyArrayObject*)PyArray_FromObject + (vertices_obj.ptr(), PyArray_DOUBLE, 1, 2); + if (!vertices || + (PyArray_NDIM(vertices) == 2 && PyArray_DIM(vertices, 1) != 2) || + (PyArray_NDIM(vertices) == 1 && PyArray_DIM(vertices, 0) != 2)) + throw Py::ValueError("Invalid vertices array."); - transform = (PyArrayObject*) PyArray_FromObject - (transform_obj.ptr(), PyArray_DOUBLE, 2, 2); - if (!transform || PyArray_NDIM(transform) != 2 || - PyArray_DIM(transform, 0) != 3 || PyArray_DIM(transform, 1) != 3) - throw Py::ValueError("Invalid transform."); + transform = (PyArrayObject*) PyArray_FromObject + (transform_obj.ptr(), PyArray_DOUBLE, 2, 2); + if (!transform || PyArray_NDIM(transform) != 2 || + PyArray_DIM(transform, 0) != 3 || PyArray_DIM(transform, 1) != 3) + throw Py::ValueError("Invalid transform."); - double a, b, c, d, e, f; - { - size_t stride0 = PyArray_STRIDE(transform, 0); - size_t stride1 = PyArray_STRIDE(transform, 1); - char* row0 = PyArray_BYTES(transform); - char* row1 = row0 + stride0; + double a, b, c, d, e, f; + { + size_t stride0 = PyArray_STRIDE(transform, 0); + size_t stride1 = PyArray_STRIDE(transform, 1); + char* row0 = PyArray_BYTES(transform); + char* row1 = row0 + stride0; - a = *(double*)(row0); - row0 += stride1; - c = *(double*)(row0); - row0 += stride1; - e = *(double*)(row0); + 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); - } + b = *(double*)(row1); + row1 += stride1; + d = *(double*)(row1); + row1 += stride1; + f = *(double*)(row1); + } - // I would have preferred to use PyArray_FromDims here, but on - // 64-bit platforms, PyArray_DIMS() does not return the same thing - // that PyArray_FromDims wants, requiring a copy, which I would - // like to avoid in this critical section. - result = (PyArrayObject*)PyArray_SimpleNew - (PyArray_NDIM(vertices), PyArray_DIMS(vertices), PyArray_DOUBLE); - if (PyArray_NDIM(vertices) == 2) { - size_t n = PyArray_DIM(vertices, 0); - char* vertex_in = PyArray_BYTES(vertices); - double* vertex_out = (double*)PyArray_DATA(result); - size_t stride0 = PyArray_STRIDE(vertices, 0); - size_t stride1 = PyArray_STRIDE(vertices, 1); - double x; - double y; + // I would have preferred to use PyArray_FromDims here, but on + // 64-bit platforms, PyArray_DIMS() does not return the same thing + // that PyArray_FromDims wants, requiring a copy, which I would + // like to avoid in this critical section. + result = (PyArrayObject*)PyArray_SimpleNew + (PyArray_NDIM(vertices), PyArray_DIMS(vertices), PyArray_DOUBLE); + if (PyArray_NDIM(vertices) == 2) + { + size_t n = PyArray_DIM(vertices, 0); + char* vertex_in = PyArray_BYTES(vertices); + double* vertex_out = (double*)PyArray_DATA(result); + size_t stride0 = PyArray_STRIDE(vertices, 0); + size_t stride1 = PyArray_STRIDE(vertices, 1); + double x; + double y; - for (size_t i = 0; i < n; ++i) { - x = *(double*)(vertex_in); - y = *(double*)(vertex_in + stride1); + for (size_t i = 0; i < n; ++i) + { + x = *(double*)(vertex_in); + y = *(double*)(vertex_in + stride1); - *vertex_out++ = a*x + c*y + e; - *vertex_out++ = b*x + d*y + f; + *vertex_out++ = a*x + c*y + e; + *vertex_out++ = b*x + d*y + f; - vertex_in += stride0; - } - } else { - char* vertex_in = PyArray_BYTES(vertices); - double* vertex_out = (double*)PyArray_DATA(result); - size_t stride0 = PyArray_STRIDE(vertices, 0); - double x; - double y; - x = *(double*)(vertex_in); - y = *(double*)(vertex_in + stride0); - *vertex_out++ = a*x + c*y + e; - *vertex_out++ = b*x + d*y + f; + vertex_in += stride0; + } + } + else + { + char* vertex_in = PyArray_BYTES(vertices); + double* vertex_out = (double*)PyArray_DATA(result); + size_t stride0 = PyArray_STRIDE(vertices, 0); + double x; + double y; + x = *(double*)(vertex_in); + y = *(double*)(vertex_in + stride0); + *vertex_out++ = a*x + c*y + e; + *vertex_out++ = b*x + d*y + f; + } } - } catch (...) { + catch (...) + { + Py_XDECREF(vertices); + Py_XDECREF(transform); + Py_XDECREF(result); + } + Py_XDECREF(vertices); Py_XDECREF(transform); - Py_XDECREF(result); - } - Py_XDECREF(vertices); - Py_XDECREF(transform); - - return Py::Object((PyObject*)result, true); + return Py::Object((PyObject*)result, true); } -Py::Object _path_module::count_bboxes_overlapping_bbox(const Py::Tuple& args) { - args.verify_length(2); +Py::Object _path_module::count_bboxes_overlapping_bbox(const Py::Tuple& args) +{ + args.verify_length(2); - Py::Object bbox = args[0]; - Py::SeqBase<Py::Object> bboxes = args[1]; + Py::Object bbox = args[0]; + Py::SeqBase<Py::Object> bboxes = args[1]; - double ax0, ay0, ax1, ay1; - double bx0, by0, bx1, by1; - long count = 0; + double ax0, ay0, ax1, ay1; + double bx0, by0, bx1, by1; + long count = 0; - if (py_convert_bbox(bbox.ptr(), ax0, ay0, ax1, ay1)) { - if (ax1 < ax0) - std::swap(ax0, ax1); - if (ay1 < ay0) - std::swap(ay0, ay1); + if (py_convert_bbox(bbox.ptr(), ax0, ay0, ax1, ay1)) + { + if (ax1 < ax0) + std::swap(ax0, ax1); + if (ay1 < ay0) + std::swap(ay0, ay1); - size_t num_bboxes = bboxes.size(); - for (size_t i = 0; i < num_bboxes; ++i) { - Py::Object bbox_b = bboxes[i]; - if (py_convert_bbox(bbox_b.ptr(), bx0, by0, bx1, by1)) { - if (bx1 < bx0) - std::swap(bx0, bx1); - if (by1 < by0) - std::swap(by0, by1); - if (not ((bx1 <= ax0) or - (by1 <= ay0) or - (bx0 >= ax1) or - (by0 >= ay1))) - ++count; - } else { - throw Py::ValueError("Non-bbox object in bboxes list"); - } + size_t num_bboxes = bboxes.size(); + for (size_t i = 0; i < num_bboxes; ++i) + { + Py::Object bbox_b = bboxes[i]; + if (py_convert_bbox(bbox_b.ptr(), bx0, by0, bx1, by1)) + { + if (bx1 < bx0) + std::swap(bx0, bx1); + if (by1 < by0) + std::swap(by0, by1); + if (not ((bx1 <= ax0) or + (by1 <= ay0) or + (bx0 >= ax1) or + (by0 >= ay1))) + ++count; + } + else + { + throw Py::ValueError("Non-bbox object in bboxes list"); + } + } } - } else { - throw Py::ValueError("First argument to count_bboxes_overlapping_bbox must be a Bbox object."); - } + else + { + throw Py::ValueError("First argument to count_bboxes_overlapping_bbox must be a Bbox object."); + } - return Py::Int(count); + return Py::Int(count); } bool segments_intersect(const double& x1, const double &y1, - const double& x2, const double &y2, - const double& x3, const double &y3, - const double& x4, const double &y4) { - double den = ((y4-y3) * (x2-x1)) - ((x4-x3)*(y2-y1)); - if (den == 0.0) - return false; + const double& x2, const double &y2, + const double& x3, const double &y3, + const double& x4, const double &y4) +{ + double den = ((y4-y3) * (x2-x1)) - ((x4-x3)*(y2-y1)); + if (den == 0.0) + return false; - double n1 = ((x4-x3) * (y1-y3)) - ((y4-y3)*(x1-x3)); - double n2 = ((x2-x1) * (y1-y3)) - ((y2-y1)*(x1-x3)); + double n1 = ((x4-x3) * (y1-y3)) - ((y4-y3)*(x1-x3)); + double n2 = ((x2-x1) * (y1-y3)) - ((y2-y1)*(x1-x3)); - double u1 = n1/den; - double u2 = n2/den; + double u1 = n1/den; + double u2 = n2/den; - return (u1 >= 0.0 && u1 <= 1.0 && - u2 >= 0.0 && u2 <= 1.0); + return (u1 >= 0.0 && u1 <= 1.0 && + u2 >= 0.0 && u2 <= 1.0); } -bool path_intersects_path(PathIterator& p1, PathIterator& p2) { - typedef agg::conv_curve<PathIterator> curve_t; +bool path_intersects_path(PathIterator& p1, PathIterator& p2) +{ + typedef agg::conv_curve<PathIterator> curve_t; - if (p1.total_vertices() < 2 || p2.total_vertices() < 2) - return false; + if (p1.total_vertices() < 2 || p2.total_vertices() < 2) + return false; - curve_t c1(p1); - curve_t c2(p2); + curve_t c1(p1); + curve_t c2(p2); - double x11, y11, x12, y12; - double x21, y21, x22, y22; + double x11, y11, x12, y12; + double x21, y21, x22, y22; - c1.vertex(&x11, &y11); - while (c1.vertex(&x12, &y12) != agg::path_cmd_stop) { - c2.rewind(0); - c2.vertex(&x21, &y21); - while (c2.vertex(&x22, &y22) != agg::path_cmd_stop) { - if (segments_intersect(x11, y11, x12, y12, x21, y21, x22, y22)) - return true; - x21 = x22; y21 = y22; + c1.vertex(&x11, &y11); + while (c1.vertex(&x12, &y12) != agg::path_cmd_stop) + { + c2.rewind(0); + c2.vertex(&x21, &y21); + while (c2.vertex(&x22, &y22) != agg::path_cmd_stop) + { + if (segments_intersect(x11, y11, x12, y12, x21, y21, x22, y22)) + return true; + x21 = x22; + y21 = y22; + } + x11 = x12; + y11 = y12; } - x11 = x12; y11 = y12; - } - return false; + return false; } -Py::Object _path_module::path_intersects_path(const Py::Tuple& args) { - args.verify_length(2); +Py::Object _path_module::path_intersects_path(const Py::Tuple& args) +{ + args.verify_length(2); - PathIterator p1(args[0]); - PathIterator p2(args[1]); + PathIterator p1(args[0]); + PathIterator p2(args[1]); - bool intersects = ::path_intersects_path(p1, p2); - if (!intersects) { - intersects = ::path_in_path(p1, agg::trans_affine(), p2, agg::trans_affine()); - if (!intersects) { - intersects = ::path_in_path(p2, agg::trans_affine(), p1, agg::trans_affine()); - if (!intersects) { - return Py::Int(0); - } + bool intersects = ::path_intersects_path(p1, p2); + if (!intersects) + { + intersects = ::path_in_path(p1, agg::trans_affine(), p2, agg::trans_affine()); + if (!intersects) + { + intersects = ::path_in_path(p2, agg::trans_affine(), p1, agg::trans_affine()); + if (!intersects) + { + return Py::Int(0); + } + } } - } - return Py::Int(1); + return Py::Int(1); } extern "C" -DL_EXPORT(void) - init_path(void) + DL_EXPORT(void) + init_path(void) { - import_array(); + import_array(); - static _path_module* _path = NULL; - _path = new _path_module; + static _path_module* _path = NULL; + _path = new _path_module; }; Modified: branches/transforms/src/agg_py_path_iterator.h ===========... [truncated message content] |
From: <md...@us...> - 2007-12-18 13:08:27
|
Revision: 4763 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4763&view=rev Author: mdboom Date: 2007-12-18 05:08:04 -0800 (Tue, 18 Dec 2007) Log Message: ----------- Don't allocate the clipping path buffers unless we need them. 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-12-18 13:02:33 UTC (rev 4762) +++ branches/transforms/src/_backend_agg.cpp 2007-12-18 13:08:04 UTC (rev 4763) @@ -239,27 +239,22 @@ height(height), dpi(dpi), NUMBYTES(width*height*4), + alphaBuffer(NULL), + alphaMaskRenderingBuffer(NULL), + alphaMask(NULL), + pixfmtAlphaMask(NULL), + rendererBaseAlphaMask(NULL), + rendererAlphaMask(NULL), + scanlineAlphaMask(NULL), debug(debug) { _VERBOSE("RendererAgg::RendererAgg"); unsigned stride(width*4); - pixBuffer = new agg::int8u[NUMBYTES]; renderingBuffer = new agg::rendering_buffer; renderingBuffer->attach(pixBuffer, width, height, stride); - alphaBuffer = new agg::int8u[NUMBYTES]; - alphaMaskRenderingBuffer = new agg::rendering_buffer; - alphaMaskRenderingBuffer->attach(alphaBuffer, width, height, stride); - alphaMask = new alpha_mask_type(*alphaMaskRenderingBuffer); - - pixfmtAlphaMask = new agg::pixfmt_gray8(*alphaMaskRenderingBuffer); - rendererBaseAlphaMask = new renderer_base_alpha_mask_type(*pixfmtAlphaMask); - rendererAlphaMask = new renderer_alpha_mask_type(*rendererBaseAlphaMask); - scanlineAlphaMask = new agg::scanline_p8(); - - slineP8 = new scanline_p8; slineBin = new scanline_bin; @@ -275,6 +270,21 @@ }; +void RendererAgg::create_alpha_buffers() { + if (!alphaBuffer) { + unsigned stride(width*4); + alphaBuffer = new agg::int8u[NUMBYTES]; + alphaMaskRenderingBuffer = new agg::rendering_buffer; + alphaMaskRenderingBuffer->attach(alphaBuffer, width, height, stride); + alphaMask = new alpha_mask_type(*alphaMaskRenderingBuffer); + + pixfmtAlphaMask = new agg::pixfmt_gray8(*alphaMaskRenderingBuffer); + rendererBaseAlphaMask = new renderer_base_alpha_mask_type(*pixfmtAlphaMask); + rendererAlphaMask = new renderer_alpha_mask_type(*rendererBaseAlphaMask); + scanlineAlphaMask = new agg::scanline_p8(); + } +} + template<class R> void RendererAgg::set_clipbox(const Py::Object& cliprect, R rasterizer) { @@ -442,6 +452,7 @@ if (has_clippath && (clippath.ptr() != lastclippath.ptr() || clippath_trans != lastclippath_transform)) { + create_alpha_buffers(); agg::trans_affine trans(clippath_trans); trans *= agg::trans_affine_scaling(1.0, -1.0); trans *= agg::trans_affine_translation(0.0, (double)height); @@ -617,7 +628,7 @@ _color(color) { } - void generate(color_type* output_span, int x, int y, unsigned len) + inline void generate(color_type* output_span, int x, int y, unsigned len) { _allocator.allocate(len); child_color_type* input_span = _allocator.span(); Modified: branches/transforms/src/_backend_agg.h =================================================================== --- branches/transforms/src/_backend_agg.h 2007-12-18 13:02:33 UTC (rev 4762) +++ branches/transforms/src/_backend_agg.h 2007-12-18 13:08:04 UTC (rev 4763) @@ -77,7 +77,7 @@ SafeSnap() : first(true), xsnap(0.0), lastx(0.0), lastxsnap(0.0), ysnap(0.0), lasty(0.0), lastysnap(0.0) {} SnapData snap (const float& x, const float& y); - + private: bool first; float xsnap, lastx, lastxsnap, ysnap, lasty, lastysnap; @@ -87,7 +87,7 @@ // a class in the swig wrapper class BufferRegion : public Py::PythonExtension<BufferRegion> { public: - BufferRegion(const agg::rect_i &r, bool freemem=true) : + BufferRegion(const agg::rect_i &r, bool freemem=true) : rect(r), freemem(freemem) { width = r.x2 - r.x1; height = r.y2 - r.y1; @@ -99,7 +99,7 @@ int width; int height; int stride; - + bool freemem; Py::Object to_string(const Py::Tuple &args); @@ -151,7 +151,7 @@ //struct AMRenderer { -// +// //} // the renderer @@ -246,6 +246,7 @@ const Py::SeqBase<Py::Int>& antialiaseds); private: + void create_alpha_buffers(); Py::Object lastclippath; agg::trans_affine lastclippath_transform; }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |