diff --git a/lib/matplotlib/backends/tkagg.py b/lib/matplotlib/backends/tkagg.py index 2a9913d61db5..81fe9265a351 100644 --- a/lib/matplotlib/backends/tkagg.py +++ b/lib/matplotlib/backends/tkagg.py @@ -4,6 +4,8 @@ import six from six.moves import tkinter as Tk +import numpy as np + from matplotlib.backends import _tkagg def blit(photoimage, aggimage, bbox=None, colormode=1): @@ -13,15 +15,19 @@ def blit(photoimage, aggimage, bbox=None, colormode=1): bbox_array = bbox.__array__() else: bbox_array = None + data = np.asarray(aggimage) try: - tk.call("PyAggImagePhoto", photoimage, id(aggimage), colormode, id(bbox_array)) + tk.call( + "PyAggImagePhoto", photoimage, + id(data), colormode, id(bbox_array)) except Tk.TclError: try: try: _tkagg.tkinit(tk.interpaddr(), 1) except AttributeError: _tkagg.tkinit(id(tk), 0) - tk.call("PyAggImagePhoto", photoimage, id(aggimage), colormode, id(bbox_array)) + tk.call("PyAggImagePhoto", photoimage, + id(data), colormode, id(bbox_array)) except (ImportError, AttributeError, Tk.TclError): raise diff --git a/setupext.py b/setupext.py index f4c30c4c7483..db1672ca6a0c 100755 --- a/setupext.py +++ b/setupext.py @@ -852,23 +852,24 @@ def check(self): self.__class__.found_external = False return str(e) + ' Using local copy.' - def add_flags(self, ext): + def add_flags(self, ext, add_sources=True): if self.found_external: pkg_config.setup_extension(ext, 'libagg') else: ext.include_dirs.append('extern/agg24/include') - agg_sources = [ - 'agg_bezier_arc.cpp', - 'agg_curves.cpp', - 'agg_image_filters.cpp', - 'agg_trans_affine.cpp', - 'agg_vcgen_contour.cpp', - 'agg_vcgen_dash.cpp', - 'agg_vcgen_stroke.cpp', - 'agg_vpgen_segmentator.cpp' - ] - ext.sources.extend( - os.path.join('extern', 'agg24', 'src', x) for x in agg_sources) + if add_sources: + agg_sources = [ + 'agg_bezier_arc.cpp', + 'agg_curves.cpp', + 'agg_image_filters.cpp', + 'agg_trans_affine.cpp', + 'agg_vcgen_contour.cpp', + 'agg_vcgen_dash.cpp', + 'agg_vcgen_stroke.cpp', + 'agg_vpgen_segmentator.cpp' + ] + ext.sources.extend( + os.path.join('extern', 'agg24', 'src', x) for x in agg_sources) class FreeType(SetupPackage): @@ -1298,7 +1299,7 @@ def get_extension(self): ext = make_extension('matplotlib.backends._tkagg', sources) self.add_flags(ext) Numpy().add_flags(ext) - LibAgg().add_flags(ext) + LibAgg().add_flags(ext, add_sources=False) return ext def query_tcltk(self): diff --git a/src/_backend_agg_wrapper.cpp b/src/_backend_agg_wrapper.cpp index 7e5e094571bb..753afe3837d2 100644 --- a/src/_backend_agg_wrapper.cpp +++ b/src/_backend_agg_wrapper.cpp @@ -1,4 +1,25 @@ -#include "_backend_agg_wrapper.h" +#include "mplutils.h" +#include "py_converters.h" +#include "_backend_agg.h" + +typedef struct +{ + PyObject_HEAD; + RendererAgg *x; + Py_ssize_t shape[3]; + Py_ssize_t strides[3]; + Py_ssize_t suboffsets[3]; +} PyRendererAgg; + +typedef struct +{ + PyObject_HEAD; + BufferRegion *x; + Py_ssize_t shape[3]; + Py_ssize_t strides[3]; + Py_ssize_t suboffsets[3]; +} PyBufferRegion; + /********************************************************************** * BufferRegion diff --git a/src/_backend_agg_wrapper.h b/src/_backend_agg_wrapper.h deleted file mode 100644 index f625b4ce43b7..000000000000 --- a/src/_backend_agg_wrapper.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __BACKEND_AGG_WRAPPER_H__ -#define __BACKEND_AGG_WRAPPER_H__ - -#include "mplutils.h" -#include "py_converters.h" -#include "_backend_agg.h" - -extern "C" { - -typedef struct -{ - PyObject_HEAD; - RendererAgg *x; - Py_ssize_t shape[3]; - Py_ssize_t strides[3]; - Py_ssize_t suboffsets[3]; -} PyRendererAgg; - -typedef struct -{ - PyObject_HEAD; - BufferRegion *x; - Py_ssize_t shape[3]; - Py_ssize_t strides[3]; - Py_ssize_t suboffsets[3]; -} PyBufferRegion; -} - -#endif diff --git a/src/_tkagg.cpp b/src/_tkagg.cpp index 827e0db0deb0..a193410a4514 100644 --- a/src/_tkagg.cpp +++ b/src/_tkagg.cpp @@ -16,8 +16,6 @@ #include #include -#include "agg_basics.h" -#include "_backend_agg_wrapper.h" #include "py_converters.h" extern "C" @@ -50,14 +48,14 @@ static int PyAggImagePhoto(ClientData clientdata, Tcl_Interp *interp, int argc, { Tk_PhotoHandle photo; Tk_PhotoImageBlock block; - PyObject *aggo; + PyObject *bufferobj; // vars for blitting PyObject *bboxo; size_t aggl, bboxl; bool has_bbox; - agg::int8u *destbuffer; + uint8_t *destbuffer; int destx, desty, destwidth, destheight, deststride; //unsigned long tmp_ptr; @@ -84,12 +82,17 @@ static int PyAggImagePhoto(ClientData clientdata, Tcl_Interp *interp, int argc, Tcl_AppendResult(interp, "error casting pointer", (char *)NULL); return TCL_ERROR; } - aggo = (PyObject *)aggl; - - // TODO: This is really brittle and will break when RendererAgg - // comes in multiple flavors - RendererAgg *aggRenderer = ((PyRendererAgg *)(aggo))->x; - int srcheight = (int)aggRenderer->get_height(); + bufferobj = (PyObject *)aggl; + + numpy::array_view buffer; + try { + buffer = numpy::array_view(bufferobj); + } catch (...) { + Tcl_AppendResult(interp, "buffer is of wrong type", (char *)NULL); + PyErr_Clear(); + return TCL_ERROR; + } + int srcheight = buffer.dim(0); /* XXX insert aggRenderer type check */ @@ -127,13 +130,11 @@ static int PyAggImagePhoto(ClientData clientdata, Tcl_Interp *interp, int argc, return TCL_ERROR; } - agg::rendering_buffer destrbuf; - destrbuf.attach(destbuffer, destwidth, destheight, deststride); - pixfmt destpf(destrbuf); - renderer_base destrb(destpf); - - agg::rect_base region(destx, desty, (int)rect.x2, srcheight - (int)rect.y1); - destrb.copy_from(aggRenderer->renderingBuffer, ®ion, -destx, -desty); + for (int i = 0; i < destheight; ++i) { + memcpy(destbuffer + (deststride * i), + &buffer(i + desty, destx, 0), + deststride); + } } else { has_bbox = false; destbuffer = NULL; @@ -170,10 +171,10 @@ static int PyAggImagePhoto(ClientData clientdata, Tcl_Interp *interp, int argc, delete[] destbuffer; } else { - block.width = aggRenderer->get_width(); - block.height = aggRenderer->get_height(); + block.width = buffer.dim(1); + block.height = buffer.dim(0); block.pitch = (int)block.width * nval; - block.pixelPtr = aggRenderer->pixBuffer; + block.pixelPtr = buffer.data(); /* Clear current contents */ Tk_PhotoBlank(photo);