[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/WeatherGod/matplotlib/mplot3d/minor_errors/src/_wxagg.cpp [Back]  [Original]

// File: _wxagg.cpp
// Purpose: Accelerate WXAgg by doing the agg->wxWidgets conversions in C++.
// Author: Ken McIvor 
//
// Copyright 2005 Illinois Institute of Technology
// Derived from `_gtkagg.cpp', Copyright 2004-2005 John Hunter
//
// See the file "LICENSE" for information on usage and redistribution
// of this file, and for a DISCLAIMER OF ALL WARRANTIES.


// TODO:
// * Better type checking.
//
// * Make the `bbox' argument optional.
//
// * Determine if there are any thread-safety issues with this implementation.
//
// * Perform some AGG kung-fu to let us slice a region out of a
//   rendering_buffer and convert it from RGBA to RGB on the fly, rather than
//   making itermediate copies.  This could be of use in _gtkagg and _tkagg as
//   well.
//
// * Write an agg_to_wx_bitmap() that works more like agg_to_gtk_drawable(),
//   drawing directly to a bitmap.
//
//   This was the initial plan, except that I had not idea how to take a
//   wx.Bitmap Python shadow class and turn it into a wxBitmap pointer.
//
//   It appears that this is the way to do it:
//       bool success = wxPyConvertSwigPtr(pyBitmap, (void**)&bitmap,
//           _T("wxBitmap"));
//
//   I'm not sure this will speed things up much, since wxWidgets requires you
//   to go AGG->wx.Image->wx.Bitmap before you can blit using a MemoryDC.


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "agg_basics.h"
#include "_backend_agg.h"
#include "agg_pixfmt_rgba.h"
#include "util/agg_color_conv_rgb8.h"
#include "agg_py_transforms.h"

#include 
#include 
#include 


// forward declarations
static wxImage  *convert_agg2image(RendererAgg *aggRenderer, Py::Object clipbox);
static wxBitmap *convert_agg2bitmap(RendererAgg *aggRenderer, Py::Object clipbox);


// the extension module
class _wxagg_module : public Py::ExtensionModule
{
public:

    _wxagg_module()
            : Py::ExtensionModule("_wxkagg")
    {
        add_varargs_method("convert_agg_to_wx_image",
                           &_wxagg_module::convert_agg_to_wx_image,
                           "Convert the region of the agg buffer bounded by bbox to a wx.Image."
                           "  If bbox\nis None, the entire buffer is converted.\n\nNote: agg must"
                           " be a backend_agg.RendererAgg instance.");

        add_varargs_method("convert_agg_to_wx_bitmap",
                           &_wxagg_module::convert_agg_to_wx_bitmap,
                           "Convert the region of the agg buffer bounded by bbox to a wx.Bitmap."
                           "  If bbox\nis None, the entire buffer is converted.\n\nNote: agg must"
                           " be a backend_agg.RendererAgg instance.");

        initialize("The _wxagg module");
    }

    virtual ~_wxagg_module() {}

private:

    Py::Object convert_agg_to_wx_image(const Py::Tuple &args)
    {
        args.verify_length(2);

        RendererAgg* aggRenderer = static_cast(
                                       args[0].getAttr("_renderer").ptr());

        Py::Object clipbox = args[1];

        // convert the buffer
        wxImage *image = convert_agg2image(aggRenderer, clipbox);

        // wrap a wx.Image around the result and return it
        PyObject *pyWxImage = wxPyConstructObject(image, _T("wxImage"), 1);
        if (pyWxImage == NULL)
        {
            throw Py::MemoryError(
                "_wxagg.convert_agg_to_wx_image(): could not create the wx.Image");
        }

        return Py::asObject(pyWxImage);
    }


    Py::Object convert_agg_to_wx_bitmap(const Py::Tuple &args)
    {
        args.verify_length(2);

        RendererAgg* aggRenderer = static_cast(
            args[0].getAttr("_renderer").ptr());

        Py::Object clipbox = args[1];

        // convert the buffer
        wxBitmap *bitmap = convert_agg2bitmap(aggRenderer, clipbox);

        // wrap a wx.Bitmap around the result and return it
        PyObject *pyWxBitmap = wxPyConstructObject(bitmap, _T("wxBitmap"), 1);
        if (pyWxBitmap == NULL)
        {
            throw Py::MemoryError(
                "_wxagg.convert_agg_to_wx_bitmap(): could not create the wx.Bitmap");
        }

        return Py::asObject(pyWxBitmap);
    }
};


//
// Implementation Functions
//

static wxImage *convert_agg2image(RendererAgg *aggRenderer, Py::Object clipbox)
{
    int srcWidth  = 1;
    int srcHeight = 1;
    int srcStride = 1;

    bool deleteSrcBuffer = false;
    agg::int8u *srcBuffer = NULL;

    double l, b, r, t;

    if (!py_convert_bbox(clipbox.ptr(), l, b, r, t))
    {
        // Convert everything: rgba => rgb -> image
        srcBuffer = aggRenderer->pixBuffer;
        srcWidth  = (int) aggRenderer->get_width();
        srcHeight = (int) aggRenderer->get_height();
        srcStride = (int) aggRenderer->get_width() * 4;
    }
    else
    {
        // Convert a region: rgba => clipped rgba => rgb -> image
        srcWidth = (int)(r - l);
        srcHeight = (int)(t - b);
        srcStride = srcWidth * 4;

        deleteSrcBuffer = true;
        srcBuffer = new agg::int8u[srcStride*srcHeight];
        if (srcBuffer == NULL)
        {
            throw Py::MemoryError(
                "_wxagg::convert_agg2image(): could not allocate `srcBuffer'");
        }

        int h = (int) aggRenderer->get_height();
        agg::rect_base region(
            (int) l,      // x1
            h - (int) t,  // y1
            (int) r,      // x2
            h - (int) b); // y2

        agg::rendering_buffer rbuf;
        rbuf.attach(srcBuffer, srcWidth, srcHeight, srcStride);
        pixfmt pf(rbuf);
        renderer_base rndr(pf);
        rndr.copy_from(aggRenderer->renderingBuffer, ®ion,
                       (int) - l, (int)(t - h));
    }

    // allocate the RGB data array

    // use malloc(3) because wxImage will use free(3)
    agg::int8u *destBuffer = (agg::int8u *) malloc(
                                 sizeof(agg::int8u) * srcWidth * 3 * srcHeight);

    if (destBuffer == NULL)
    {
        if (deleteSrcBuffer)
        {
            delete [] srcBuffer;
        }

        throw Py::MemoryError(
            "_wxagg::convert_agg2image(): could not allocate `destBuffer'");
    }

    // convert from RGBA to RGB
    agg::rendering_buffer rbSource;
    rbSource.attach(srcBuffer, srcWidth, srcHeight, srcStride);

    agg::rendering_buffer rbDest;
    rbDest.attach(destBuffer, srcWidth, srcHeight, srcWidth*3);

    agg::color_conv(&rbDest, &rbSource, agg::color_conv_rgba32_to_rgb24());

    // Create a wxImage using the RGB data
    wxImage *image = new wxImage(srcWidth, srcHeight, destBuffer);
    if (image == NULL)
    {
        if (deleteSrcBuffer)
        {
            delete [] srcBuffer;
        }

        free(destBuffer);
        throw Py::MemoryError(
            "_wxagg::convert_agg2image(): could not allocate `image'");
    }

    if (deleteSrcBuffer)
    {
        delete [] srcBuffer;
    }

    return image;
}


static wxBitmap *convert_agg2bitmap(RendererAgg *aggRenderer, Py::Object clipbox)
{
    // Convert everything: rgba => rgb -> image => bitmap
    // Convert a region:   rgba => clipped rgba => rgb -> image => bitmap
    wxImage *image = convert_agg2image(aggRenderer, clipbox);
    wxBitmap *bitmap = new wxBitmap(*image);

    image->Destroy();
    delete image;

    if (bitmap == NULL)
    {
        throw Py::MemoryError(
            "_wxagg::convert_agg2bitmap(): could not allocate `bitmap'");
    }

    return bitmap;
}


//
// Module Initialization
//

extern "C"
    DL_EXPORT(void)
    init_wxagg(void)
{
    wxPyCoreAPI_IMPORT();
    //suppress an unused variable warning by creating _wxagg_module in two lines
    static _wxagg_module* _wxagg = NULL;
    _wxagg = new _wxagg_module;
};

Web Proxy Viewer  |  New URL  |  Original Page