/* -*- mode: c++; c-basic-offset: 4 -*- */
#include <pygobject.h>
#include <pygtk/pygtk.h>
#include <vector>
#include "agg_basics.h"
#include "agg_pixfmt_rgba.h"
#include "agg_renderer_base.h"
#include "agg_rendering_buffer.h"
#include "numpy_cpp.h"
#include "py_converters.h"
static PyObject *Py_agg_to_gtk_drawable(PyObject *self, PyObject *args, PyObject *kwds)
{
typedef agg::pixfmt_rgba32_plain pixfmt;
typedef agg::renderer_base<pixfmt> renderer_base;
PyGObject *py_drawable;
numpy::array_view<agg::int8u, 3> buffer;
agg::rect_d rect;
// args are gc, renderer, bbox where bbox is a transforms BBox
// (possibly None). If bbox is None, blit the entire agg buffer
// to gtk. If bbox is not None, blit only the region defined by
// the bbox
if (!PyArg_ParseTuple(args,
"OO&O&:agg_to_gtk_drawable",
&py_drawable,
&buffer.converter,
&buffer,
&convert_rect,
&rect)) {
return NULL;
}
if (buffer.dim(2) != 4) {
PyErr_SetString(PyExc_ValueError, "Invalid image buffer. Must be NxMx4.");
return NULL;
}
GdkDrawable *drawable = GDK_DRAWABLE(py_drawable->obj);
GdkGC *gc = gdk_gc_new(drawable);
int srcstride = buffer.dim(1) * 4;
int srcwidth = buffer.dim(1);
int srcheight = buffer.dim(0);
// these three will be overridden below
int destx = 0;
int desty = 0;
int destwidth = 1;
int destheight = 1;
int deststride = 1;
std::vector<agg::int8u> destbuffer;
agg::int8u *destbufferptr;
if (rect.x1 == 0.0 && rect.x2 == 0.0 && rect.y1 == 0.0 && rect.y2 == 0.0) {
// bbox is None; copy the entire image
destbufferptr = (agg::int8u *)buffer.data();
destwidth = srcwidth;
destheight = srcheight;
deststride = srcstride;
} else {
destx = (int)rect.x1;
desty = srcheight - (int)rect.y2;
destwidth = (int)(rect.x2 - rect.x1);
destheight = (int)(rect.y2 - rect.y1);
deststride = destwidth * 4;
destbuffer.resize(destheight * deststride, 0);
destbufferptr = &destbuffer.front();
agg::rendering_buffer destrbuf;
destrbuf.attach(destbufferptr, destwidth, destheight, deststride);
pixfmt destpf(destrbuf);
renderer_base destrb(destpf);
agg::rendering_buffer srcrbuf;
srcrbuf.attach((agg::int8u *)buffer.data(), buffer.dim(1), buffer.dim(0), buffer.dim(1) * 4);
agg::rect_base<int> region(destx, desty, (int)rect.x2, srcheight - (int)rect.y1);
destrb.copy_from(srcrbuf, ®ion, -destx, -desty);
}
gdk_draw_rgb_32_image(drawable,
gc,
destx,
desty,
destwidth,
destheight,
GDK_RGB_DITHER_NORMAL,
destbufferptr,
deststride);
gdk_gc_destroy(gc);
Py_RETURN_NONE;
}
static PyMethodDef module_methods[] = {
{"agg_to_gtk_drawable", (PyCFunction)Py_agg_to_gtk_drawable, METH_VARARGS, NULL},
NULL
};
extern "C" {
#if PY3K
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_gtkagg",
NULL,
0,
module_methods,
NULL,
NULL,
NULL,
NULL
};
#define INITERROR return NULL
PyMODINIT_FUNC PyInit__gtkagg(void)
#else
#define INITERROR return
PyMODINIT_FUNC init_gtkagg(void)
#endif
{
PyObject *m;
#if PY3K
m = PyModule_Create(&moduledef);
#else
m = Py_InitModule3("_gtkagg", module_methods, NULL);
#endif
if (m == NULL) {
INITERROR;
}
init_pygobject();
init_pygtk();
import_array();
#if PY3K
return m;
#endif
}
}