Revision: 5980 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5980&view=rev Author: efiring Date: 2008年08月06日 17:42:59 +0000 (2008年8月06日) Log Message: ----------- Use MPL_notisfinite in place of MPL_isnan Modified Paths: -------------- trunk/matplotlib/src/MPL_isnan.h trunk/matplotlib/src/agg_py_path_iterator.h Modified: trunk/matplotlib/src/MPL_isnan.h =================================================================== --- trunk/matplotlib/src/MPL_isnan.h 2008年08月06日 12:50:31 UTC (rev 5979) +++ trunk/matplotlib/src/MPL_isnan.h 2008年08月06日 17:42:59 UTC (rev 5980) @@ -69,3 +69,15 @@ ( (( MPL_U64(u) & 0x7ff0000000000000i64) != 0x7ff0000000000000i64)) ? 1:0 #endif #endif /* MPL_isfinite64 */ + +#if !defined(MPL_notisfinite64) +#if !defined(_MSC_VER) +#define MPL_notisfinite64(u) \ + ( (( MPL_U64(u) & 0x7ff0000000000000LL) != 0x7ff0000000000000LL)) ? 0:1 +#else +#define MPL_notisfinite64(u) \ + ( (( MPL_U64(u) & 0x7ff0000000000000i64) != 0x7ff0000000000000i64)) ? 0:1 +#endif +#endif /* MPL_notisfinite64 */ + + Modified: trunk/matplotlib/src/agg_py_path_iterator.h =================================================================== --- trunk/matplotlib/src/agg_py_path_iterator.h 2008年08月06日 12:50:31 UTC (rev 5979) +++ trunk/matplotlib/src/agg_py_path_iterator.h 2008年08月06日 17:42:59 UTC (rev 5980) @@ -76,14 +76,14 @@ if (m_iterator >= m_total_vertices) return agg::path_cmd_stop; unsigned code = vertex_with_code(m_iterator++, x, y); - if (MPL_isnan64(*x) || MPL_isnan64(*y)) { + if (MPL_notisfinite64(*x) || MPL_notisfinite64(*y)) { do { if (m_iterator < m_total_vertices) { vertex(m_iterator++, x, y); } else { return agg::path_cmd_stop; } - } while (MPL_isnan64(*x) || MPL_isnan64(*y)); + } while (MPL_notisfinite64(*x) || MPL_notisfinite64(*y)); return agg::path_cmd_move_to; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 6340 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6340&view=rev Author: mdboom Date: 2008年10月27日 21:13:24 +0000 (2008年10月27日) Log Message: ----------- Reduce heap allocation of objects. Be safer when forced to do heap allocation. Remove some dead code. Modified Paths: -------------- trunk/matplotlib/src/_backend_agg.cpp trunk/matplotlib/src/_backend_agg.h Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2008年10月27日 19:40:25 UTC (rev 6339) +++ trunk/matplotlib/src/_backend_agg.cpp 2008年10月27日 21:13:24 UTC (rev 6340) @@ -263,63 +263,57 @@ height(height), dpi(dpi), NUMBYTES(width*height*4), + pixBuffer(NULL), + renderingBuffer(), alphaBuffer(NULL), - alphaMaskRenderingBuffer(NULL), - alphaMask(NULL), - pixfmtAlphaMask(NULL), - rendererBaseAlphaMask(NULL), - rendererAlphaMask(NULL), - scanlineAlphaMask(NULL), + alphaMaskRenderingBuffer(), + alphaMask(alphaMaskRenderingBuffer), + pixfmtAlphaMask(alphaMaskRenderingBuffer), + rendererBaseAlphaMask(), + rendererAlphaMask(), + scanlineAlphaMask(), + slineP8(), + slineBin(), + pixFmt(), + rendererBase(), + rendererAA(), + rendererBin(), + theRasterizer(), 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); - - slineP8 = new scanline_p8; - slineBin = new scanline_bin; - - pixFmt = new pixfmt(*renderingBuffer); - rendererBase = new renderer_base(*pixFmt); - rendererBase->clear(agg::rgba(1, 1, 1, 0)); - - rendererAA = new renderer_aa(*rendererBase); - rendererBin = new renderer_bin(*rendererBase); - theRasterizer = new rasterizer(); - //theRasterizer->filling_rule(agg::fill_even_odd); - //theRasterizer->filling_rule(agg::fill_non_zero); - + renderingBuffer.attach(pixBuffer, width, height, stride); + pixFmt.attach(renderingBuffer); + rendererBase.attach(pixFmt); + rendererBase.clear(agg::rgba(1, 1, 1, 0)); + rendererAA.attach(rendererBase); + rendererBin.attach(rendererBase); } 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(); + alphaMaskRenderingBuffer.attach(alphaBuffer, width, height, stride); + rendererBaseAlphaMask.attach(pixfmtAlphaMask); + rendererAlphaMask.attach(rendererBaseAlphaMask); } } template<class R> void -RendererAgg::set_clipbox(const Py::Object& cliprect, R rasterizer) { +RendererAgg::set_clipbox(const Py::Object& cliprect, R& rasterizer) { //set the clip rectangle from the gc _VERBOSE("RendererAgg::set_clipbox"); double l, b, r, t; if (py_convert_bbox(cliprect.ptr(), l, b, r, t)) { - rasterizer->clip_box(int(mpl_round(l)) + 1, height - int(mpl_round(b)), - int(mpl_round(r)), height - int(mpl_round(t))); + rasterizer.clip_box(int(mpl_round(l)) + 1, height - int(mpl_round(b)), + int(mpl_round(r)), height - int(mpl_round(t))); } _VERBOSE("RendererAgg::set_clipbox done"); @@ -341,45 +335,6 @@ return face; } -SnapData -SafeSnap::snap (const float& x, const float& y) { - xsnap = (int)(x + 0.5f); - ysnap = (int)(y + 0.5f); - - if ( first || ( (xsnap!=lastxsnap) || (ysnap!=lastysnap) ) ) { - lastxsnap = xsnap; - lastysnap = ysnap; - lastx = x; - lasty = y; - first = false; - return SnapData(true, xsnap, ysnap); - } - - // ok both are equal and we need to do an offset - if ( (x==lastx) && (y==lasty) ) { - // no choice but to return equal coords; set newpoint = false - lastxsnap = xsnap; - lastysnap = ysnap; - lastx = x; - lasty = y; - return SnapData(false, xsnap, ysnap); - } - - // ok the real points are not identical but the rounded ones, so do - // a one pixel offset - if (x>lastx) xsnap += 1.; - else if (x<lastx) xsnap -= 1.; - - if (y>lasty) ysnap += 1.; - else if (y<lasty) ysnap -= 1.; - - lastxsnap = xsnap; - lastysnap = ysnap; - lastx = x; - lasty = y; - return SnapData(true, xsnap, ysnap); -} - template<class Path> bool should_snap(Path& path, const agg::trans_affine& trans) { // If this contains only straight horizontal or vertical lines, it should be @@ -443,12 +398,17 @@ throw Py::MemoryError("RendererAgg::copy_from_bbox could not allocate memory for buffer"); } - agg::rendering_buffer rbuf; - rbuf.attach(reg->data, reg->width, reg->height, reg->stride); + try { + agg::rendering_buffer rbuf; + rbuf.attach(reg->data, reg->width, reg->height, reg->stride); - pixfmt pf(rbuf); - renderer_base rb(pf); - rb.copy_from(*renderingBuffer, &rect, -rect.x1, -rect.y1); + pixfmt pf(rbuf); + renderer_base rb(pf); + rb.copy_from(renderingBuffer, &rect, -rect.x1, -rect.y1); + } catch (...) { + delete reg; + throw Py::RuntimeError("An unknown error occurred in copy_from_bbox"); + } return Py::asObject(reg); } @@ -468,7 +428,7 @@ region->height, region->stride); - rendererBase->copy_from(rbuf, 0, region->rect.x1, region->rect.y1); + rendererBase.copy_from(rbuf, 0, region->rect.x1, region->rect.y1); return Py::Object(); } @@ -488,12 +448,12 @@ trans *= agg::trans_affine_translation(0.0, (double)height); PathIterator clippath_iter(clippath); - rendererBaseAlphaMask->clear(agg::gray8(0, 0)); + rendererBaseAlphaMask.clear(agg::gray8(0, 0)); transformed_path_t transformed_clippath(clippath_iter, trans); agg::conv_curve<transformed_path_t> curved_clippath(transformed_clippath); - theRasterizer->add_path(curved_clippath); - rendererAlphaMask->color(agg::gray8(255, 255)); - agg::render_scanlines(*theRasterizer, *scanlineAlphaMask, *rendererAlphaMask); + theRasterizer.add_path(curved_clippath); + rendererAlphaMask.color(agg::gray8(255, 255)); + agg::render_scanlines(theRasterizer, scanlineAlphaMask, rendererAlphaMask); lastclippath = clippath; lastclippath_transform = clippath_trans; } @@ -544,24 +504,22 @@ //maxim's suggestions for cached scanlines agg::scanline_storage_aa8 scanlines; - theRasterizer->reset(); - theRasterizer->reset_clipping(); - rendererBase->reset_clipping(true); + theRasterizer.reset(); + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); agg::int8u staticFillCache[MARKER_CACHE_SIZE]; agg::int8u staticStrokeCache[MARKER_CACHE_SIZE]; - agg::int8u* fillCache = NULL; - agg::int8u* strokeCache = NULL; + agg::int8u* fillCache = staticFillCache; + agg::int8u* strokeCache = staticStrokeCache; try { unsigned fillSize = 0; if (face.first) { - theRasterizer->add_path(marker_path_curve); - agg::render_scanlines(*theRasterizer, *slineP8, scanlines); + theRasterizer.add_path(marker_path_curve); + agg::render_scanlines(theRasterizer, slineP8, scanlines); fillSize = scanlines.byte_size(); - if (fillSize < MARKER_CACHE_SIZE) - fillCache = staticFillCache; - else + if (fillSize >= MARKER_CACHE_SIZE) fillCache = new agg::int8u[fillSize]; scanlines.serialize(fillCache); } @@ -570,18 +528,16 @@ stroke.width(gc.linewidth); stroke.line_cap(gc.cap); stroke.line_join(gc.join); - theRasterizer->reset(); - theRasterizer->add_path(stroke); - agg::render_scanlines(*theRasterizer, *slineP8, scanlines); + theRasterizer.reset(); + theRasterizer.add_path(stroke); + agg::render_scanlines(theRasterizer, slineP8, scanlines); unsigned strokeSize = scanlines.byte_size(); - if (strokeSize < MARKER_CACHE_SIZE) - strokeCache = staticStrokeCache; - else + if (strokeSize >= MARKER_CACHE_SIZE) strokeCache = new agg::int8u[strokeSize]; scanlines.serialize(strokeCache); - theRasterizer->reset_clipping(); - rendererBase->reset_clipping(true); + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); set_clipbox(gc.cliprect, rendererBase); bool has_clippath = render_clippath(gc.clippath, gc.clippath_trans); @@ -592,7 +548,7 @@ if (has_clippath) { while (path_transformed.vertex(&x, &y) != agg::path_cmd_stop) { - pixfmt_amask_type pfa(*pixFmt, *alphaMask); + pixfmt_amask_type pfa(pixFmt, alphaMask); amask_ren_type r(pfa); amask_aa_renderer_type ren(r); @@ -608,14 +564,14 @@ } else { while (path_transformed.vertex(&x, &y) != agg::path_cmd_stop) { if (face.first) { - rendererAA->color(face.second); + rendererAA.color(face.second); sa.init(fillCache, fillSize, x, y); - agg::render_scanlines(sa, sl, *rendererAA); + agg::render_scanlines(sa, sl, rendererAA); } - rendererAA->color(gc.color); + rendererAA.color(gc.color); sa.init(strokeCache, strokeSize, x, y); - agg::render_scanlines(sa, sl, *rendererAA); + agg::render_scanlines(sa, sl, rendererAA); } } } catch(...) { @@ -734,8 +690,8 @@ GCAgg gc = GCAgg(args[4], dpi); - theRasterizer->reset_clipping(); - rendererBase->reset_clipping(true); + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); set_clipbox(gc.cliprect, theRasterizer); agg::rendering_buffer srcbuf((agg::int8u*)buffer, width, height, width); @@ -764,10 +720,10 @@ image_accessor_type ia(pixf_img, 0); image_span_gen_type image_span_generator(ia, interpolator, filter); span_gen_type output_span_generator(&image_span_generator, gc.color); - renderer_type ri(*rendererBase, sa, output_span_generator); + renderer_type ri(rendererBase, sa, output_span_generator); - theRasterizer->add_path(rect2); - agg::render_scanlines(*theRasterizer, *slineP8, ri); + theRasterizer.add_path(rect2); + agg::render_scanlines(theRasterizer, slineP8, ri); Py_XDECREF(image_array); @@ -789,8 +745,8 @@ agg::trans_affine clippath_trans; bool has_clippath = false; - theRasterizer->reset_clipping(); - rendererBase->reset_clipping(true); + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); if (args.size() == 6) { clippath = args[4]; clippath_trans = py_to_agg_transformation_matrix(args[5], false); @@ -828,15 +784,15 @@ image_accessor_type ia(pixf, agg::rgba8(0, 0, 0, 0)); interpolator_type interpolator(inv_mtx); image_span_gen_type image_span_generator(ia, interpolator); - pixfmt_amask_type pfa(*pixFmt, *alphaMask); + pixfmt_amask_type pfa(pixFmt, alphaMask); amask_ren_type r(pfa); renderer_type ri(r, sa, image_span_generator); - theRasterizer->add_path(rect2); - agg::render_scanlines(*theRasterizer, *slineP8, ri); + theRasterizer.add_path(rect2); + agg::render_scanlines(theRasterizer, slineP8, ri); } else { set_clipbox(box_obj, rendererBase); - rendererBase->blend_from(pixf, 0, (int)x, (int)(height-(y+image->rowsOut))); + rendererBase.blend_from(pixf, 0, (int)x, (int)(height-(y+image->rowsOut))); } image->flipud_out(empty); @@ -857,29 +813,29 @@ // Render face if (face.first) { - theRasterizer->add_path(path); + theRasterizer.add_path(path); if (gc.isaa) { if (has_clippath) { - pixfmt_amask_type pfa(*pixFmt, *alphaMask); + pixfmt_amask_type pfa(pixFmt, alphaMask); amask_ren_type r(pfa); amask_aa_renderer_type ren(r); ren.color(face.second); - agg::render_scanlines(*theRasterizer, *slineP8, ren); + agg::render_scanlines(theRasterizer, slineP8, ren); } else { - rendererAA->color(face.second); - agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); + rendererAA.color(face.second); + agg::render_scanlines(theRasterizer, slineP8, rendererAA); } } else { if (has_clippath) { - pixfmt_amask_type pfa(*pixFmt, *alphaMask); + pixfmt_amask_type pfa(pixFmt, alphaMask); amask_ren_type r(pfa); amask_bin_renderer_type ren(r); ren.color(face.second); - agg::render_scanlines(*theRasterizer, *slineP8, ren); + agg::render_scanlines(theRasterizer, slineP8, ren); } else { - rendererBin->color(face.second); - agg::render_scanlines(*theRasterizer, *slineP8, *rendererBin); + rendererBin.color(face.second); + agg::render_scanlines(theRasterizer, slineP8, rendererBin); } } } @@ -895,7 +851,7 @@ stroke.width(linewidth); stroke.line_cap(gc.cap); stroke.line_join(gc.join); - theRasterizer->add_path(stroke); + theRasterizer.add_path(stroke); } else { dash_t dash(path); for (GCAgg::dash_t::const_iterator i = gc.dashes.begin(); @@ -912,30 +868,30 @@ stroke.line_cap(gc.cap); stroke.line_join(gc.join); stroke.width(linewidth); - theRasterizer->add_path(stroke); + theRasterizer.add_path(stroke); } if (gc.isaa) { if (has_clippath) { - pixfmt_amask_type pfa(*pixFmt, *alphaMask); + pixfmt_amask_type pfa(pixFmt, alphaMask); amask_ren_type r(pfa); amask_aa_renderer_type ren(r); ren.color(gc.color); - agg::render_scanlines(*theRasterizer, *slineP8, ren); + agg::render_scanlines(theRasterizer, slineP8, ren); } else { - rendererAA->color(gc.color); - agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); + rendererAA.color(gc.color); + agg::render_scanlines(theRasterizer, slineP8, rendererAA); } } else { if (has_clippath) { - pixfmt_amask_type pfa(*pixFmt, *alphaMask); + pixfmt_amask_type pfa(pixFmt, alphaMask); amask_ren_type r(pfa); amask_bin_renderer_type ren(r); ren.color(gc.color); - agg::render_scanlines(*theRasterizer, *slineP8, ren); + agg::render_scanlines(theRasterizer, slineP8, ren); } else { - rendererBin->color(gc.color); - agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin); + rendererBin.color(gc.color); + agg::render_scanlines(theRasterizer, slineBin, rendererBin); } } } @@ -961,8 +917,8 @@ GCAgg gc = GCAgg(gc_obj, dpi); facepair_t face = _get_rgba_face(face_obj, gc.alpha); - theRasterizer->reset_clipping(); - rendererBase->reset_clipping(true); + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); set_clipbox(gc.cliprect, theRasterizer); bool has_clippath = render_clippath(gc.clippath, gc.clippath_trans); @@ -1074,8 +1030,8 @@ } // Handle any clipping globally - theRasterizer->reset_clipping(); - rendererBase->reset_clipping(true); + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); set_clipbox(cliprect, theRasterizer); bool has_clippath = render_clippath(clippath, clippath_trans); @@ -1430,21 +1386,28 @@ args.verify_length(0); int row_len = width*3; unsigned char* buf_tmp = new unsigned char[row_len * height]; - if (buf_tmp ==NULL) { + if (buf_tmp == NULL) { //todo: also handle allocation throw throw Py::MemoryError("RendererAgg::tostring_rgb could not allocate memory"); } - agg::rendering_buffer renderingBufferTmp; - renderingBufferTmp.attach(buf_tmp, - width, - height, - row_len); - agg::color_conv(&renderingBufferTmp, renderingBuffer, agg::color_conv_rgba32_to_rgb24()); + try { + agg::rendering_buffer renderingBufferTmp; + renderingBufferTmp.attach(buf_tmp, + width, + height, + row_len); + agg::color_conv(&renderingBufferTmp, &renderingBuffer, agg::color_conv_rgba32_to_rgb24()); + } catch (...) { + delete [] buf_tmp; + throw Py::RuntimeError("Unknown exception occurred in tostring_rgb"); + } + //todo: how to do this with native CXX PyObject* o = Py_BuildValue("s#", buf_tmp, row_len * height); + delete [] buf_tmp; return Py::asObject(o); } @@ -1463,12 +1426,16 @@ //todo: also handle allocation throw throw Py::MemoryError("RendererAgg::tostring_argb could not allocate memory"); } - agg::rendering_buffer renderingBufferTmp; - renderingBufferTmp.attach(buf_tmp, width, height, row_len); - agg::color_conv(&renderingBufferTmp, renderingBuffer, agg::color_conv_rgba32_to_argb32()); + try { + agg::rendering_buffer renderingBufferTmp; + renderingBufferTmp.attach(buf_tmp, width, height, row_len); + agg::color_conv(&renderingBufferTmp, &renderingBuffer, agg::color_conv_rgba32_to_argb32()); + } catch (...) { + delete [] buf_tmp; + throw Py::RuntimeError("Unknown exception occurred in tostring_argb"); + } - //todo: how to do this with native CXX PyObject* o = Py_BuildValue("s#", buf_tmp, row_len * height); delete [] buf_tmp; @@ -1488,14 +1455,19 @@ //todo: also handle allocation throw throw Py::MemoryError("RendererAgg::tostring_bgra could not allocate memory"); } - agg::rendering_buffer renderingBufferTmp; - renderingBufferTmp.attach(buf_tmp, - width, - height, - row_len); - agg::color_conv(&renderingBufferTmp, renderingBuffer, agg::color_conv_rgba32_to_bgra32()); + try { + agg::rendering_buffer renderingBufferTmp; + renderingBufferTmp.attach(buf_tmp, + width, + height, + row_len); + agg::color_conv(&renderingBufferTmp, &renderingBuffer, agg::color_conv_rgba32_to_bgra32()); + } catch (...) { + delete [] buf_tmp; + throw Py::RuntimeError("Unknown exception occurred in tostring_bgra"); + } //todo: how to do this with native CXX PyObject* o = Py_BuildValue("s#", @@ -1557,12 +1529,17 @@ int newsize = newwidth * newheight * 4; unsigned char* buf = new unsigned char[newsize]; + if (buf == NULL) { + throw Py::MemoryError("RendererAgg::tostring_minimized could not allocate memory"); + } + unsigned int* dst = (unsigned int*)buf; unsigned int* src = (unsigned int*)pixBuffer; for (int y = ymin; y < ymax; ++y) for (int x = xmin; x < xmax; ++x, ++dst) *dst = src[y * width + x]; + // The Py::String will take over the buffer data = Py::String((const char *)buf, (int)newsize); } @@ -1586,7 +1563,7 @@ _VERBOSE("RendererAgg::clear"); args.verify_length(0); - rendererBase->clear(agg::rgba(1, 1, 1, 0)); + rendererBase.clear(agg::rgba(1, 1, 1, 0)); return Py::Object(); } @@ -1627,25 +1604,8 @@ _VERBOSE("RendererAgg::~RendererAgg"); - - delete slineP8; - delete slineBin; - delete theRasterizer; - delete rendererAA; - delete rendererBin; - delete rendererBase; - delete pixFmt; - delete renderingBuffer; - - delete alphaMask; - delete alphaMaskRenderingBuffer; delete [] alphaBuffer; delete [] pixBuffer; - delete pixfmtAlphaMask; - delete rendererBaseAlphaMask; - delete rendererAlphaMask; - delete scanlineAlphaMask; - } /* ------------ module methods ------------- */ @@ -1752,5 +1712,4 @@ static _backend_agg_module* _backend_agg = NULL; _backend_agg = new _backend_agg_module; - } Modified: trunk/matplotlib/src/_backend_agg.h =================================================================== --- trunk/matplotlib/src/_backend_agg.h 2008年10月27日 19:40:25 UTC (rev 6339) +++ trunk/matplotlib/src/_backend_agg.h 2008年10月27日 21:13:24 UTC (rev 6340) @@ -64,25 +64,6 @@ typedef agg::renderer_base<agg::pixfmt_gray8> renderer_base_alpha_mask_type; typedef agg::renderer_scanline_aa_solid<renderer_base_alpha_mask_type> renderer_alpha_mask_type; -struct SnapData { - SnapData(const bool& newpoint, const float& xsnap, const float& ysnap) : - newpoint(newpoint), xsnap(xsnap), ysnap(ysnap) {} - bool newpoint; - float xsnap, ysnap; -}; - -class SafeSnap { - // snap to pixel center, avoiding 0 path length rounding errors. -public: - 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; -}; - // a helper class to pass agg::buffer objects around. agg::buffer is // a class in the swig wrapper class BufferRegion : public Py::PythonExtension<BufferRegion> { @@ -198,27 +179,27 @@ size_t NUMBYTES; //the number of bytes in buffer agg::int8u *pixBuffer; - agg::rendering_buffer *renderingBuffer; + agg::rendering_buffer renderingBuffer; agg::int8u *alphaBuffer; - agg::rendering_buffer *alphaMaskRenderingBuffer; - alpha_mask_type *alphaMask; - agg::pixfmt_gray8 *pixfmtAlphaMask; - renderer_base_alpha_mask_type *rendererBaseAlphaMask; - renderer_alpha_mask_type *rendererAlphaMask; - agg::scanline_p8 *scanlineAlphaMask; + agg::rendering_buffer alphaMaskRenderingBuffer; + alpha_mask_type alphaMask; + agg::pixfmt_gray8 pixfmtAlphaMask; + renderer_base_alpha_mask_type rendererBaseAlphaMask; + renderer_alpha_mask_type rendererAlphaMask; + agg::scanline_p8 scanlineAlphaMask; + scanline_p8 slineP8; + scanline_bin slineBin; + pixfmt pixFmt; + renderer_base rendererBase; + renderer_aa rendererAA; + renderer_bin rendererBin; + rasterizer theRasterizer; + Py::Object lastclippath; + agg::trans_affine lastclippath_transform; - scanline_p8* slineP8; - scanline_bin* slineBin; - pixfmt *pixFmt; - renderer_base *rendererBase; - renderer_aa *rendererAA; - renderer_bin *rendererBin; - rasterizer *theRasterizer; - - const int debug; protected: @@ -227,7 +208,7 @@ agg::rgba rgb_to_color(const Py::SeqBase<Py::Object>& rgb, double alpha); facepair_t _get_rgba_face(const Py::Object& rgbFace, double alpha); template<class R> - void set_clipbox(const Py::Object& cliprect, R rasterizer); + 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, bool has_clippath, @@ -251,8 +232,6 @@ private: void create_alpha_buffers(); - Py::Object lastclippath; - agg::trans_affine lastclippath_transform; }; // the extension module This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 6341 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6341&view=rev Author: mdboom Date: 2008年10月28日 12:51:39 +0000 (2008年10月28日) Log Message: ----------- Update TkAgg and GtkAgg extensions to match yesterday's refactoring in backend_agg Modified Paths: -------------- trunk/matplotlib/src/_gtkagg.cpp trunk/matplotlib/src/_tkagg.cpp Modified: trunk/matplotlib/src/_gtkagg.cpp =================================================================== --- trunk/matplotlib/src/_gtkagg.cpp 2008年10月27日 21:13:24 UTC (rev 6340) +++ trunk/matplotlib/src/_gtkagg.cpp 2008年10月28日 12:51:39 UTC (rev 6341) @@ -98,7 +98,7 @@ //destrb.clear(agg::rgba(1, 1, 1, 0)); agg::rect_base<int> region(destx, desty, (int)r, srcheight-(int)b); - destrb.copy_from(*aggRenderer->renderingBuffer, ®ion, + destrb.copy_from(aggRenderer->renderingBuffer, ®ion, -destx, -desty); } Modified: trunk/matplotlib/src/_tkagg.cpp =================================================================== --- trunk/matplotlib/src/_tkagg.cpp 2008年10月27日 21:13:24 UTC (rev 6340) +++ trunk/matplotlib/src/_tkagg.cpp 2008年10月28日 12:51:39 UTC (rev 6341) @@ -131,7 +131,7 @@ renderer_base destrb(destpf); agg::rect_base<int> region(destx, desty, (int)r, srcheight-(int)b); - destrb.copy_from(*aggRenderer->renderingBuffer, ®ion, + destrb.copy_from(aggRenderer->renderingBuffer, ®ion, -destx, -desty); } else { has_bbox = false; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 6475 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6475&view=rev Author: mdboom Date: 2008年12月02日 19:51:10 +0000 (2008年12月02日) Log Message: ----------- suppress gcc-4.3 warnings Modified Paths: -------------- trunk/matplotlib/src/_backend_agg.cpp trunk/matplotlib/src/_image.cpp Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2008年12月02日 17:55:15 UTC (rev 6474) +++ trunk/matplotlib/src/_backend_agg.cpp 2008年12月02日 19:51:10 UTC (rev 6475) @@ -1216,8 +1216,8 @@ private: inline unsigned vertex(unsigned idx, double* x, double* y) { - size_t m = m_m + ((idx & 0x2) >> 1); - size_t n = m_n + ((idx+1 & 0x2) >> 1); + size_t m = m_m + ((idx & 0x2) >> 1); + size_t n = m_n + (((idx+1) & 0x2) >> 1); double* pair = (double*)PyArray_GETPTR2(m_coordinates, n, m); *x = *pair++; *y = *pair; @@ -1336,11 +1336,15 @@ throw Py::RuntimeError(e); } } catch (...) { - if (free_edgecolors) Py_XDECREF(edgecolors_obj.ptr()); + if (free_edgecolors) { + Py_XDECREF(edgecolors_obj.ptr()); + } throw; } - if (free_edgecolors) Py_XDECREF(edgecolors_obj.ptr()); + if (free_edgecolors) { + Py_XDECREF(edgecolors_obj.ptr()); + } return Py::Object(); } Modified: trunk/matplotlib/src/_image.cpp =================================================================== --- trunk/matplotlib/src/_image.cpp 2008年12月02日 17:55:15 UTC (rev 6474) +++ trunk/matplotlib/src/_image.cpp 2008年12月02日 19:51:10 UTC (rev 6475) @@ -1327,20 +1327,27 @@ void _pcolor_cleanup(PyArrayObject* x, PyArrayObject* y, PyArrayObject *d, unsigned int * rowstarts ,unsigned int*colstarts , float *acols , float *arows) { - if (x) + if (x) { Py_XDECREF(x); - if (y) + } + if (y) { Py_XDECREF(y); - if(d) + } + if(d) { Py_XDECREF(d); - if(rowstarts) + } + if(rowstarts) { PyMem_Free(rowstarts); - if(colstarts) + } + if(colstarts) { PyMem_Free(colstarts); - if(acols) + } + if(acols) { PyMem_Free(acols); - if(arows) + } + if(arows) { PyMem_Free(arows); + } return; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 6897 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6897&view=rev Author: mdboom Date: 2009年02月09日 20:06:49 +0000 (2009年2月09日) Log Message: ----------- Fix indentation. Modified Paths: -------------- trunk/matplotlib/src/path_cleanup.cpp trunk/matplotlib/src/path_cleanup.h Modified: trunk/matplotlib/src/path_cleanup.cpp =================================================================== --- trunk/matplotlib/src/path_cleanup.cpp 2009年02月09日 20:06:32 UTC (rev 6896) +++ trunk/matplotlib/src/path_cleanup.cpp 2009年02月09日 20:06:49 UTC (rev 6897) @@ -7,7 +7,8 @@ #include "agg_py_transforms.h" #include "path_converters.h" -class PathCleanupIterator { +class PathCleanupIterator +{ typedef agg::conv_transform<PathIterator> transformed_path_t; typedef PathNanRemover<transformed_path_t> nan_removal_t; typedef PathClipper<nan_removal_t> clipped_t; @@ -49,36 +50,36 @@ }; extern "C" { - void* - get_path_iterator( - PyObject* path, PyObject* trans, int remove_nans, int do_clip, - double rect[4], e_quantize_mode quantize_mode, int do_simplify) - { - agg::trans_affine agg_trans = py_to_agg_transformation_matrix(trans, false); - agg::rect_base<double> clip_rect(rect[0], rect[1], rect[2], rect[3]); + void* + get_path_iterator( + PyObject* path, PyObject* trans, int remove_nans, int do_clip, + double rect[4], e_quantize_mode quantize_mode, int do_simplify) + { + agg::trans_affine agg_trans = py_to_agg_transformation_matrix(trans, false); + agg::rect_base<double> clip_rect(rect[0], rect[1], rect[2], rect[3]); - PathCleanupIterator* pipeline = new PathCleanupIterator( - path, agg_trans, remove_nans != 0, do_clip != 0, - clip_rect, quantize_mode, do_simplify != 0); + PathCleanupIterator* pipeline = new PathCleanupIterator( + path, agg_trans, remove_nans != 0, do_clip != 0, + clip_rect, quantize_mode, do_simplify != 0); - return (void*)pipeline; - } + return (void*)pipeline; + } - unsigned - get_vertex(void* pipeline, double* x, double* y) - { - PathCleanupIterator* pipeline_iter = (PathCleanupIterator*)pipeline; + unsigned + get_vertex(void* pipeline, double* x, double* y) + { + PathCleanupIterator* pipeline_iter = (PathCleanupIterator*)pipeline; - unsigned code = pipeline_iter->vertex(x, y); - return code; - } + unsigned code = pipeline_iter->vertex(x, y); + return code; + } - void - free_path_iterator(void* pipeline) - { - PathCleanupIterator* pipeline_iter = (PathCleanupIterator*)pipeline; + void + free_path_iterator(void* pipeline) + { + PathCleanupIterator* pipeline_iter = (PathCleanupIterator*)pipeline; - delete pipeline_iter; - } + delete pipeline_iter; + } } Modified: trunk/matplotlib/src/path_cleanup.h =================================================================== --- trunk/matplotlib/src/path_cleanup.h 2009年02月09日 20:06:32 UTC (rev 6896) +++ trunk/matplotlib/src/path_cleanup.h 2009年02月09日 20:06:49 UTC (rev 6897) @@ -12,8 +12,8 @@ void* get_path_iterator( - PyObject* path, PyObject* trans, int remove_nans, int do_clip, - double rect[4], e_quantize_mode quantize_mode, int do_simplify); + PyObject* path, PyObject* trans, int remove_nans, int do_clip, + double rect[4], e_quantize_mode quantize_mode, int do_simplify); unsigned get_vertex(void* pipeline, double* x, double* y); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8458 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8458&view=rev Author: mdboom Date: 2010年06月23日 14:43:52 +0000 (2010年6月23日) Log Message: ----------- Uses doubles for rectangle clipping everywhere in the Agg backend. Modified Paths: -------------- trunk/matplotlib/src/_backend_agg.h trunk/matplotlib/src/_image.cpp Modified: trunk/matplotlib/src/_backend_agg.h =================================================================== --- trunk/matplotlib/src/_backend_agg.h 2010年06月23日 14:18:05 UTC (rev 8457) +++ trunk/matplotlib/src/_backend_agg.h 2010年06月23日 14:43:52 UTC (rev 8458) @@ -55,7 +55,7 @@ typedef agg::renderer_base<pixfmt> renderer_base; typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_aa; typedef agg::renderer_scanline_bin_solid<renderer_base> renderer_bin; -typedef agg::rasterizer_scanline_aa<> rasterizer; +typedef agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> rasterizer; typedef agg::scanline_p8 scanline_p8; typedef agg::scanline_bin scanline_bin; Modified: trunk/matplotlib/src/_image.cpp =================================================================== --- trunk/matplotlib/src/_image.cpp 2010年06月23日 14:18:05 UTC (rev 8457) +++ trunk/matplotlib/src/_image.cpp 2010年06月23日 14:43:52 UTC (rev 8458) @@ -39,7 +39,7 @@ typedef agg::pixfmt_rgba32 pixfmt; typedef agg::renderer_base<pixfmt> renderer_base; typedef agg::span_interpolator_linear<> interpolator_type; -typedef agg::rasterizer_scanline_aa<> rasterizer; +typedef agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> rasterizer; Image::Image() : @@ -351,7 +351,7 @@ pixfmt pixf(*rbufOut); renderer_base rb(pixf); rb.clear(bg); - agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> ras; + rasterizer ras; agg::scanline_u8 sl; ras.clip_box(0, 0, numcols, numrows); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8460 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8460&view=rev Author: mdboom Date: 2010年06月24日 13:06:03 +0000 (2010年6月24日) Log Message: ----------- Standardizing formatting of C/C++ code. Modified Paths: -------------- trunk/matplotlib/src/_backend_agg.cpp trunk/matplotlib/src/_backend_agg.h trunk/matplotlib/src/_gtkagg.cpp trunk/matplotlib/src/_image.cpp trunk/matplotlib/src/_image.h trunk/matplotlib/src/_path.cpp trunk/matplotlib/src/_png.cpp trunk/matplotlib/src/_tkagg.cpp trunk/matplotlib/src/_ttconv.cpp trunk/matplotlib/src/_windowing.cpp trunk/matplotlib/src/_wxagg.cpp trunk/matplotlib/src/agg_py_path_iterator.h trunk/matplotlib/src/ft2font.cpp trunk/matplotlib/src/ft2font.h trunk/matplotlib/src/mplutils.cpp trunk/matplotlib/src/mplutils.h trunk/matplotlib/src/path_cleanup.cpp trunk/matplotlib/src/path_converters.h Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2010年06月23日 14:44:32 UTC (rev 8459) +++ trunk/matplotlib/src/_backend_agg.cpp 2010年06月24日 13:06:03 UTC (rev 8460) @@ -54,57 +54,82 @@ /* Convert dashes from the Python representation as nested sequences to the C++ representation as a std::vector<std::pair<double, double> > - (GCAgg::dash_t) -*/ -void convert_dashes(const Py::Tuple& dashes, double dpi, GCAgg::dash_t& dashes_out, - double& dashOffset_out) { - if (dashes.length()!=2) - throw Py::ValueError(Printf("Dash descriptor must be a length 2 tuple; found %d", dashes.length()).str()); + (GCAgg::dash_t) */ +void +convert_dashes(const Py::Tuple& dashes, double dpi, + GCAgg::dash_t& dashes_out, double& dashOffset_out) +{ + if (dashes.length() != 2) + { + throw Py::ValueError( + Printf("Dash descriptor must be a length 2 tuple; found %d", + dashes.length()).str() + ); + } - dashes_out.clear(); - dashOffset_out = 0.0; - if (dashes[0].ptr() == Py_None) - return; + dashes_out.clear(); + dashOffset_out = 0.0; + if (dashes[0].ptr() == Py_None) + { + return; + } - dashOffset_out = double(Py::Float(dashes[0])) * dpi/72.0; + dashOffset_out = double(Py::Float(dashes[0])) * dpi / 72.0; - Py::SeqBase<Py::Object> dashSeq = dashes[1]; + Py::SeqBase<Py::Object> dashSeq = dashes[1]; - size_t Ndash = dashSeq.length(); - if (Ndash % 2 != 0) - throw Py::ValueError(Printf("Dash sequence must be an even length sequence; found %d", Ndash).str()); + size_t Ndash = dashSeq.length(); + if (Ndash % 2 != 0) + { + throw Py::ValueError( + Printf("Dash sequence must be an even length sequence; found %d", Ndash).str() + ); + } - dashes_out.clear(); - dashes_out.reserve(Ndash / 2); + dashes_out.clear(); + dashes_out.reserve(Ndash / 2); - double val0, val1; - for (size_t i = 0; i < Ndash; i += 2) { - val0 = double(Py::Float(dashSeq[i])) * dpi/72.0; - val1 = double(Py::Float(dashSeq[i+1])) * dpi/72.0; - dashes_out.push_back(std::make_pair(val0, val1)); - } + double val0, val1; + for (size_t i = 0; i < Ndash; i += 2) + { + val0 = double(Py::Float(dashSeq[i])) * dpi / 72.0; + val1 = double(Py::Float(dashSeq[i+1])) * dpi / 72.0; + dashes_out.push_back(std::make_pair(val0, val1)); + } } -Py::Object BufferRegion::to_string(const Py::Tuple &args) { - // owned=true to prevent memory leak - return Py::String(PyString_FromStringAndSize((const char*)data, height*stride), true); + +Py::Object +BufferRegion::to_string(const Py::Tuple &args) +{ + // owned=true to prevent memory leak + return Py::String(PyString_FromStringAndSize((const char*)data, height*stride), true); } -Py::Object BufferRegion::set_x(const Py::Tuple &args) { + +Py::Object +BufferRegion::set_x(const Py::Tuple &args) +{ args.verify_length(1); - size_t x = Py::Int( args[0] ); + size_t x = Py::Int(args[0]); rect.x1 = x; return Py::Object(); } -Py::Object BufferRegion::set_y(const Py::Tuple &args) { + +Py::Object +BufferRegion::set_y(const Py::Tuple &args) +{ args.verify_length(1); - size_t y = Py::Int( args[0] ); + size_t y = Py::Int(args[0]); rect.y1 = y; return Py::Object(); } -Py::Object BufferRegion::get_extents(const Py::Tuple &args) { + +Py::Object +BufferRegion::get_extents(const Py::Tuple &args) +{ args.verify_length(0); Py::Tuple extents(4); @@ -116,562 +141,673 @@ return extents; } -Py::Object BufferRegion::to_string_argb(const Py::Tuple &args) { - // owned=true to prevent memory leak - Py_ssize_t length; - unsigned char* pix; - unsigned char* begin; - unsigned char* end; - unsigned char tmp; - size_t i, j; - PyObject* str = PyString_FromStringAndSize((const char*)data, height*stride); - if (PyString_AsStringAndSize(str, (char**)&begin, &length)) { - throw Py::TypeError("Could not create memory for blit"); - } +Py::Object +BufferRegion::to_string_argb(const Py::Tuple &args) +{ + // owned=true to prevent memory leak + Py_ssize_t length; + unsigned char* pix; + unsigned char* begin; + unsigned char* end; + unsigned char tmp; + size_t i, j; - pix = begin; - end = begin + (height * stride); - for (i = 0; i < (size_t)height; ++i) { - pix = begin + i * stride; - for (j = 0; j < (size_t)width; ++j) { - // Convert rgba to argb - tmp = pix[2]; - pix[2] = pix[0]; - pix[0] = tmp; - pix += 4; + PyObject* str = PyString_FromStringAndSize( + (const char*)data, height * stride); + if (PyString_AsStringAndSize(str, (char**)&begin, &length)) + { + throw Py::TypeError("Could not create memory for blit"); } - } - return Py::String(str, true); + pix = begin; + end = begin + (height * stride); + for (i = 0; i < (size_t)height; ++i) + { + pix = begin + i * stride; + for (j = 0; j < (size_t)width; ++j) + { + // Convert rgba to argb + tmp = pix[2]; + pix[2] = pix[0]; + pix[0] = tmp; + pix += 4; + } + } + + return Py::String(str, true); } + GCAgg::GCAgg(const Py::Object &gc, double dpi) : - dpi(dpi), isaa(true), dashOffset(0.0) + dpi(dpi), isaa(true), dashOffset(0.0) { - _VERBOSE("GCAgg::GCAgg"); - linewidth = points_to_pixels ( gc.getAttr("_linewidth") ) ; - alpha = Py::Float( gc.getAttr("_alpha") ); - color = get_color(gc); - _set_antialiased(gc); - _set_linecap(gc); - _set_joinstyle(gc); - _set_dashes(gc); - _set_clip_rectangle(gc); - _set_clip_path(gc); - _set_snap(gc); - _set_hatch_path(gc); + _VERBOSE("GCAgg::GCAgg"); + linewidth = points_to_pixels(gc.getAttr("_linewidth")) ; + alpha = Py::Float(gc.getAttr("_alpha")); + color = get_color(gc); + _set_antialiased(gc); + _set_linecap(gc); + _set_joinstyle(gc); + _set_dashes(gc); + _set_clip_rectangle(gc); + _set_clip_path(gc); + _set_snap(gc); + _set_hatch_path(gc); } + void -GCAgg::_set_antialiased(const Py::Object& gc) { - _VERBOSE("GCAgg::antialiased"); - isaa = Py::Int( gc.getAttr( "_antialiased") ); +GCAgg::_set_antialiased(const Py::Object& gc) +{ + _VERBOSE("GCAgg::antialiased"); + isaa = Py::Int(gc.getAttr("_antialiased")); } + agg::rgba -GCAgg::get_color(const Py::Object& gc) { - _VERBOSE("GCAgg::get_color"); - Py::Tuple rgb = Py::Tuple( gc.getAttr("_rgb") ); +GCAgg::get_color(const Py::Object& gc) +{ + _VERBOSE("GCAgg::get_color"); + Py::Tuple rgb = Py::Tuple(gc.getAttr("_rgb")); - double alpha = Py::Float( gc.getAttr("_alpha") ); + double alpha = Py::Float(gc.getAttr("_alpha")); - double r = Py::Float(rgb[0]); - double g = Py::Float(rgb[1]); - double b = Py::Float(rgb[2]); - return agg::rgba(r, g, b, alpha); + double r = Py::Float(rgb[0]); + double g = Py::Float(rgb[1]); + double b = Py::Float(rgb[2]); + return agg::rgba(r, g, b, alpha); } + double -GCAgg::points_to_pixels( const Py::Object& points) { - _VERBOSE("GCAgg::points_to_pixels"); - double p = Py::Float( points ) ; - return p * dpi/72.0; +GCAgg::points_to_pixels(const Py::Object& points) +{ + _VERBOSE("GCAgg::points_to_pixels"); + double p = Py::Float(points) ; + return p * dpi / 72.0; } + void -GCAgg::_set_linecap(const Py::Object& gc) { - _VERBOSE("GCAgg::_set_linecap"); +GCAgg::_set_linecap(const Py::Object& gc) +{ + _VERBOSE("GCAgg::_set_linecap"); - std::string capstyle = Py::String( gc.getAttr( "_capstyle" ) ); + std::string capstyle = Py::String(gc.getAttr("_capstyle")); - if (capstyle=="butt") - cap = agg::butt_cap; - else if (capstyle=="round") - cap = agg::round_cap; - else if(capstyle=="projecting") - cap = agg::square_cap; - else - throw Py::ValueError(Printf("GC _capstyle attribute must be one of butt, round, projecting; found %s", capstyle.c_str()).str()); + if (capstyle == "butt") + { + cap = agg::butt_cap; + } + else if (capstyle == "round") + { + cap = agg::round_cap; + } + else if (capstyle == "projecting") + { + cap = agg::square_cap; + } + else + { + throw Py::ValueError(Printf("GC _capstyle attribute must be one of butt, round, projecting; found %s", capstyle.c_str()).str()); + } } + void -GCAgg::_set_joinstyle(const Py::Object& gc) { - _VERBOSE("GCAgg::_set_joinstyle"); +GCAgg::_set_joinstyle(const Py::Object& gc) +{ + _VERBOSE("GCAgg::_set_joinstyle"); - std::string joinstyle = Py::String( gc.getAttr("_joinstyle") ); + std::string joinstyle = Py::String(gc.getAttr("_joinstyle")); - if (joinstyle == "miter") - join = agg::miter_join_revert; - else if (joinstyle == "round") - join = agg::round_join; - else if (joinstyle == "bevel") - join = agg::bevel_join; - else - throw Py::ValueError(Printf("GC _joinstyle attribute must be one of butt, round, projecting; found %s", joinstyle.c_str()).str()); + if (joinstyle == "miter") + { + join = agg::miter_join_revert; + } + else if (joinstyle == "round") + { + join = agg::round_join; + } + else if (joinstyle == "bevel") + { + join = agg::bevel_join; + } + else + { + throw Py::ValueError(Printf("GC _joinstyle attribute must be one of butt, round, projecting; found %s", joinstyle.c_str()).str()); + } } + void -GCAgg::_set_dashes(const Py::Object& gc) { - //return the dashOffset, dashes sequence tuple. - _VERBOSE("GCAgg::_set_dashes"); +GCAgg::_set_dashes(const Py::Object& gc) +{ + //return the dashOffset, dashes sequence tuple. + _VERBOSE("GCAgg::_set_dashes"); - Py::Object dash_obj( gc.getAttr( "_dashes" ) ); - if (dash_obj.ptr() == Py_None) { - dashes.clear(); - return; - } + Py::Object dash_obj(gc.getAttr("_dashes")); + if (dash_obj.ptr() == Py_None) + { + dashes.clear(); + return; + } - convert_dashes(dash_obj, dpi, dashes, dashOffset); + convert_dashes(dash_obj, dpi, dashes, dashOffset); } + void -GCAgg::_set_clip_rectangle( const Py::Object& gc) { - //set the clip rectangle from the gc +GCAgg::_set_clip_rectangle(const Py::Object& gc) +{ + //set the clip rectangle from the gc - _VERBOSE("GCAgg::_set_clip_rectangle"); + _VERBOSE("GCAgg::_set_clip_rectangle"); - Py::Object o ( gc.getAttr( "_cliprect" ) ); - cliprect = o; + Py::Object o(gc.getAttr("_cliprect")); + cliprect = o; } + void -GCAgg::_set_clip_path( const Py::Object& gc) { - //set the clip path from the gc +GCAgg::_set_clip_path(const Py::Object& gc) +{ + //set the clip path from the gc - _VERBOSE("GCAgg::_set_clip_path"); + _VERBOSE("GCAgg::_set_clip_path"); - Py::Object method_obj = gc.getAttr("get_clip_path"); - Py::Callable method(method_obj); - Py::Tuple path_and_transform = method.apply(Py::Tuple()); - if (path_and_transform[0].ptr() != Py_None) { - clippath = path_and_transform[0]; - clippath_trans = py_to_agg_transformation_matrix(path_and_transform[1].ptr()); - } + Py::Object method_obj = gc.getAttr("get_clip_path"); + Py::Callable method(method_obj); + Py::Tuple path_and_transform = method.apply(Py::Tuple()); + if (path_and_transform[0].ptr() != Py_None) + { + clippath = path_and_transform[0]; + clippath_trans = py_to_agg_transformation_matrix(path_and_transform[1].ptr()); + } } + void -GCAgg::_set_snap( const Py::Object& gc) { - //set the snap setting +GCAgg::_set_snap(const Py::Object& gc) +{ + //set the snap setting - _VERBOSE("GCAgg::_set_snap"); + _VERBOSE("GCAgg::_set_snap"); - Py::Object method_obj = gc.getAttr("get_snap"); - Py::Callable method(method_obj); - Py::Object py_snap = method.apply(Py::Tuple()); - if (py_snap.isNone()) { - snap_mode = SNAP_AUTO; - } else if (py_snap.isTrue()) { - snap_mode = SNAP_TRUE; - } else { - snap_mode = SNAP_FALSE; - } + Py::Object method_obj = gc.getAttr("get_snap"); + Py::Callable method(method_obj); + Py::Object py_snap = method.apply(Py::Tuple()); + if (py_snap.isNone()) + { + snap_mode = SNAP_AUTO; + } + else if (py_snap.isTrue()) + { + snap_mode = SNAP_TRUE; + } + else + { + snap_mode = SNAP_FALSE; + } } + void -GCAgg::_set_hatch_path( const Py::Object& gc) { - _VERBOSE("GCAgg::_set_hatch_path"); +GCAgg::_set_hatch_path(const Py::Object& gc) +{ + _VERBOSE("GCAgg::_set_hatch_path"); - Py::Object method_obj = gc.getAttr("get_hatch_path"); - Py::Callable method(method_obj); - hatchpath = method.apply(Py::Tuple()); + Py::Object method_obj = gc.getAttr("get_hatch_path"); + Py::Callable method(method_obj); + hatchpath = method.apply(Py::Tuple()); } + const size_t RendererAgg::PIXELS_PER_INCH(96); + RendererAgg::RendererAgg(unsigned int width, unsigned int height, double dpi, int debug) : - width(width), - height(height), - dpi(dpi), - NUMBYTES(width*height*4), - pixBuffer(NULL), - renderingBuffer(), - alphaBuffer(NULL), - alphaMaskRenderingBuffer(), - alphaMask(alphaMaskRenderingBuffer), - pixfmtAlphaMask(alphaMaskRenderingBuffer), - rendererBaseAlphaMask(), - rendererAlphaMask(), - scanlineAlphaMask(), - slineP8(), - slineBin(), - pixFmt(), - rendererBase(), - rendererAA(), - rendererBin(), - theRasterizer(), - debug(debug) + width(width), + height(height), + dpi(dpi), + NUMBYTES(width*height*4), + pixBuffer(NULL), + renderingBuffer(), + alphaBuffer(NULL), + alphaMaskRenderingBuffer(), + alphaMask(alphaMaskRenderingBuffer), + pixfmtAlphaMask(alphaMaskRenderingBuffer), + rendererBaseAlphaMask(), + rendererAlphaMask(), + scanlineAlphaMask(), + slineP8(), + slineBin(), + pixFmt(), + rendererBase(), + rendererAA(), + rendererBin(), + theRasterizer(), + debug(debug) { - _VERBOSE("RendererAgg::RendererAgg"); - unsigned stride(width*4); + _VERBOSE("RendererAgg::RendererAgg"); + unsigned stride(width*4); - pixBuffer = new agg::int8u[NUMBYTES]; - renderingBuffer.attach(pixBuffer, width, height, stride); - pixFmt.attach(renderingBuffer); - rendererBase.attach(pixFmt); - rendererBase.clear(agg::rgba(1, 1, 1, 0)); - rendererAA.attach(rendererBase); - rendererBin.attach(rendererBase); - hatchRenderingBuffer.attach(hatchBuffer, HATCH_SIZE, HATCH_SIZE, HATCH_SIZE*4); + pixBuffer = new agg::int8u[NUMBYTES]; + renderingBuffer.attach(pixBuffer, width, height, stride); + pixFmt.attach(renderingBuffer); + rendererBase.attach(pixFmt); + rendererBase.clear(agg::rgba(1, 1, 1, 0)); + rendererAA.attach(rendererBase); + rendererBin.attach(rendererBase); + hatchRenderingBuffer.attach(hatchBuffer, HATCH_SIZE, HATCH_SIZE, + HATCH_SIZE*4); } -void RendererAgg::create_alpha_buffers() { - if (!alphaBuffer) { - unsigned stride(width*4); - alphaBuffer = new agg::int8u[NUMBYTES]; - alphaMaskRenderingBuffer.attach(alphaBuffer, width, height, stride); - rendererBaseAlphaMask.attach(pixfmtAlphaMask); - rendererAlphaMask.attach(rendererBaseAlphaMask); - } + +void +RendererAgg::create_alpha_buffers() +{ + if (!alphaBuffer) + { + unsigned stride(width*4); + alphaBuffer = new agg::int8u[NUMBYTES]; + alphaMaskRenderingBuffer.attach(alphaBuffer, width, height, stride); + rendererBaseAlphaMask.attach(pixfmtAlphaMask); + rendererAlphaMask.attach(rendererBaseAlphaMask); + } } + template<class R> void -RendererAgg::set_clipbox(const Py::Object& cliprect, R& rasterizer) { - //set the clip rectangle from the gc +RendererAgg::set_clipbox(const Py::Object& cliprect, R& rasterizer) +{ + //set the clip rectangle from the gc - _VERBOSE("RendererAgg::set_clipbox"); + _VERBOSE("RendererAgg::set_clipbox"); - double l, b, r, t; - if (py_convert_bbox(cliprect.ptr(), l, b, r, t)) { - rasterizer.clip_box(int(mpl_round(l)), height - int(mpl_round(b)), - int(mpl_round(r)), height - int(mpl_round(t))); - } + double l, b, r, t; + if (py_convert_bbox(cliprect.ptr(), l, b, r, t)) + { + rasterizer.clip_box(int(mpl_round(l)), height - int(mpl_round(b)), + int(mpl_round(r)), height - int(mpl_round(t))); + } - _VERBOSE("RendererAgg::set_clipbox done"); + _VERBOSE("RendererAgg::set_clipbox done"); } + std::pair<bool, agg::rgba> -RendererAgg::_get_rgba_face(const Py::Object& rgbFace, double alpha) { - _VERBOSE("RendererAgg::_get_rgba_face"); - std::pair<bool, agg::rgba> face; +RendererAgg::_get_rgba_face(const Py::Object& rgbFace, double alpha) +{ + _VERBOSE("RendererAgg::_get_rgba_face"); + std::pair<bool, agg::rgba> face; - if (rgbFace.ptr() == Py_None) { - face.first = false; - } - else { - face.first = true; - Py::Tuple rgb = Py::Tuple(rgbFace); - face.second = rgb_to_color(rgb, alpha); - } - return face; + if (rgbFace.ptr() == Py_None) + { + face.first = false; + } + else + { + face.first = true; + Py::Tuple rgb = Py::Tuple(rgbFace); + face.second = rgb_to_color(rgb, alpha); + } + return face; } + Py::Object -RendererAgg::copy_from_bbox(const Py::Tuple& args) { - //copy region in bbox to buffer and return swig/agg buffer object - args.verify_length(1); +RendererAgg::copy_from_bbox(const Py::Tuple& args) +{ + //copy region in bbox to buffer and return swig/agg buffer object + args.verify_length(1); - Py::Object box_obj = args[0]; - double 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"); + Py::Object box_obj = args[0]; + double 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"); + } - // std::cout << l << " " << b << " " << r << " " << t << " " << (height - (int)b) << " " << height - (int)t << std::endl; - agg::rect_i rect((int)l, height - (int)t, (int)r, height - (int)b); + agg::rect_i rect((int)l, height - (int)t, (int)r, height - (int)b); - BufferRegion* reg = NULL; - try { - reg = new BufferRegion(rect, true); - } catch (...) { - throw Py::MemoryError("RendererAgg::copy_from_bbox could not allocate memory for buffer"); - } + BufferRegion* reg = NULL; + try + { + reg = new BufferRegion(rect, true); + } + catch (...) + { + throw Py::MemoryError( + "RendererAgg::copy_from_bbox could not allocate memory for buffer"); + } - if (!reg) { - throw Py::MemoryError("RendererAgg::copy_from_bbox could not allocate memory for buffer"); - } + if (!reg) + { + throw Py::MemoryError( + "RendererAgg::copy_from_bbox could not allocate memory for buffer"); + } - try { - agg::rendering_buffer rbuf; - rbuf.attach(reg->data, reg->width, reg->height, reg->stride); + try + { + agg::rendering_buffer rbuf; + rbuf.attach(reg->data, reg->width, reg->height, reg->stride); - pixfmt pf(rbuf); - renderer_base rb(pf); - rb.copy_from(renderingBuffer, &rect, -rect.x1, -rect.y1); - } catch (...) { - delete reg; - throw Py::RuntimeError("An unknown error occurred in copy_from_bbox"); - } - return Py::asObject(reg); + pixfmt pf(rbuf); + renderer_base rb(pf); + rb.copy_from(renderingBuffer, &rect, -rect.x1, -rect.y1); + } + catch (...) + { + delete reg; + throw Py::RuntimeError("An unknown error occurred in copy_from_bbox"); + } + return Py::asObject(reg); } + Py::Object -RendererAgg::restore_region(const Py::Tuple& args) { - //copy BufferRegion to buffer - args.verify_length(1); - BufferRegion* region = static_cast<BufferRegion*>(args[0].ptr()); +RendererAgg::restore_region(const Py::Tuple& args) +{ + //copy BufferRegion to buffer + args.verify_length(1); + BufferRegion* region = static_cast<BufferRegion*>(args[0].ptr()); - if (region->data==NULL) - throw Py::ValueError("Cannot restore_region from NULL data"); - //return Py::Object(); + if (region->data == NULL) + { + throw Py::ValueError("Cannot restore_region from NULL data"); + } - //std::cout << "restoring " << region->width << " " << region->height << " " << region->stride << " " << region->rect.x1 << " " << region->rect.y1 << std::endl; + agg::rendering_buffer rbuf; + rbuf.attach(region->data, + region->width, + region->height, + region->stride); - agg::rendering_buffer rbuf; - rbuf.attach(region->data, - region->width, - region->height, - region->stride); + rendererBase.copy_from(rbuf, 0, region->rect.x1, region->rect.y1); - rendererBase.copy_from(rbuf, 0, region->rect.x1, region->rect.y1); - - return Py::Object(); + return Py::Object(); } + // Restore the part of the saved region with offsets Py::Object -RendererAgg::restore_region2(const Py::Tuple& args) { - //copy BufferRegion to buffer - args.verify_length(7); +RendererAgg::restore_region2(const Py::Tuple& args) +{ + //copy BufferRegion to buffer + args.verify_length(7); + int x(0), y(0), xx1(0), yy1(0), xx2(0), yy2(0); + try + { + xx1 = Py::Int(args[1]); + yy1 = Py::Int(args[2]); + xx2 = Py::Int(args[3]); + yy2 = Py::Int(args[4]); + x = Py::Int(args[5]); + y = Py::Int(args[6]); + } + catch (Py::TypeError) + { + throw Py::TypeError("Invalid input arguments to draw_text_image"); + } - int x(0),y(0), xx1(0),yy1(0), xx2(0), yy2(0); - try { - xx1 = Py::Int( args[1] ); - yy1 = Py::Int( args[2] ); - xx2 = Py::Int( args[3] ); - yy2 = Py::Int( args[4] ); - x = Py::Int( args[5] ); - y = Py::Int( args[6] ); - } - catch (Py::TypeError) { - throw Py::TypeError("Invalid input arguments to draw_text_image"); - } + BufferRegion* region = static_cast<BufferRegion*>(args[0].ptr()); + if (region->data == NULL) + { + throw Py::ValueError("Cannot restore_region from NULL data"); + } - BufferRegion* region = static_cast<BufferRegion*>(args[0].ptr()); + agg::rect_i rect(xx1 - region->rect.x1, (yy1 - region->rect.y1), + xx2 - region->rect.x1, (yy2 - region->rect.y1)); - if (region->data==NULL) - throw Py::ValueError("Cannot restore_region from NULL data"); + agg::rendering_buffer rbuf; + rbuf.attach(region->data, + region->width, + region->height, + region->stride); - agg::rect_i rect(xx1-region->rect.x1, (yy1-region->rect.y1), - xx2-region->rect.x1, (yy2-region->rect.y1)); + rendererBase.copy_from(rbuf, &rect, x, y); - - agg::rendering_buffer rbuf; - rbuf.attach(region->data, - region->width, - region->height, - region->stride); - - rendererBase.copy_from(rbuf, &rect, x, y); - - return Py::Object(); + return Py::Object(); } -bool RendererAgg::render_clippath(const Py::Object& clippath, const agg::trans_affine& clippath_trans) { - typedef agg::conv_transform<PathIterator> transformed_path_t; - typedef agg::conv_curve<transformed_path_t> curve_t; +bool +RendererAgg::render_clippath(const Py::Object& clippath, + const agg::trans_affine& clippath_trans) +{ + typedef agg::conv_transform<PathIterator> transformed_path_t; + typedef agg::conv_curve<transformed_path_t> curve_t; - bool has_clippath = (clippath.ptr() != Py_None); + bool has_clippath = (clippath.ptr() != Py_None); - 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); + 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); - PathIterator clippath_iter(clippath); - rendererBaseAlphaMask.clear(agg::gray8(0, 0)); - transformed_path_t transformed_clippath(clippath_iter, trans); - agg::conv_curve<transformed_path_t> curved_clippath(transformed_clippath); - theRasterizer.add_path(curved_clippath); - rendererAlphaMask.color(agg::gray8(255, 255)); - agg::render_scanlines(theRasterizer, scanlineAlphaMask, rendererAlphaMask); - lastclippath = clippath; - lastclippath_transform = clippath_trans; - } + PathIterator clippath_iter(clippath); + rendererBaseAlphaMask.clear(agg::gray8(0, 0)); + transformed_path_t transformed_clippath(clippath_iter, trans); + agg::conv_curve<transformed_path_t> curved_clippath(transformed_clippath); + theRasterizer.add_path(curved_clippath); + rendererAlphaMask.color(agg::gray8(255, 255)); + agg::render_scanlines(theRasterizer, scanlineAlphaMask, rendererAlphaMask); + lastclippath = clippath; + lastclippath_transform = clippath_trans; + } - return has_clippath; + return has_clippath; } #define MARKER_CACHE_SIZE 512 + Py::Object -RendererAgg::draw_markers(const Py::Tuple& args) { - typedef agg::conv_transform<PathIterator> transformed_path_t; - typedef PathSnapper<transformed_path_t> snap_t; - typedef agg::conv_curve<snap_t> curve_t; - typedef agg::conv_stroke<curve_t> stroke_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; - args.verify_length(5, 6); +RendererAgg::draw_markers(const Py::Tuple& args) +{ + typedef agg::conv_transform<PathIterator> transformed_path_t; + typedef PathSnapper<transformed_path_t> snap_t; + typedef agg::conv_curve<snap_t> curve_t; + typedef agg::conv_stroke<curve_t> stroke_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; + args.verify_length(5, 6); - Py::Object gc_obj = args[0]; - Py::Object marker_path_obj = args[1]; - agg::trans_affine marker_trans = py_to_agg_transformation_matrix(args[2].ptr()); - Py::Object path_obj = args[3]; - agg::trans_affine trans = py_to_agg_transformation_matrix(args[4].ptr()); - Py::Object face_obj; - if (args.size() == 6) - face_obj = args[5]; + Py::Object gc_obj = args[0]; + Py::Object marker_path_obj = args[1]; + agg::trans_affine marker_trans = py_to_agg_transformation_matrix(args[2].ptr()); + Py::Object path_obj = args[3]; + agg::trans_affine trans = py_to_agg_transformation_matrix(args[4].ptr()); + Py::Object face_obj; + if (args.size() == 6) + { + face_obj = args[5]; + } - GCAgg gc(gc_obj, dpi); + GCAgg gc(gc_obj, dpi); - // Deal with the difference in y-axis direction - marker_trans *= agg::trans_affine_scaling(1.0, -1.0); - trans *= agg::trans_affine_scaling(1.0, -1.0); - trans *= agg::trans_affine_translation(0.0, (double)height); + // Deal with the difference in y-axis direction + marker_trans *= agg::trans_affine_scaling(1.0, -1.0); + trans *= agg::trans_affine_scaling(1.0, -1.0); + trans *= agg::trans_affine_translation(0.0, (double)height); - PathIterator marker_path(marker_path_obj); - transformed_path_t marker_path_transformed(marker_path, marker_trans); - snap_t marker_path_snapped(marker_path_transformed, - gc.snap_mode, - marker_path.total_vertices(), - gc.linewidth); - curve_t marker_path_curve(marker_path_snapped); + PathIterator marker_path(marker_path_obj); + transformed_path_t marker_path_transformed(marker_path, marker_trans); + snap_t marker_path_snapped(marker_path_transformed, + gc.snap_mode, + marker_path.total_vertices(), + gc.linewidth); + curve_t marker_path_curve(marker_path_snapped); - PathIterator path(path_obj); - transformed_path_t path_transformed(path, trans); - snap_t path_snapped(path_transformed, - gc.snap_mode, - path.total_vertices(), - 1.0); - curve_t path_curve(path_snapped); - path_curve.rewind(0); + PathIterator path(path_obj); + transformed_path_t path_transformed(path, trans); + snap_t path_snapped(path_transformed, + gc.snap_mode, + path.total_vertices(), + 1.0); + curve_t path_curve(path_snapped); + path_curve.rewind(0); - facepair_t face = _get_rgba_face(face_obj, gc.alpha); + facepair_t face = _get_rgba_face(face_obj, gc.alpha); - //maxim's suggestions for cached scanlines - agg::scanline_storage_aa8 scanlines; - theRasterizer.reset(); - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); + //maxim's suggestions for cached scanlines + agg::scanline_storage_aa8 scanlines; + theRasterizer.reset(); + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); - agg::int8u staticFillCache[MARKER_CACHE_SIZE]; - agg::int8u staticStrokeCache[MARKER_CACHE_SIZE]; - agg::int8u* fillCache = staticFillCache; - agg::int8u* strokeCache = staticStrokeCache; + agg::int8u staticFillCache[MARKER_CACHE_SIZE]; + agg::int8u staticStrokeCache[MARKER_CACHE_SIZE]; + agg::int8u* fillCache = staticFillCache; + agg::int8u* strokeCache = staticStrokeCache; - try { - unsigned fillSize = 0; - if (face.first) { - theRasterizer.add_path(marker_path_curve); - agg::render_scanlines(theRasterizer, slineP8, scanlines); - fillSize = scanlines.byte_size(); - if (fillSize >= MARKER_CACHE_SIZE) - fillCache = new agg::int8u[fillSize]; - scanlines.serialize(fillCache); - } + try + { + unsigned fillSize = 0; + if (face.first) + { + theRasterizer.add_path(marker_path_curve); + agg::render_scanlines(theRasterizer, slineP8, scanlines); + fillSize = scanlines.byte_size(); + if (fillSize >= MARKER_CACHE_SIZE) + { + fillCache = new agg::int8u[fillSize]; + } + scanlines.serialize(fillCache); + } - stroke_t stroke(marker_path_curve); - stroke.width(gc.linewidth); - stroke.line_cap(gc.cap); - stroke.line_join(gc.join); - theRasterizer.reset(); - theRasterizer.add_path(stroke); - agg::render_scanlines(theRasterizer, slineP8, scanlines); - unsigned strokeSize = scanlines.byte_size(); - if (strokeSize >= MARKER_CACHE_SIZE) - strokeCache = new agg::int8u[strokeSize]; - scanlines.serialize(strokeCache); + stroke_t stroke(marker_path_curve); + stroke.width(gc.linewidth); + stroke.line_cap(gc.cap); + stroke.line_join(gc.join); + theRasterizer.reset(); + theRasterizer.add_path(stroke); + agg::render_scanlines(theRasterizer, slineP8, scanlines); + unsigned strokeSize = scanlines.byte_size(); + if (strokeSize >= MARKER_CACHE_SIZE) + { + strokeCache = new agg::int8u[strokeSize]; + } + scanlines.serialize(strokeCache); - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - set_clipbox(gc.cliprect, rendererBase); - bool has_clippath = render_clippath(gc.clippath, gc.clippath_trans); + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); + set_clipbox(gc.cliprect, rendererBase); + bool has_clippath = render_clippath(gc.clippath, gc.clippath_trans); - double x, y; + double x, y; - agg::serialized_scanlines_adaptor_aa8 sa; - agg::serialized_scanlines_adaptor_aa8::embedded_scanline sl; + agg::serialized_scanlines_adaptor_aa8 sa; + agg::serialized_scanlines_adaptor_aa8::embedded_scanline sl; - agg::rect_d clipping_rect( - -(scanlines.min_x() + 1.0), - -(scanlines.min_y() + 1.0), - width + scanlines.max_x() + 1.0, - height + scanlines.max_y() + 1.0); + agg::rect_d clipping_rect( + -(scanlines.min_x() + 1.0), + -(scanlines.min_y() + 1.0), + width + scanlines.max_x() + 1.0, + height + scanlines.max_y() + 1.0); - if (has_clippath) { - while (path_curve.vertex(&x, &y) != agg::path_cmd_stop) { - if (MPL_notisfinite64(x) || MPL_notisfinite64(y)) { - continue; - } + if (has_clippath) + { + while (path_curve.vertex(&x, &y) != agg::path_cmd_stop) + { + if (MPL_notisfinite64(x) || MPL_notisfinite64(y)) + { + continue; + } - x = (double)(int)x; y = (double)(int)y; + x = (double)(int)x; + y = (double)(int)y; - // Cull points outside the boundary of the image. Values - // that are too large may overflow and create segfaults. - // because they can create segfaults of they overflow; eg - // http://sourceforge.net/tracker/?func=detail&aid=2865490&group_id=80706&atid=560720 - if (!clipping_rect.hit_test(x, y)) { - continue; - } + // Cull points outside the boundary of the image. + // Values that are too large may overflow and create + // segfaults. + // http://sourceforge.net/tracker/?func=detail&aid=2865490&group_id=80706&atid=560720 + if (!clipping_rect.hit_test(x, y)) + { + continue; + } - pixfmt_amask_type pfa(pixFmt, alphaMask); - amask_ren_type r(pfa); - amask_aa_renderer_type ren(r); + pixfmt_amask_type pfa(pixFmt, alphaMask); + amask_ren_type r(pfa); + amask_aa_renderer_type ren(r); - if (face.first) { - ren.color(face.second); - sa.init(fillCache, fillSize, x, y); - agg::render_scanlines(sa, sl, ren); + if (face.first) + { + ren.color(face.second); + sa.init(fillCache, fillSize, x, y); + agg::render_scanlines(sa, sl, ren); + } + ren.color(gc.color); + sa.init(strokeCache, strokeSize, x, y); + agg::render_scanlines(sa, sl, ren); + } } - ren.color(gc.color); - sa.init(strokeCache, strokeSize, x, y); - agg::render_scanlines(sa, sl, ren); - } - } else { - while (path_curve.vertex(&x, &y) != agg::path_cmd_stop) { - if (MPL_notisfinite64(x) || MPL_notisfinite64(y)) { - continue; - } + else + { + while (path_curve.vertex(&x, &y) != agg::path_cmd_stop) + { + if (MPL_notisfinite64(x) || MPL_notisfinite64(y)) + { + continue; + } - x = (double)(int)x; y = (double)(int)y; + x = (double)(int)x; + y = (double)(int)y; - // Cull points outside the boundary of the image. Values - // that are too large may overflow and create segfaults. - // because they can create segfaults of they overflow; eg - // http://sourceforge.net/tracker/?func=detail&aid=2865490&group_id=80706&atid=560720 - if (!clipping_rect.hit_test(x, y)) { - continue; - } + // Cull points outside the boundary of the image. + // Values that are too large may overflow and create + // segfaults. + // http://sourceforge.net/tracker/?func=detail&aid=2865490&group_id=80706&atid=560720 + if (!clipping_rect.hit_test(x, y)) + { + continue; + } - if (face.first) { - rendererAA.color(face.second); - sa.init(fillCache, fillSize, x, y); - agg::render_scanlines(sa, sl, rendererAA); + if (face.first) + { + rendererAA.color(face.second); + sa.init(fillCache, fillSize, x, y); + agg::render_scanlines(sa, sl, rendererAA); + } + + rendererAA.color(gc.color); + sa.init(strokeCache, strokeSize, x, y); + agg::render_scanlines(sa, sl, rendererAA); + } } + } + catch (...) + { + if (fillCache != staticFillCache) + delete[] fillCache; + if (strokeCache != staticStrokeCache) + delete[] strokeCache; + throw; + } - rendererAA.color(gc.color); - sa.init(strokeCache, strokeSize, x, y); - agg::render_scanlines(sa, sl, rendererAA); - } - } - } catch(...) { if (fillCache != staticFillCache) - delete[] fillCache; + delete[] fillCache; if (strokeCache != staticStrokeCache) - delete[] strokeCache; - throw; - } + delete[] strokeCache; - if (fillCache != staticFillCache) - delete[] fillCache; - if (strokeCache != staticStrokeCache) - delete[] strokeCache; - - return Py::Object(); + return Py::Object(); } + /** * This is a custom span generator that converts spans in the * 8-bit inverted greyscale font buffer to rgba that agg can use. @@ -680,1380 +816,1626 @@ class font_to_rgba { public: - typedef ChildGenerator child_type; - typedef agg::rgba8 color_type; - typedef typename child_type::color_type child_color_type; - typedef agg::span_allocator<child_color_type> span_alloc_type; + typedef ChildGenerator child_type; + typedef agg::rgba8 color_type; + typedef typename child_type::color_type child_color_type; + typedef agg::span_allocator<child_color_type> span_alloc_type; private: - child_type* _gen; - color_type _color; - span_alloc_type _allocator; + child_type* _gen; + color_type _color; + span_alloc_type _allocator; public: - font_to_rgba(child_type* gen, color_type color) : - _gen(gen), - _color(color) { - } + font_to_rgba(child_type* gen, color_type color) : + _gen(gen), + _color(color) + { - inline void generate(color_type* output_span, int x, int y, unsigned len) - { - _allocator.allocate(len); - child_color_type* input_span = _allocator.span(); - _gen->generate(input_span, x, y, len); + } - do { - *output_span = _color; - output_span->a = ((unsigned int)_color.a * (unsigned int)input_span->v) >> 8; - ++output_span; - ++input_span; - } while (--len); - } + inline void + generate(color_type* output_span, int x, int y, unsigned len) + { + _allocator.allocate(len); + child_color_type* input_span = _allocator.span(); + _gen->generate(input_span, x, y, len); - void prepare() - { - _gen->prepare(); - } + do + { + *output_span = _color; + output_span->a = ((unsigned int)_color.a * + (unsigned int)input_span->v) >> 8; + ++output_span; + ++input_span; + } + while (--len); + } + void + prepare() + { + _gen->prepare(); + } }; + // MGDTODO: Support clip paths Py::Object -RendererAgg::draw_text_image(const Py::Tuple& args) { - _VERBOSE("RendererAgg::draw_text"); +RendererAgg::draw_text_image(const Py::Tuple& args) +{ + _VERBOSE("RendererAgg::draw_text"); - typedef agg::span_allocator<agg::gray8> gray_span_alloc_type; - typedef agg::span_allocator<agg::rgba8> color_span_alloc_type; - typedef agg::span_interpolator_linear<> interpolator_type; - typedef agg::image_accessor_clip<agg::pixfmt_gray8> image_accessor_type; - //typedef agg::span_image_filter_gray_2x2<image_accessor_type, interpolator_type> - // image_span_gen_type; - typedef agg::span_image_filter_gray<image_accessor_type, interpolator_type> - image_span_gen_type; + typedef agg::span_allocator<agg::gray8> gray_span_alloc_type; + typedef agg::span_allocator<agg::rgba8> color_span_alloc_type; + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::image_accessor_clip<agg::pixfmt_gray8> image_accessor_type; + typedef agg::span_image_filter_gray<image_accessor_type, + interpolator_type> image_span_gen_type; + typedef font_to_rgba<image_span_gen_type> span_gen_type; + typedef agg::renderer_scanline_aa<renderer_base, color_span_alloc_type, + span_gen_type> renderer_type; - typedef font_to_rgba<image_span_gen_type> span_gen_type; - typedef agg::renderer_scanline_aa<renderer_base, color_span_alloc_type, span_gen_type> - renderer_type; + args.verify_length(5); - args.verify_length(5); + const unsigned char* buffer = NULL; + int width, height; + Py::Object image_obj = args[0]; + PyArrayObject* image_array = NULL; - const unsigned char* buffer = NULL; - int width, height; - Py::Object image_obj = args[0]; - PyArrayObject* image_array = NULL; - if (PyArray_Check(image_obj.ptr())) { - image_array = (PyArrayObject*)PyArray_FromObject(image_obj.ptr(), PyArray_UBYTE, 2, 2); - if (!image_array) - throw Py::ValueError("First argument to draw_text_image must be a FT2Font.Image object or a Nx2 uint8 numpy array."); - buffer = (unsigned char *)PyArray_DATA(image_array); - width = PyArray_DIM(image_array, 1); - height = PyArray_DIM(image_array, 0); - } else { - FT2Image *image = static_cast<FT2Image*>(args[0].ptr()); - if (!image->get_buffer()) - throw Py::ValueError("First argument to draw_text_image must be a FT2Font.Image object or a Nx2 uint8 numpy array."); - buffer = image->get_buffer(); - width = image->get_width(); - height = image->get_height(); - } + if (PyArray_Check(image_obj.ptr())) + { + image_array = (PyArrayObject*)PyArray_FromObject(image_obj.ptr(), PyArray_UBYTE, 2, 2); + if (!image_array) + { + throw Py::ValueError( + "First argument to draw_text_image must be a FT2Font.Image object or a Nx2 uint8 numpy array."); + } + buffer = (unsigned char *)PyArray_DATA(image_array); + width = PyArray_DIM(image_array, 1); + height = PyArray_DIM(image_array, 0); + } + else + { + FT2Image *image = static_cast<FT2Image*>(args[0].ptr()); + if (!image->get_buffer()) + { + throw Py::ValueError( + "First argument to draw_text_image must be a FT2Font.Image object or a Nx2 uint8 numpy array."); + } + buffer = image->get_buffer(); + width = image->get_width(); + height = image->get_height(); + } - int x(0),y(0); - try { - x = Py::Int( args[1] ); - y = Py::Int( args[2] ); - } - catch (Py::TypeError) { - Py_XDECREF(image_array); - throw Py::TypeError("Invalid input arguments to draw_text_image"); - } + int x(0), y(0); + try + { + x = Py::Int(args[1]); + y = Py::Int(args[2]); + } + catch (Py::TypeError) + { + Py_XDECREF(image_array); + throw Py::TypeError("Invalid input arguments to draw_text_image"); + } - double angle = Py::Float( args[3] ); + double angle = Py::Float(args[3]); - GCAgg gc(args[4], dpi); + GCAgg gc(args[4], dpi); - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - set_clipbox(gc.cliprect, theRasterizer); + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); + set_clipbox(gc.cliprect, theRasterizer); - agg::rendering_buffer srcbuf((agg::int8u*)buffer, width, height, width); - agg::pixfmt_gray8 pixf_img(srcbuf); + agg::rendering_buffer srcbuf((agg::int8u*)buffer, width, height, width); + agg::pixfmt_gray8 pixf_img(srcbuf); - agg::trans_affine mtx; - mtx *= agg::trans_affine_translation(0, -height); - mtx *= agg::trans_affine_rotation(-angle * agg::pi / 180.0); - mtx *= agg::trans_affine_translation(x, y); + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(0, -height); + mtx *= agg::trans_affine_rotation(-angle * agg::pi / 180.0); + mtx *= agg::trans_affine_translation(x, y); - agg::path_storage rect; - rect.move_to(0, 0); - rect.line_to(width, 0); - rect.line_to(width, height); - rect.line_to(0, height); - rect.line_to(0, 0); - agg::conv_transform<agg::path_storage> rect2(rect, mtx); + agg::path_storage rect; + rect.move_to(0, 0); + rect.line_to(width, 0); + rect.line_to(width, height); + rect.line_to(0, height); + rect.line_to(0, 0); + agg::conv_transform<agg::path_storage> rect2(rect, mtx); - agg::trans_affine inv_mtx(mtx); - inv_mtx.invert(); + agg::trans_affine inv_mtx(mtx); + inv_mtx.invert(); - agg::image_filter_lut filter; - filter.calculate(agg::image_filter_spline36()); - interpolator_type interpolator(inv_mtx); - color_span_alloc_type sa; - image_accessor_type ia(pixf_img, 0); - image_span_gen_type image_span_generator(ia, interpolator, filter); - span_gen_type output_span_generator(&image_span_generator, gc.color); - renderer_type ri(rendererBase, sa, output_span_generator); + agg::image_filter_lut filter; + filter.calculate(agg::image_filter_spline36()); + interpolator_type interpolator(inv_mtx); + color_span_alloc_type sa; + image_accessor_type ia(pixf_img, 0); + image_span_gen_type image_span_generator(ia, interpolator, filter); + span_gen_type output_span_generator(&image_span_generator, gc.color); + renderer_type ri(rendererBase, sa, output_span_generator); - theRasterizer.add_path(rect2); - agg::render_scanlines(theRasterizer, slineP8, ri); + theRasterizer.add_path(rect2); + agg::render_scanlines(theRasterizer, slineP8, ri); - Py_XDECREF(image_array); + Py_XDECREF(image_array); - return Py::Object(); + return Py::Object(); } Py::Object -RendererAgg::draw_image(const Py::Tuple& args) { - _VERBOSE("RendererAgg::draw_image"); +RendererAgg::draw_image(const Py::Tuple& args) +{ + _VERBOSE("RendererAgg::draw_image"); - args.verify_length(4, 7); // 7 if affine matrix if given + args.verify_length(4, 7); // 7 if affine matrix if given - GCAgg gc(args[0], dpi); - Image *image = static_cast<Image*>(args[3].ptr()); - bool has_clippath = false; - agg::trans_affine affine_trans; - bool has_affine = false; - double x, y, w, h; + GCAgg gc(args[0], dpi); + Image *image = static_cast<Image*>(args[3].ptr()); + bool has_clippath = false; + agg::trans_affine affine_trans; + bool has_affine = false; + double x, y, w, h; - - if (args.size() == 7) { - has_affine = true; - x = Py::Float(args[1]); - y = Py::Float(args[2]); - w = Py::Float(args[4]); - h = Py::Float(args[5]); - affine_trans = py_to_agg_transformation_matrix(args[6].ptr()); - } else { - x = mpl_round(Py::Float(args[1])); - y = mpl_round(Py::Float(args[2])); - w = h = 0; /* w and h not used in this case, but assign to prevent + if (args.size() == 7) + { + has_affine = true; + x = Py::Float(args[1]); + y = Py::Float(args[2]); + w = Py::Float(args[4]); + h = Py::Float(args[5]); + affine_trans = py_to_agg_transformation_matrix(args[6].ptr()); + } + else + { + x = mpl_round(Py::Float(args[1])); + y = mpl_round(Py::Float(args[2])); + w = h = 0; /* w and h not used in this case, but assign to prevent warnings from the compiler */ - } + } + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); + set_clipbox(gc.cliprect, theRasterizer); + has_clippath = render_clippath(gc.clippath, gc.clippath_trans); - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - set_clipbox(gc.cliprect, theRasterizer); - has_clippath = render_clippath(gc.clippath, gc.clippath_trans); + Py::Tuple empty; + image->flipud_out(empty); + pixfmt pixf(*(image->rbufOut)); - Py::Tuple empty; - image->flipud_out(empty); - pixfmt pixf(*(image->rbufOut)); + if (has_affine | has_clippath) + { + agg::trans_affine mtx; + agg::path_storage rect; - if (has_affine | has_clippath) { - agg::trans_affine mtx; - agg::path_storage rect; + if (has_affine) + { + mtx *= agg::trans_affine_scaling(1, -1); + mtx *= agg::trans_affine_translation(0, image->rowsOut); + mtx *= agg::trans_affine_scaling(w / (image->colsOut), + h / (image->rowsOut)); + mtx *= agg::trans_affine_translation(x, y); + mtx *= affine_trans; + mtx *= agg::trans_affine_scaling(1.0, -1.0); + mtx *= agg::trans_affine_translation(0.0, (double) height); + } + else + { + mtx *= agg::trans_affine_translation( + (int)x, + (int)(height - (y + image->rowsOut))); + } - if (has_affine) { - mtx *= agg::trans_affine_scaling(1, -1); - mtx *= agg::trans_affine_translation(0, image->rowsOut); - mtx *= agg::trans_affine_scaling(w/(image->colsOut), h/(image->rowsOut)); - mtx *= agg::trans_affine_translation(x, y); - mtx *= affine_trans; - mtx *= agg::trans_affine_scaling(1.0, -1.0); - mtx *= agg::trans_affine_translation(0.0, (double) height); - } else { - mtx *= agg::trans_affine_translation((int)x, (int)(height-(y+image->rowsOut))); - } + rect.move_to(0, 0); + rect.line_to(image->colsOut, 0); + rect.line_to(image->colsOut, image->rowsOut); + rect.line_to(0, image->rowsOut); + rect.line_to(0, 0); - rect.move_to(0, 0); - rect.line_to(image->colsOut, 0); - rect.line_to(image->colsOut, image->rowsOut); - rect.line_to(0, image->rowsOut); - rect.line_to(0, 0); + agg::conv_transform<agg::path_storage> rect2(rect, mtx); - agg::conv_transform<agg::path_storage> rect2(rect, mtx); + agg::trans_affine inv_mtx(mtx); + inv_mtx.invert(); - agg::trans_affine inv_mtx(mtx); - inv_mtx.invert(); + typedef agg::span_allocator<agg::rgba8> color_span_alloc_type; + typedef agg::image_accessor_clip<agg::pixfmt_rgba32> + image_accessor_type; + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::span_image_filter_rgba_nn<image_accessor_type, + interpolator_type> image_span_gen_type; + color_span_alloc_type sa; + image_accessor_type ia(pixf, agg::rgba8(0, 0, 0, 0)); + interpolator_type interpolator(inv_mtx); + image_span_gen_type image_span_generator(ia, interpolator); - typedef agg::span_allocator<agg::rgba8> color_span_alloc_type; - typedef agg::image_accessor_clip<agg::pixfmt_rgba32> image_accessor_type; - typedef agg::span_interpolator_linear<> interpolator_type; - typedef agg::span_image_filter_rgba_nn<image_accessor_type, interpolator_type> image_span_gen_type; + if (has_clippath) + { + 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<amask_ren_type, + color_span_alloc_type, + image_span_gen_type> + renderer_type_alpha; + pixfmt_amask_type pfa(pixFmt, alphaMask); + amask_ren_type r(pfa); + renderer_type_alpha ri(r, sa, image_span_generator); - color_span_alloc_type sa; - image_accessor_type ia(pixf, agg::rgba8(0, 0, 0, 0)); - interpolator_type interpolator(inv_mtx); - image_span_gen_type image_span_generator(ia, interpolator); + theRasterizer.add_path(rect2); + agg::render_scanlines(theRasterizer, slineP8, ri); + } + else + { + typedef agg::renderer_base<pixfmt> ren_type; + typedef agg::renderer_scanline_aa<ren_type, + color_span_alloc_type, + image_span_gen_type> + renderer_type; + ren_type r(pixFmt); + renderer_type ri(r, sa, image_span_generator); - if (has_clippath) { - 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<amask_ren_type, color_span_alloc_type, image_span_gen_type> renderer_type_alpha; + theRasterizer.add_path(rect2); + agg::render_scanlines(theRasterizer, slineP8, ri); + } - pixfmt_amask_type pfa(pixFmt, alphaMask); - amask_ren_type r(pfa); - renderer_type_alpha ri(r, sa, image_span_generator); - - theRasterizer.add_path(rect2); - agg::render_scanlines(theRasterizer, slineP8, ri); - } else { - typedef agg::renderer_base<pixfmt> ren_type; - typedef agg::renderer_scanline_aa<ren_type, color_span_alloc_type, image_span_gen_type> renderer_type; - ren_type r(pixFmt); - renderer_type ri(r, sa, image_span_generator); - - theRasterizer.add_path(rect2); - agg::render_scanlines(theRasterizer, slineP8, ri); } + else + { + set_clipbox(gc.cliprect, rendererBase); + rendererBase.blend_from(pixf, 0, (int)x, (int)(height - (y + image->rowsOut))); + } - } else { - set_clipbox(gc.cliprect, rendererBase); - rendererBase.blend_from(pixf, 0, (int)x, (int)(height-(y+image->rowsOut))); - } + image->flipud_out(empty); - image->flipud_out(empty); - - return Py::Object(); + return Py::Object(); } - - 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; + 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; - // Render face - if (face.first) { - theRasterizer.add_path(path); + // Render face + if (face.first) + { + theRasterizer.add_path(path); - if (gc.isaa) { - if (has_clippath) { - pixfmt_amask_type pfa(pixFmt, alphaMask); - amask_ren_type r(pfa); - amask_aa_renderer_type ren(r); - ren.color(face.second); - agg::render_scanlines(theRasterizer, slineP8, ren); - } else { - rendererAA.color(face.second); - agg::render_scanlines(theRasterizer, slineP8, rendererAA); - } - } else { - if (has_clippath) { - pixfmt_amask_type pfa(pixFmt, alphaMask); - amask_ren_type r(pfa); - amask_bin_renderer_type ren(r); - ren.color(face.second); - agg::render_scanlines(theRasterizer, slineP8, ren); - } else { - rendererBin.color(face.second); - agg::render_scanlines(theRasterizer, slineP8, rendererBin); - } + if (gc.isaa) + { + if (has_clippath) + { + pixfmt_amask_type pfa(pixFmt, alphaMask); + amask_ren_type r(pfa); + amask_aa_renderer_type ren(r); + ren.color(face.second); + agg::render_scanlines(theRasterizer, slineP8, ren); + } + else + { + rendererAA.color(face.second); + agg::render_scanlines(theRasterizer, slineP8, rendererAA); + } + } + else + { + if (has_clippath) + { + pixfmt_amask_type pfa(pixFmt, alphaMask); + amask_ren_type r(pfa); + amask_bin_renderer_type ren(r); + ren.color(face.second); + agg::render_scanlines(theRasterizer, slineP8, ren); + } + else + { + rendererBin.color(face.second); + agg::render_scanlines(theRasterizer, slineP8, rendererBin); + } + } } - } - // Render hatch - if (!gc.hatchpath.isNone()) { - // Reset any clipping that may be in effect, since we'll be - // drawing the hatch in a scratch buffer at origin (0, 0) - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); + // Render hatch + if (!gc.hatchpath.isNone()) + { + // Reset any clipping that may be in effect, since we'll be + // drawing the hatch in a scratch buffer at origin (0, 0) + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); - // Create and transform the path - typedef agg::conv_transform<PathIterator> hatch_p... [truncated message content]
Revision: 8464 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8464&view=rev Author: mdboom Date: 2010年06月24日 17:59:48 +0000 (2010年6月24日) Log Message: ----------- Speed up Gouraud shading in Agg backend. Modified Paths: -------------- trunk/matplotlib/src/_backend_agg.cpp trunk/matplotlib/src/_backend_agg.h Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2010年06月24日 17:12:26 UTC (rev 8463) +++ trunk/matplotlib/src/_backend_agg.cpp 2010年06月24日 17:59:48 UTC (rev 8464) @@ -1824,19 +1824,15 @@ } void -RendererAgg::_draw_gouraud_triangle(const GCAgg& gc, const double* points, +RendererAgg::_draw_gouraud_triangle(const double* points, const double* colors, - agg::trans_affine trans) + agg::trans_affine trans, + bool has_clippath) { typedef agg::rgba8 color_t; typedef agg::span_gouraud_rgba<color_t> span_gen_t; typedef agg::span_allocator<color_t> span_alloc_t; - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - set_clipbox(gc.cliprect, theRasterizer); - bool has_clippath = render_clippath(gc.clippath, gc.clippath_trans); - trans *= agg::trans_affine_scaling(1.0, -1.0); trans *= agg::trans_affine_translation(0.0, (double)height); @@ -1897,6 +1893,11 @@ PyArrayObject* points = NULL; PyArrayObject* colors = NULL; + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); + set_clipbox(gc.cliprect, theRasterizer); + bool has_clippath = render_clippath(gc.clippath, gc.clippath_trans); + try { points = (PyArrayObject*)PyArray_ContiguousFromAny @@ -1916,7 +1917,8 @@ } _draw_gouraud_triangle( - gc, (double*)PyArray_DATA(points), (double*)PyArray_DATA(colors), trans); + (double*)PyArray_DATA(points), (double*)PyArray_DATA(colors), + trans, has_clippath); } catch (...) { @@ -1951,6 +1953,11 @@ PyArrayObject* points = NULL; PyArrayObject* colors = NULL; + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); + set_clipbox(gc.cliprect, theRasterizer); + bool has_clippath = render_clippath(gc.clippath, gc.clippath_trans); + try { points = (PyArrayObject*)PyArray_ContiguousFromAny @@ -1976,7 +1983,9 @@ for (int i = 0; i < PyArray_DIM(points, 0); ++i) { - _draw_gouraud_triangle(gc, (double*)PyArray_GETPTR1(points, i), (double*)PyArray_GETPTR1(colors, i), trans); + _draw_gouraud_triangle( + (double*)PyArray_GETPTR1(points, i), + (double*)PyArray_GETPTR1(colors, i), trans, has_clippath); } } catch (...) Modified: trunk/matplotlib/src/_backend_agg.h =================================================================== --- trunk/matplotlib/src/_backend_agg.h 2010年06月24日 17:12:26 UTC (rev 8463) +++ trunk/matplotlib/src/_backend_agg.h 2010年06月24日 17:59:48 UTC (rev 8464) @@ -263,8 +263,8 @@ void _draw_gouraud_triangle( - const GCAgg& gc, - const double* points, const double* colors, agg::trans_affine trans); + const double* points, const double* colors, + agg::trans_affine trans, bool has_clippath); private: void create_alpha_buffers(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 8474 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8474&view=rev Author: mdboom Date: 2010年06月28日 13:54:52 +0000 (2010年6月28日) Log Message: ----------- Use automatic memory management to simplify the code. Modified Paths: -------------- trunk/matplotlib/src/_backend_agg.cpp trunk/matplotlib/src/_image.cpp trunk/matplotlib/src/agg_py_path_iterator.h Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2010年06月28日 13:51:16 UTC (rev 8473) +++ trunk/matplotlib/src/_backend_agg.cpp 2010年06月28日 13:54:52 UTC (rev 8474) @@ -881,23 +881,24 @@ const unsigned char* buffer = NULL; int width, height; Py::Object image_obj = args[0]; - PyArrayObject* image_array = NULL; if (PyArray_Check(image_obj.ptr())) { - image_array = (PyArrayObject*)PyArray_FromObject(image_obj.ptr(), PyArray_UBYTE, 2, 2); + PyObject* image_array = PyArray_FromObject( + image_obj.ptr(), PyArray_UBYTE, 2, 2); if (!image_array) { throw Py::ValueError( "First argument to draw_text_image must be a FT2Font.Image object or a Nx2 uint8 numpy array."); } + image_obj = Py::Object(image_array, true); buffer = (unsigned char *)PyArray_DATA(image_array); width = PyArray_DIM(image_array, 1); height = PyArray_DIM(image_array, 0); } else { - FT2Image *image = static_cast<FT2Image*>(args[0].ptr()); + FT2Image *image = static_cast<FT2Image*>(image_obj.ptr()); if (!image->get_buffer()) { throw Py::ValueError( @@ -916,7 +917,6 @@ } catch (Py::TypeError) { - Py_XDECREF(image_array); throw Py::TypeError("Invalid input arguments to draw_text_image"); } @@ -959,8 +959,6 @@ theRasterizer.add_path(rect2); agg::render_scanlines(theRasterizer, slineP8, ri); - Py_XDECREF(image_array); - return Py::Object(); } @@ -1352,204 +1350,193 @@ typedef agg::conv_curve<snapped_t> snapped_curve_t; typedef agg::conv_curve<clipped_t> curve_t; - PyArrayObject* offsets = NULL; - PyArrayObject* facecolors = NULL; - PyArrayObject* edgecolors = NULL; + 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)) + { + Py_XDECREF(offsets); + throw Py::ValueError("Offsets array must be Nx2"); + } + Py::Object offsets_arr_obj((PyObject*)offsets, true); - try + PyArrayObject* facecolors = (PyArrayObject*)PyArray_FromObject + (facecolors_obj.ptr(), PyArray_DOUBLE, 1, 2); + if (!facecolors || + (PyArray_NDIM(facecolors) == 1 && PyArray_DIM(facecolors, 0) != 0) || + (PyArray_NDIM(facecolors) == 2 && PyArray_DIM(facecolors, 1) != 4)) { - 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"); - } + Py_XDECREF(facecolors); + throw Py::ValueError("Facecolors must be a Nx4 numpy array or empty"); + } + Py::Object facecolors_arr_obj((PyObject*)facecolors, true); - facecolors = (PyArrayObject*)PyArray_FromObject - (facecolors_obj.ptr(), PyArray_DOUBLE, 1, 2); - if (!facecolors || - (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 || + (PyArray_NDIM(edgecolors) == 1 && PyArray_DIM(edgecolors, 0) != 0) || + (PyArray_NDIM(edgecolors) == 2 && PyArray_DIM(edgecolors, 1) != 4)) + { + Py_XDECREF(edgecolors); + throw Py::ValueError("Edgecolors must be a Nx4 numpy array"); + } + Py::Object edgecolors_arr_obj((PyObject*)edgecolors, true); - edgecolors = (PyArrayObject*)PyArray_FromObject - (edgecolors_obj.ptr(), PyArray_DOUBLE, 1, 2); - if (!edgecolors || - (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(); + size_t Noffsets = offsets->dimensions[0]; + size_t N = std::max(Npaths, Noffsets); + size_t Ntransforms = std::min(transforms_obj.length(), N); + size_t Nfacecolors = facecolors->dimensions[0]; + size_t Nedgecolors = edgecolors->dimensions[0]; + size_t Nlinewidths = linewidths.length(); + size_t Nlinestyles = std::min(linestyles_obj.length(), N); + size_t Naa = antialiaseds.length(); - size_t Npaths = path_generator.num_paths(); - size_t Noffsets = offsets->dimensions[0]; - size_t N = std::max(Npaths, Noffsets); - size_t Ntransforms = std::min(transforms_obj.length(), N); - size_t Nfacecolors = facecolors->dimensions[0]; - size_t Nedgecolors = edgecolors->dimensions[0]; - size_t Nlinewidths = linewidths.length(); - size_t Nlinestyles = std::min(linestyles_obj.length(), N); - size_t Naa = antialiaseds.length(); + if ((Nfacecolors == 0 && Nedgecolors == 0) || Npaths == 0) + { + return Py::Object(); + } - if ((Nfacecolors == 0 && Nedgecolors == 0) || Npaths == 0) - { - return Py::Object(); - } + size_t i = 0; - size_t i = 0; + // 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].ptr(), false); + trans *= master_transform; - // 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].ptr(), false); - trans *= master_transform; + transforms.push_back(trans); + } - transforms.push_back(trans); + // Convert all the dashes up front + typedef std::vector<std::pair<double, GCAgg::dash_t> > dashes_t; + dashes_t dashes; + dashes.resize(Nlinestyles); + i = 0; + for (dashes_t::iterator d = dashes.begin(); + d != dashes.end(); ++d, ++i) + { + convert_dashes(Py::Tuple(linestyles_obj[i]), dpi, d->second, + d->first); + } + + // Handle any clipping globally + theRasterizer.reset_clipping(); + rendererBase.reset_clipping(true); + set_clipbox(cliprect, theRasterizer); + bool has_clippath = render_clippath(clippath, clippath_trans); + + // Set some defaults, assuming no face or edge + gc.linewidth = 0.0; + facepair_t face; + face.first = Nfacecolors != 0; + agg::trans_affine trans; + + for (i = 0; i < N; ++i) + { + typename PathGenerator::path_iterator path = path_generator(i); + + if (Ntransforms) + { + trans = transforms[i % Ntransforms]; } + else + { + trans = master_transform; + } - // Convert all the dashes up front - typedef std::vector<std::pair<double, GCAgg::dash_t> > dashes_t; - dashes_t dashes; - dashes.resize(Nlinestyles); - i = 0; - for (dashes_t::iterator d = dashes.begin(); - d != dashes.end(); ++d, ++i) + if (Noffsets) { - convert_dashes(Py::Tuple(linestyles_obj[i]), dpi, d->second, - d->first); + 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); } - // Handle any clipping globally - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - set_clipbox(cliprect, theRasterizer); - bool has_clippath = render_clippath(clippath, clippath_trans); + // These transformations must be done post-offsets + trans *= agg::trans_affine_scaling(1.0, -1.0); + trans *= agg::trans_affine_translation(0.0, (double)height); - // Set some defaults, assuming no face or edge - gc.linewidth = 0.0; - facepair_t face; - face.first = Nfacecolors != 0; - agg::trans_affine trans; + if (Nfacecolors) + { + size_t fi = i % Nfacecolors; + face.second = agg::rgba( + *(double*)PyArray_GETPTR2(facecolors, fi, 0), + *(double*)PyArray_GETPTR2(facecolors, fi, 1), + *(double*)PyArray_GETPTR2(facecolors, fi, 2), + *(double*)PyArray_GETPTR2(facecolors, fi, 3)); + } - for (i = 0; i < N; ++i) + if (Nedgecolors) { - typename PathGenerator::path_iterator path = path_generator(i); + size_t ei = i % Nedgecolors; + gc.color = agg::rgba( + *(double*)PyArray_GETPTR2(edgecolors, ei, 0), + *(double*)PyArray_GETPTR2(edgecolors, ei, 1), + *(double*)PyArray_GETPTR2(edgecolors, ei, 2), + *(double*)PyArray_GETPTR2(edgecolors, ei, 3)); - if (Ntransforms) + if (Nlinewidths) { - trans = transforms[i % Ntransforms]; + gc.linewidth = double(Py::Float(linewidths[i % Nlinewidths])) * dpi / 72.0; } else { - trans = master_transform; + gc.linewidth = 1.0; } - - if (Noffsets) + if (Nlinestyles) { - 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); + gc.dashes = dashes[i % Nlinestyles].second; + gc.dashOffset = dashes[i % Nlinestyles].first; } + } - // These transformations must be done post-offsets - trans *= agg::trans_affine_scaling(1.0, -1.0); - trans *= agg::trans_affine_translation(0.0, (double)height); + bool do_clip = !face.first && gc.hatchpath.isNone() && !has_curves; - if (Nfacecolors) + if (check_snap) + { + gc.isaa = bool(Py::Int(antialiaseds[i % Naa])); + + transformed_path_t tpath(path, trans); + nan_removed_t nan_removed(tpath, true, has_curves); + clipped_t clipped(nan_removed, do_clip, width, height); + snapped_t snapped(clipped, gc.snap_mode, + path.total_vertices(), gc.linewidth); + if (has_curves) { - size_t fi = i % Nfacecolors; - face.second = agg::rgba( - *(double*)PyArray_GETPTR2(facecolors, fi, 0), - *(double*)PyArray_GETPTR2(facecolors, fi, 1), - *(double*)PyArray_GETPTR2(facecolors, fi, 2), - *(double*)PyArray_GETPTR2(facecolors, fi, 3)); + snapped_curve_t curve(snapped); + _draw_path(curve, has_clippath, face, gc); } - - if (Nedgecolors) + else { - size_t ei = i % Nedgecolors; - gc.color = agg::rgba( - *(double*)PyArray_GETPTR2(edgecolors, ei, 0), - *(double*)PyArray_GETPTR2(edgecolors, ei, 1), - *(double*)PyArray_GETPTR2(edgecolors, ei, 2), - *(double*)PyArray_GETPTR2(edgecolors, ei, 3)); - - if (Nlinewidths) - { - gc.linewidth = double(Py::Float(linewidths[i % Nlinewidths])) * dpi / 72.0; - } - else - { - gc.linewidth = 1.0; - } - if (Nlinestyles) - { - gc.dashes = dashes[i % Nlinestyles].second; - gc.dashOffset = dashes[i % Nlinestyles].first; - } + _draw_path(snapped, has_clippath, face, gc); } + } + else + { + gc.isaa = bool(Py::Int(antialiaseds[i % Naa])); - bool do_clip = !face.first && gc.hatchpath.isNone() && !has_curves; - - if (check_snap) + transformed_path_t tpath(path, trans); + nan_removed_t nan_removed(tpath, true, has_curves); + clipped_t clipped(nan_removed, do_clip, width, height); + if (has_curves) { - gc.isaa = bool(Py::Int(antialiaseds[i % Naa])); - - transformed_path_t tpath(path, trans); - nan_removed_t nan_removed(tpath, true, has_curves); - clipped_t clipped(nan_removed, do_clip, width, height); - snapped_t snapped(clipped, gc.snap_mode, - path.total_vertices(), gc.linewidth); - if (has_curves) - { - snapped_curve_t curve(snapped); - _draw_path(curve, has_clippath, face, gc); - } - else - { - _draw_path(snapped, has_clippath, face, gc); - } + curve_t curve(clipped); + _draw_path(curve, has_clippath, face, gc); } else { - gc.isaa = bool(Py::Int(antialiaseds[i % Naa])); - - transformed_path_t tpath(path, trans); - nan_removed_t nan_removed(tpath, true, has_curves); - clipped_t clipped(nan_removed, do_clip, width, height); - if (has_curves) - { - curve_t curve(clipped); - _draw_path(curve, has_clippath, face, gc); - } - else - { - _draw_path(clipped, has_clippath, face, gc); - } + _draw_path(clipped, has_clippath, face, gc); } } - - Py_XDECREF(offsets); - Py_XDECREF(facecolors); - Py_XDECREF(edgecolors); - return Py::Object(); } - catch (...) - { - Py_XDECREF(offsets); - Py_XDECREF(facecolors); - Py_XDECREF(edgecolors); - throw; - } + + return Py::Object(); } @@ -1741,7 +1728,7 @@ agg::trans_affine master_transform = py_to_agg_transformation_matrix(args[1].ptr()); size_t mesh_width = Py::Int(args[2]); size_t mesh_height = Py::Int(args[3]); - PyObject* coordinates = args[4].ptr(); + Py::Object coordinates = args[4]; Py::Object offsets_obj = args[5]; agg::trans_affine offset_trans = py_to_agg_transformation_matrix(args[6].ptr()); Py::Object facecolors_obj = args[7]; @@ -1749,7 +1736,7 @@ bool showedges = (bool)Py::Int(args[9]); bool free_edgecolors = false; - QuadMeshGenerator path_generator(mesh_width, mesh_height, coordinates); + QuadMeshGenerator path_generator(mesh_width, mesh_height, coordinates.ptr()); Py::SeqBase<Py::Object> transforms_obj; Py::Object edgecolors_obj; @@ -1763,9 +1750,8 @@ { npy_intp dims[] = { 1, 4, 0 }; double data[] = { 0, 0, 0, 1 }; - edgecolors_obj = PyArray_SimpleNewFromData(2, dims, PyArray_DOUBLE, - (char*)data); - free_edgecolors = true; + edgecolors_obj = Py::Object(PyArray_SimpleNewFromData(2, dims, PyArray_DOUBLE, + (char*)data), true); } else { @@ -1783,9 +1769,7 @@ try { - try - { - _draw_path_collection_generic<QuadMeshGenerator, 0, 0> + _draw_path_collection_generic<QuadMeshGenerator, 0, 0> (gc, master_transform, gc.cliprect, @@ -1800,26 +1784,12 @@ linewidths, linestyles_obj, antialiaseds); - } - catch (const char* e) - { - throw Py::RuntimeError(e); - } } - catch (...) + catch (const char* e) { - if (free_edgecolors) - { - Py_XDECREF(edgecolors_obj.ptr()); - } - throw; + throw Py::RuntimeError(e); } - if (free_edgecolors) - { - Py_XDECREF(edgecolors_obj.ptr()); - } - return Py::Object(); } @@ -1890,46 +1860,34 @@ Py::Object colors_obj = args[2]; agg::trans_affine trans = py_to_agg_transformation_matrix(args[3].ptr()); - PyArrayObject* points = NULL; - PyArrayObject* colors = NULL; - theRasterizer.reset_clipping(); rendererBase.reset_clipping(true); set_clipbox(gc.cliprect, theRasterizer); bool has_clippath = render_clippath(gc.clippath, gc.clippath_trans); - try + PyArrayObject* points = (PyArrayObject*)PyArray_ContiguousFromAny + (points_obj.ptr(), PyArray_DOUBLE, 2, 2); + if (!points || + PyArray_DIM(points, 0) != 3 || PyArray_DIM(points, 1) != 2) { - points = (PyArrayObject*)PyArray_ContiguousFromAny - (points_obj.ptr(), PyArray_DOUBLE, 2, 2); - if (!points || - PyArray_DIM(points, 0) != 3 || PyArray_DIM(points, 1) != 2) - { - throw Py::ValueError("points must be a 3x2 numpy array"); - } - - colors = (PyArrayObject*)PyArray_ContiguousFromAny - (colors_obj.ptr(), PyArray_DOUBLE, 2, 2); - if (!colors || - PyArray_DIM(colors, 0) != 3 || PyArray_DIM(colors, 1) != 4) - { - throw Py::ValueError("colors must be a 3x4 numpy array"); - } - - _draw_gouraud_triangle( - (double*)PyArray_DATA(points), (double*)PyArray_DATA(colors), - trans, has_clippath); + Py_XDECREF(points); + throw Py::ValueError("points must be a 3x2 numpy array"); } - catch (...) + points_obj = Py::Object((PyObject*)points, true); + + PyArrayObject* colors = (PyArrayObject*)PyArray_ContiguousFromAny + (colors_obj.ptr(), PyArray_DOUBLE, 2, 2); + if (!colors || + PyArray_DIM(colors, 0) != 3 || PyArray_DIM(colors, 1) != 4) { - Py_XDECREF(points); Py_XDECREF(colors); - - throw; + throw Py::ValueError("colors must be a 3x4 numpy array"); } + colors_obj = Py::Object((PyObject*)colors, true); - Py_XDECREF(points); - Py_XDECREF(colors); + _draw_gouraud_triangle( + (double*)PyArray_DATA(points), (double*)PyArray_DATA(colors), + trans, has_clippath); return Py::Object(); } @@ -1950,54 +1908,42 @@ Py::Object colors_obj = args[2]; agg::trans_affine trans = py_to_agg_transformation_matrix(args[3].ptr()); - PyArrayObject* points = NULL; - PyArrayObject* colors = NULL; - theRasterizer.reset_clipping(); rendererBase.reset_clipping(true); set_clipbox(gc.cliprect, theRasterizer); bool has_clippath = render_clippath(gc.clippath, gc.clippath_trans); - try + PyArrayObject* points = (PyArrayObject*)PyArray_ContiguousFromAny + (points_obj.ptr(), PyArray_DOUBLE, 3, 3); + if (!points || + PyArray_DIM(points, 1) != 3 || PyArray_DIM(points, 2) != 2) { - points = (PyArrayObject*)PyArray_ContiguousFromAny - (points_obj.ptr(), PyArray_DOUBLE, 3, 3); - if (!points || - PyArray_DIM(points, 1) != 3 || PyArray_DIM(points, 2) != 2) - { - throw Py::ValueError("points must be a Nx3x2 numpy array"); - } - - colors = (PyArrayObject*)PyArray_ContiguousFromAny - (colors_obj.ptr(), PyArray_DOUBLE, 3, 3); - if (!colors || - PyArray_DIM(colors, 1) != 3 || PyArray_DIM(colors, 2) != 4) - { - throw Py::ValueError("colors must be a Nx3x4 numpy array"); - } - - if (PyArray_DIM(points, 0) != PyArray_DIM(colors, 0)) - { - throw Py::ValueError("points and colors arrays must be the same length"); - } - - for (int i = 0; i < PyArray_DIM(points, 0); ++i) - { - _draw_gouraud_triangle( - (double*)PyArray_GETPTR1(points, i), - (double*)PyArray_GETPTR1(colors, i), trans, has_clippath); - } + Py_XDECREF(points); + throw Py::ValueError("points must be a Nx3x2 numpy array"); } - catch (...) + points_obj = Py::Object((PyObject*)points, true); + + PyArrayObject* colors = (PyArrayObject*)PyArray_ContiguousFromAny + (colors_obj.ptr(), PyArray_DOUBLE, 3, 3); + if (!colors || + PyArray_DIM(colors, 1) != 3 || PyArray_DIM(colors, 2) != 4) { - Py_XDECREF(points); Py_XDECREF(colors); + throw Py::ValueError("colors must be a Nx3x4 numpy array"); + } + colors_obj = Py::Object((PyObject*)colors, true); - throw; + if (PyArray_DIM(points, 0) != PyArray_DIM(colors, 0)) + { + throw Py::ValueError("points and colors arrays must be the same length"); } - Py_XDECREF(points); - Py_XDECREF(colors); + for (int i = 0; i < PyArray_DIM(points, 0); ++i) + { + _draw_gouraud_triangle( + (double*)PyArray_GETPTR1(points, i), + (double*)PyArray_GETPTR1(colors, i), trans, has_clippath); + } return Py::Object(); } Modified: trunk/matplotlib/src/_image.cpp =================================================================== --- trunk/matplotlib/src/_image.cpp 2010年06月28日 13:51:16 UTC (rev 8473) +++ trunk/matplotlib/src/_image.cpp 2010年06月28日 13:54:52 UTC (rev 8474) @@ -864,15 +864,13 @@ Py::Object x = args[0]; int isoutput = Py::Int(args[1]); - //PyArrayObject *A = (PyArrayObject *) PyArray_ContiguousFromObject(x.ptr(), PyArray_DOUBLE, 2, 3); PyArrayObject *A = (PyArrayObject *) PyArray_FromObject(x.ptr(), PyArray_DOUBLE, 2, 3); - if (A == NULL) { throw Py::ValueError("Array must be rank 2 or 3 of doubles"); } + Py::Object A_obj((PyObject *)A, true); - Image* imo = new Image; imo->rowsIn = A->dimensions[0]; @@ -924,7 +922,6 @@ if (A->dimensions[2] != 3 && A->dimensions[2] != 4) { - Py_XDECREF(A); throw Py::ValueError(Printf("3rd dimension must be length 3 (RGB) or 4 (RGBA); found %d", A->dimensions[2]).str()); } @@ -959,11 +956,9 @@ } else // error { - Py_XDECREF(A); throw Py::ValueError("Illegal array rank; must be rank; must 2 or 3"); } buffer -= NUMBYTES; - Py_XDECREF(A); return Py::asObject(imo); } @@ -986,12 +981,11 @@ Py::Object x = args[0]; int isoutput = Py::Int(args[1]); PyArrayObject *A = (PyArrayObject *) PyArray_ContiguousFromObject(x.ptr(), PyArray_DOUBLE, 2, 3); - //PyArrayObject *A = (PyArrayObject *) PyArray_FromObject(x.ptr(), PyArray_DOUBLE, 2, 3); - if (A == NULL) { throw Py::ValueError("Array must be rank 2 or 3 of doubles"); } + Py::Object A_obj((PyObject*)A, true); Image* imo = new Image; @@ -1043,7 +1037,6 @@ { if (A->dimensions[2] != 3 && A->dimensions[2] != 4) { - Py_XDECREF(A); throw Py::ValueError(Printf("3rd dimension must be length 3 (RGB) or 4 (RGBA); found %d", A->dimensions[2]).str()); } @@ -1072,11 +1065,9 @@ } else // error { - Py_XDECREF(A); throw Py::ValueError("Illegal array rank; must be rank; must 2 or 3"); } buffer -= NUMBYTES; - Py_XDECREF(A); return Py::asObject(imo); } @@ -1104,6 +1095,8 @@ { throw Py::ValueError("Array must have 3 dimensions"); } + Py::Object A_obj((PyObject*)A, true); + if (A->dimensions[2] < 3 || A->dimensions[2] > 4) { throw Py::ValueError("Array dimension 3 must have size 3 or 4"); @@ -1146,7 +1139,6 @@ buffer -= N; arrbuf -= imo->rowsIn * imo->colsIn; } - Py_XDECREF(A); if (isoutput) { @@ -1456,18 +1448,9 @@ unsigned int * rowstarts , unsigned int*colstarts , float *acols , float *arows) { - if (x) - { - Py_XDECREF(x); - } - if (y) - { - Py_XDECREF(y); - } - if (d) - { - Py_XDECREF(d); - } + Py_XDECREF(x); + Py_XDECREF(y); + Py_XDECREF(d); if (rowstarts) { PyMem_Free(rowstarts); @@ -1494,7 +1477,9 @@ if (args.length() != 7) + { throw Py::TypeError("Incorrect number of arguments (7 expected)"); + } Py::Object xp = args[0]; Py::Object yp = args[1]; @@ -1510,7 +1495,10 @@ } if (bounds.length() != 4) + { throw Py::TypeError("Incorrect number of bounds (4 expected)"); + } + float x_min = Py::Float(bounds[0]); float x_max = Py::Float(bounds[1]); float y_min = Py::Float(bounds[2]); @@ -1529,8 +1517,8 @@ PyArrayObject *x = NULL; PyArrayObject *y = NULL; PyArrayObject *d = NULL; - unsigned int * rowstarts = NULL; - unsigned int*colstarts = NULL; + unsigned int *rowstarts = NULL; + unsigned int *colstarts = NULL; float *acols = NULL; float *arows = NULL; @@ -1704,7 +1692,24 @@ } +void _pcolor2_cleanup(PyArrayObject* x, PyArrayObject* y, PyArrayObject *d, + PyArrayObject* bg, int *irows, int*jcols) +{ + Py_XDECREF(x); + Py_XDECREF(y); + Py_XDECREF(d); + Py_XDECREF(bg); + if (irows) + { + PyMem_Free(irows); + } + if (jcols) + { + PyMem_Free(jcols); + } +} + char __image_module_pcolor2__doc__[] = "pcolor2(x, y, data, rows, cols, bounds, bg)\n" "\n" @@ -1748,33 +1753,39 @@ // Check we have something to output to if (rows == 0 || cols == 0) + { throw Py::ValueError("rows or cols is zero; there are no pixels"); + } + PyArrayObject* x = NULL; + PyArrayObject* y = NULL; + PyArrayObject* d = NULL; + PyArrayObject* bg = NULL; + int* irows = NULL; + int* jcols = NULL; + // Get numpy arrays - PyArrayObject *x = (PyArrayObject *) PyArray_ContiguousFromObject(xp.ptr(), - PyArray_DOUBLE, 1, 1); + x = (PyArrayObject *) PyArray_ContiguousFromObject(xp.ptr(), PyArray_DOUBLE, 1, 1); if (x == NULL) + { + _pcolor2_cleanup(x, y, d, bg, irows, jcols); throw Py::ValueError("x is of incorrect type (wanted 1D double)"); - PyArrayObject *y = (PyArrayObject *) PyArray_ContiguousFromObject(yp.ptr(), - PyArray_DOUBLE, 1, 1); + } + y = (PyArrayObject *) PyArray_ContiguousFromObject(yp.ptr(), PyArray_DOUBLE, 1, 1); if (y == NULL) { - Py_XDECREF(x); + _pcolor2_cleanup(x, y, d, bg, irows, jcols); throw Py::ValueError("y is of incorrect type (wanted 1D double)"); } - PyArrayObject *d = (PyArrayObject *) PyArray_ContiguousFromObject(dp.ptr(), - PyArray_UBYTE, 3, 3); + d = (PyArrayObject *) PyArray_ContiguousFromObject(dp.ptr(), PyArray_UBYTE, 3, 3); if (d == NULL) { - Py_XDECREF(x); - Py_XDECREF(y); + _pcolor2_cleanup(x, y, d, bg, irows, jcols); throw Py::ValueError("data is of incorrect type (wanted 3D uint8)"); } if (d->dimensions[2] != 4) { - Py_XDECREF(x); - Py_XDECREF(y); - Py_XDECREF(d); + _pcolor2_cleanup(x, y, d, bg, irows, jcols); throw Py::ValueError("data must be in RGBA format"); } @@ -1783,49 +1794,33 @@ int ny = y->dimensions[0]; if (nx != d->dimensions[1] + 1 || ny != d->dimensions[0] + 1) { - Py_XDECREF(x); - Py_XDECREF(y); - Py_XDECREF(d); + _pcolor2_cleanup(x, y, d, bg, irows, jcols); throw Py::ValueError("data and axis bin boundary dimensions are incompatible"); } - PyArrayObject *bg = (PyArrayObject *) PyArray_ContiguousFromObject(bgp.ptr(), - PyArray_UBYTE, 1, 1); + bg = (PyArrayObject *) PyArray_ContiguousFromObject(bgp.ptr(), PyArray_UBYTE, 1, 1); if (bg == NULL) { - Py_XDECREF(x); - Py_XDECREF(y); - Py_XDECREF(d); + _pcolor2_cleanup(x, y, d, bg, irows, jcols); throw Py::ValueError("bg is of incorrect type (wanted 1D uint8)"); } if (bg->dimensions[0] != 4) { - Py_XDECREF(x); - Py_XDECREF(y); - Py_XDECREF(d); - Py_XDECREF(bg); + _pcolor2_cleanup(x, y, d, bg, irows, jcols); throw Py::ValueError("bg must be in RGBA format"); } - // Allocate memory for pointer arrays - int * irows = reinterpret_cast<int*>(PyMem_Malloc(sizeof(int) * rows)); + irows = reinterpret_cast<int*>(PyMem_Malloc(sizeof(int) * rows)); if (irows == NULL) { - Py_XDECREF(x); - Py_XDECREF(y); - Py_XDECREF(d); - Py_XDECREF(bg); + _pcolor2_cleanup(x, y, d, bg, irows, jcols); throw Py::MemoryError("Cannot allocate memory for lookup table"); } - int * jcols = reinterpret_cast<int*>(PyMem_Malloc(sizeof(int) * cols)); + jcols = reinterpret_cast<int*>(PyMem_Malloc(sizeof(int) * cols)); if (jcols == NULL) { - Py_XDECREF(x); - Py_XDECREF(y); - Py_XDECREF(d); - Py_XDECREF(bg); - PyMem_Free(irows); + _pcolor2_cleanup(x, y, d, bg, irows, jcols); throw Py::MemoryError("Cannot allocate memory for lookup table"); } @@ -1839,12 +1834,7 @@ agg::int8u *buffer = new agg::int8u[NUMBYTES]; if (buffer == NULL) { - Py_XDECREF(x); - Py_XDECREF(y); - Py_XDECREF(d); - Py_XDECREF(bg); - PyMem_Free(irows); - PyMem_Free(jcols); + _pcolor2_cleanup(x, y, d, bg, irows, jcols); throw Py::MemoryError("Could not allocate memory for image"); } @@ -1886,12 +1876,7 @@ imo->bufferOut = buffer; imo->rbufOut->attach(imo->bufferOut, imo->colsOut, imo->rowsOut, imo->colsOut * imo->BPP); - Py_XDECREF(x); - Py_XDECREF(y); - Py_XDECREF(d); - Py_XDECREF(bg); - PyMem_Free(irows); - PyMem_Free(jcols); + _pcolor2_cleanup(x, y, d, bg, irows, jcols); return Py::asObject(imo); } Modified: trunk/matplotlib/src/agg_py_path_iterator.h =================================================================== --- trunk/matplotlib/src/agg_py_path_iterator.h 2010年06月28日 13:51:16 UTC (rev 8473) +++ trunk/matplotlib/src/agg_py_path_iterator.h 2010年06月28日 13:54:52 UTC (rev 8474) @@ -24,8 +24,8 @@ underlying data arrays, so that Python reference counting can work. */ - PyArrayObject* m_vertices; - PyArrayObject* m_codes; + Py::Object m_vertices; + Py::Object m_codes; size_t m_iterator; size_t m_total_vertices; @@ -39,7 +39,7 @@ public: /* path_obj is an instance of the class Path as defined in path.py */ inline PathIterator(const Py::Object& path_obj) : - m_vertices(NULL), m_codes(NULL), m_iterator(0), m_should_simplify(false), + m_vertices(), m_codes(), m_iterator(0), m_should_simplify(false), m_simplify_threshold(1.0 / 9.0) { Py::Object vertices_obj = path_obj.getAttr("vertices"); @@ -47,45 +47,42 @@ Py::Object should_simplify_obj = path_obj.getAttr("should_simplify"); Py::Object simplify_threshold_obj = path_obj.getAttr("simplify_threshold"); - m_vertices = (PyArrayObject*)PyArray_FromObject - (vertices_obj.ptr(), PyArray_DOUBLE, 2, 2); - if (!m_vertices || - PyArray_DIM(m_vertices, 1) != 2) + PyObject* vertices_arr = PyArray_FromObject(vertices_obj.ptr(), PyArray_DOUBLE, 2, 2); + if (!vertices_arr) { - Py_XDECREF(m_vertices); - m_vertices = NULL; throw Py::ValueError("Invalid vertices array."); } + m_vertices = Py::Object(vertices_arr, true); + if (PyArray_DIM(m_vertices.ptr(), 1) != 2) + { + throw Py::ValueError("Invalid vertices array."); + } + if (codes_obj.ptr() != Py_None) { - m_codes = (PyArrayObject*)PyArray_FromObject - (codes_obj.ptr(), PyArray_UINT8, 1, 1); - if (!m_codes) + PyObject* codes_arr = PyArray_FromObject(codes_obj.ptr(), PyArray_UINT8, 1, 1); + + if (!codes_arr) { - Py_XDECREF(m_vertices); - m_vertices = NULL; throw Py::ValueError("Invalid codes array."); } - if (PyArray_DIM(m_codes, 0) != PyArray_DIM(m_vertices, 0)) + + m_codes = Py::Object(codes_arr, true); + if (PyArray_DIM(m_codes.ptr(), 0) != PyArray_DIM(m_vertices.ptr(), 0)) { - Py_XDECREF(m_vertices); - m_vertices = NULL; - Py_XDECREF(m_codes); - m_codes = NULL; throw Py::ValueError("Codes array is wrong length"); } } m_should_simplify = should_simplify_obj.isTrue(); - m_total_vertices = PyArray_DIM(m_vertices, 0); + m_total_vertices = PyArray_DIM(m_vertices.ptr(), 0); m_simplify_threshold = Py::Float(simplify_threshold_obj); } ~PathIterator() { - Py_XDECREF(m_vertices); - Py_XDECREF(m_codes); + } inline unsigned vertex(double* x, double* y) @@ -94,13 +91,13 @@ const size_t idx = m_iterator++; - char* pair = (char*)PyArray_GETPTR2(m_vertices, idx, 0); + char* pair = (char*)PyArray_GETPTR2(m_vertices.ptr(), idx, 0); *x = *(double*)pair; - *y = *(double*)(pair + PyArray_STRIDE(m_vertices, 1)); + *y = *(double*)(pair + PyArray_STRIDE(m_vertices.ptr(), 1)); - if (m_codes) + if (!m_codes.isNone()) { - return (unsigned)(*(char *)PyArray_GETPTR1(m_codes, idx)); + return (unsigned)(*(char *)PyArray_GETPTR1(m_codes.ptr(), idx)); } else { @@ -130,7 +127,7 @@ inline bool has_curves() { - return m_codes != NULL; + return !m_codes.isNone(); } }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.