From 1fbe7feb4bbeccd9ed7694b17454740803d5abcc Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Sun, 15 Aug 2021 07:48:37 -0400 Subject: [PATCH 01/13] find and load Tk_PhotoPutBlock --- src/_tkagg.cpp | 6 ++++++ src/_tkmini.h | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/src/_tkagg.cpp b/src/_tkagg.cpp index fc1fe2d82787..31afd8c1e324 100644 --- a/src/_tkagg.cpp +++ b/src/_tkagg.cpp @@ -50,6 +50,7 @@ static int convert_voidptr(PyObject *obj, void *p) // Global vars for Tk functions. We load these symbols from the tkinter // extension module or loaded Tk libraries at run-time. static Tk_FindPhoto_t TK_FIND_PHOTO; +static Tk_PhotoPutBlock_t TK_PHOTO_PUT_BLOCK; static Tk_PhotoPutBlock_NoComposite_t TK_PHOTO_PUT_BLOCK_NO_COMPOSITE; #ifdef WIN32_DLL // Global vars for Tcl functions. We load these symbols from the tkinter @@ -219,6 +220,8 @@ int load_tk(T lib) return !!(TK_FIND_PHOTO = (Tk_FindPhoto_t)dlsym(lib, "Tk_FindPhoto")) + + !!(TK_PHOTO_PUT_BLOCK = + (Tk_PhotoPutBlock_t)dlsym(lib, "Tk_PhotoPutBlock")) + !!(TK_PHOTO_PUT_BLOCK_NO_COMPOSITE = (Tk_PhotoPutBlock_NoComposite_t)dlsym(lib, "Tk_PhotoPutBlock_NoComposite")); } @@ -341,6 +344,9 @@ PyMODINIT_FUNC PyInit__tkagg(void) } else if (!TK_FIND_PHOTO) { PyErr_SetString(PyExc_RuntimeError, "Failed to load Tk_FindPhoto"); return NULL; + } else if (!TK_PHOTO_PUT_BLOCK) { + PyErr_SetString(PyExc_RuntimeError, "Failed to load Tk_PhotoPutBlock"); + return NULL; } else if (!TK_PHOTO_PUT_BLOCK_NO_COMPOSITE) { PyErr_SetString(PyExc_RuntimeError, "Failed to load Tk_PhotoPutBlock_NoComposite"); return NULL; diff --git a/src/_tkmini.h b/src/_tkmini.h index e45184166b67..996b2618bc3e 100644 --- a/src/_tkmini.h +++ b/src/_tkmini.h @@ -86,10 +86,17 @@ typedef struct Tk_PhotoImageBlock int offset[4]; } Tk_PhotoImageBlock; +#define TK_PHOTO_COMPOSITE_OVERLAY 0 +#define TK_PHOTO_COMPOSITE_SET 1 + /* Typedefs derived from function signatures in Tk header */ /* Tk_FindPhoto typedef */ typedef Tk_PhotoHandle (*Tk_FindPhoto_t) (Tcl_Interp *interp, const char *imageName); +/* Tk_PhotoPutBLock typedef */ +typedef int (*Tk_PhotoPutBlock_t) (Tcl_Interp *interp, Tk_PhotoHandle handle, + Tk_PhotoImageBlock *blockPtr, int x, int y, + int width, int height); /* Tk_PhotoPutBLock_NoComposite typedef */ typedef void (*Tk_PhotoPutBlock_NoComposite_t) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, From 8f4ed5d9cb599c9e323faa5317bdf7265edccb25 Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Sun, 15 Aug 2021 08:50:11 -0400 Subject: [PATCH 02/13] Substitute TkPhotoPutBlock Also release GIL Currently, drawing an equivalence between blank and TK_PHOTO_COMPOSITE_SET which may not be entirely accurate --- lib/matplotlib/backends/_backend_tk.py | 7 +------ src/_tkagg.cpp | 15 ++++++++++++--- src/_tkmini.h | 6 +++--- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/lib/matplotlib/backends/_backend_tk.py b/lib/matplotlib/backends/_backend_tk.py index 28c5ae737c9b..f0d488f18b96 100644 --- a/lib/matplotlib/backends/_backend_tk.py +++ b/lib/matplotlib/backends/_backend_tk.py @@ -60,15 +60,10 @@ def _blit(argsid): *argsid* is a unique string identifier to fetch the correct arguments from the ``_blit_args`` dict, since arguments cannot be passed directly. - - photoimage blanking must occur in the same event and thread as blitting - to avoid flickering. """ photoimage, dataptr, offsets, bboxptr, blank = _blit_args.pop(argsid) - if blank: - photoimage.blank() _tkagg.blit( - photoimage.tk.interpaddr(), str(photoimage), dataptr, offsets, bboxptr) + photoimage.tk.interpaddr(), str(photoimage), dataptr, blank, offsets, bboxptr) def blit(photoimage, aggimage, offsets, bbox=None): diff --git a/src/_tkagg.cpp b/src/_tkagg.cpp index 31afd8c1e324..3e2508d5ed44 100644 --- a/src/_tkagg.cpp +++ b/src/_tkagg.cpp @@ -64,13 +64,15 @@ static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) char const *photo_name; int height, width; unsigned char *data_ptr; + int blank; int o0, o1, o2, o3; int x1, x2, y1, y2; Tk_PhotoHandle photo; Tk_PhotoImageBlock block; - if (!PyArg_ParseTuple(args, "O&s(iiO&)(iiii)(iiii):blit", + if (!PyArg_ParseTuple(args, "O&s(iiO&)i(iiii)(iiii):blit", convert_voidptr, &interp, &photo_name, &height, &width, convert_voidptr, &data_ptr, + &blank, &o0, &o1, &o2, &o3, &x1, &x2, &y1, &y2)) { goto exit; @@ -83,7 +85,12 @@ static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) PyErr_SetString(PyExc_ValueError, "Attempting to draw out of bounds"); goto exit; } + if (blank != TK_PHOTO_COMPOSITE_OVERLAY && blank != TK_PHOTO_COMPOSITE_SET){ + PyErr_SetString(PyExc_ValueError, "Invalid blank argument"); + goto exit; + } + Py_BEGIN_ALLOW_THREADS block.pixelPtr = data_ptr + 4 * ((height - y2) * width + x1); block.width = x2 - x1; block.height = y2 - y1; @@ -93,8 +100,10 @@ static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) block.offset[1] = o1; block.offset[2] = o2; block.offset[3] = o3; - TK_PHOTO_PUT_BLOCK_NO_COMPOSITE( - photo, &block, x1, height - y2, x2 - x1, y2 - y1); + TK_PHOTO_PUT_BLOCK( + interp, photo, &block, x1, height - y2, x2 - x1, y2 - y1, blank); + Py_END_ALLOW_THREADS + exit: if (PyErr_Occurred()) { return NULL; diff --git a/src/_tkmini.h b/src/_tkmini.h index 996b2618bc3e..97a4fe60e4b9 100644 --- a/src/_tkmini.h +++ b/src/_tkmini.h @@ -86,8 +86,8 @@ typedef struct Tk_PhotoImageBlock int offset[4]; } Tk_PhotoImageBlock; -#define TK_PHOTO_COMPOSITE_OVERLAY 0 -#define TK_PHOTO_COMPOSITE_SET 1 +#define TK_PHOTO_COMPOSITE_OVERLAY 0 // don't blank +#define TK_PHOTO_COMPOSITE_SET 1 // blank /* Typedefs derived from function signatures in Tk header */ /* Tk_FindPhoto typedef */ @@ -96,7 +96,7 @@ typedef Tk_PhotoHandle (*Tk_FindPhoto_t) (Tcl_Interp *interp, const char /* Tk_PhotoPutBLock typedef */ typedef int (*Tk_PhotoPutBlock_t) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, - int width, int height); + int width, int height, int compRule); /* Tk_PhotoPutBLock_NoComposite typedef */ typedef void (*Tk_PhotoPutBlock_NoComposite_t) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, From 422b8d775db900c2e1ddf9c6c89bc254060fc2c7 Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Sun, 15 Aug 2021 09:18:12 -0400 Subject: [PATCH 03/13] Delete old, deprecated api --- src/_tkagg.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/_tkagg.cpp b/src/_tkagg.cpp index 3e2508d5ed44..3e1f5cff0c7c 100644 --- a/src/_tkagg.cpp +++ b/src/_tkagg.cpp @@ -51,7 +51,6 @@ static int convert_voidptr(PyObject *obj, void *p) // extension module or loaded Tk libraries at run-time. static Tk_FindPhoto_t TK_FIND_PHOTO; static Tk_PhotoPutBlock_t TK_PHOTO_PUT_BLOCK; -static Tk_PhotoPutBlock_NoComposite_t TK_PHOTO_PUT_BLOCK_NO_COMPOSITE; #ifdef WIN32_DLL // Global vars for Tcl functions. We load these symbols from the tkinter // extension module or loaded Tcl libraries at run-time. @@ -230,9 +229,7 @@ int load_tk(T lib) !!(TK_FIND_PHOTO = (Tk_FindPhoto_t)dlsym(lib, "Tk_FindPhoto")) + !!(TK_PHOTO_PUT_BLOCK = - (Tk_PhotoPutBlock_t)dlsym(lib, "Tk_PhotoPutBlock")) + - !!(TK_PHOTO_PUT_BLOCK_NO_COMPOSITE = - (Tk_PhotoPutBlock_NoComposite_t)dlsym(lib, "Tk_PhotoPutBlock_NoComposite")); + (Tk_PhotoPutBlock_t)dlsym(lib, "Tk_PhotoPutBlock")); } #ifdef WIN32_DLL @@ -356,9 +353,6 @@ PyMODINIT_FUNC PyInit__tkagg(void) } else if (!TK_PHOTO_PUT_BLOCK) { PyErr_SetString(PyExc_RuntimeError, "Failed to load Tk_PhotoPutBlock"); return NULL; - } else if (!TK_PHOTO_PUT_BLOCK_NO_COMPOSITE) { - PyErr_SetString(PyExc_RuntimeError, "Failed to load Tk_PhotoPutBlock_NoComposite"); - return NULL; } return PyModule_Create(&_tkagg_module); } From 2efc4f5c1300d7773d19fa3ba66c0c3ed3f6d1de Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Sun, 15 Aug 2021 10:00:46 -0400 Subject: [PATCH 04/13] more descriptive names for composition rule --- lib/matplotlib/backends/_backend_tk.py | 14 ++++++++------ src/_tkagg.cpp | 10 +++++----- src/_tkmini.h | 4 ++-- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/matplotlib/backends/_backend_tk.py b/lib/matplotlib/backends/_backend_tk.py index f0d488f18b96..0c2ccfeadb4c 100644 --- a/lib/matplotlib/backends/_backend_tk.py +++ b/lib/matplotlib/backends/_backend_tk.py @@ -53,6 +53,8 @@ def _restore_foreground_window_at_end(): # Initialize to a non-empty string that is not a Tcl command _blit_tcl_name = "mpl_blit_" + uuid.uuid4().hex +TK_PHOTO_COMPOSITE_OVERLAY = 0 # apply transparency rules pixel-wise +TK_PHOTO_COMPOSITE_SET = 1 # set image buffer directly def _blit(argsid): """ @@ -61,9 +63,9 @@ def _blit(argsid): *argsid* is a unique string identifier to fetch the correct arguments from the ``_blit_args`` dict, since arguments cannot be passed directly. """ - photoimage, dataptr, offsets, bboxptr, blank = _blit_args.pop(argsid) + photoimage, dataptr, offsets, bboxptr, comp_rule = _blit_args.pop(argsid) _tkagg.blit( - photoimage.tk.interpaddr(), str(photoimage), dataptr, blank, offsets, bboxptr) + photoimage.tk.interpaddr(), str(photoimage), dataptr, comp_rule, offsets, bboxptr) def blit(photoimage, aggimage, offsets, bbox=None): @@ -76,7 +78,7 @@ def blit(photoimage, aggimage, offsets, bbox=None): for big-endian ARGB32 (i.e. ARGB8888) data. If *bbox* is passed, it defines the region that gets blitted. That region - will NOT be blanked before blitting. + will be composed with the previous data according to the alpha channel. Tcl events must be dispatched to trigger a blit from a non-Tcl thread. """ @@ -90,10 +92,10 @@ def blit(photoimage, aggimage, offsets, bbox=None): y1 = max(math.floor(y1), 0) y2 = min(math.ceil(y2), height) bboxptr = (x1, x2, y1, y2) - blank = False + comp_rule = TK_PHOTO_COMPOSITE_OVERLAY else: bboxptr = (0, width, 0, height) - blank = True + comp_rule = TK_PHOTO_COMPOSITE_SET # NOTE: _tkagg.blit is thread unsafe and will crash the process if called # from a thread (GH#13293). Instead of blanking and blitting here, @@ -102,7 +104,7 @@ def blit(photoimage, aggimage, offsets, bbox=None): # tkapp.call coerces all arguments to strings, so to avoid string parsing # within _blit, pack up the arguments into a global data structure. - args = photoimage, dataptr, offsets, bboxptr, blank + args = photoimage, dataptr, offsets, bboxptr, comp_rule # Need a unique key to avoid thread races. # Again, make the key a string to avoid string parsing in _blit. argsid = str(id(args)) diff --git a/src/_tkagg.cpp b/src/_tkagg.cpp index 3e1f5cff0c7c..3581552efca6 100644 --- a/src/_tkagg.cpp +++ b/src/_tkagg.cpp @@ -63,7 +63,7 @@ static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) char const *photo_name; int height, width; unsigned char *data_ptr; - int blank; + int comp_rule; int o0, o1, o2, o3; int x1, x2, y1, y2; Tk_PhotoHandle photo; @@ -71,7 +71,7 @@ static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "O&s(iiO&)i(iiii)(iiii):blit", convert_voidptr, &interp, &photo_name, &height, &width, convert_voidptr, &data_ptr, - &blank, + &comp_rule, &o0, &o1, &o2, &o3, &x1, &x2, &y1, &y2)) { goto exit; @@ -84,8 +84,8 @@ static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) PyErr_SetString(PyExc_ValueError, "Attempting to draw out of bounds"); goto exit; } - if (blank != TK_PHOTO_COMPOSITE_OVERLAY && blank != TK_PHOTO_COMPOSITE_SET){ - PyErr_SetString(PyExc_ValueError, "Invalid blank argument"); + if (comp_rule != TK_PHOTO_COMPOSITE_OVERLAY && comp_rule != TK_PHOTO_COMPOSITE_SET){ + PyErr_SetString(PyExc_ValueError, "Invalid comp_rule argument"); goto exit; } @@ -100,7 +100,7 @@ static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) block.offset[2] = o2; block.offset[3] = o3; TK_PHOTO_PUT_BLOCK( - interp, photo, &block, x1, height - y2, x2 - x1, y2 - y1, blank); + interp, photo, &block, x1, height - y2, x2 - x1, y2 - y1, comp_rule); Py_END_ALLOW_THREADS exit: diff --git a/src/_tkmini.h b/src/_tkmini.h index 97a4fe60e4b9..09d41dc24fdf 100644 --- a/src/_tkmini.h +++ b/src/_tkmini.h @@ -86,8 +86,8 @@ typedef struct Tk_PhotoImageBlock int offset[4]; } Tk_PhotoImageBlock; -#define TK_PHOTO_COMPOSITE_OVERLAY 0 // don't blank -#define TK_PHOTO_COMPOSITE_SET 1 // blank +#define TK_PHOTO_COMPOSITE_OVERLAY 0 // apply transparency rules pixel-wise +#define TK_PHOTO_COMPOSITE_SET 1 // set image buffer directly /* Typedefs derived from function signatures in Tk header */ /* Tk_FindPhoto typedef */ From 5709e7b229e2e2cff02670a452e10af8794dcbb6 Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Sun, 15 Aug 2021 10:01:11 -0400 Subject: [PATCH 05/13] fix test --- lib/matplotlib/tests/test_backend_tk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/tests/test_backend_tk.py b/lib/matplotlib/tests/test_backend_tk.py index 4c714b303bd1..7c6a051df9ad 100644 --- a/lib/matplotlib/tests/test_backend_tk.py +++ b/lib/matplotlib/tests/test_backend_tk.py @@ -80,7 +80,7 @@ def test_blit(): # pragma: no cover for bad_box in bad_boxes: try: _tkagg.blit( - photoimage.tk.interpaddr(), str(photoimage), dataptr, + photoimage.tk.interpaddr(), str(photoimage), dataptr, 0, (0, 1, 2, 3), bad_box) except ValueError: print("success") From dd447a0c66e6bf865fd2fff512ea20620534e3f8 Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Sun, 15 Aug 2021 10:42:03 -0400 Subject: [PATCH 06/13] flake8 --- lib/matplotlib/backends/_backend_tk.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/backends/_backend_tk.py b/lib/matplotlib/backends/_backend_tk.py index 0c2ccfeadb4c..e07c089676b4 100644 --- a/lib/matplotlib/backends/_backend_tk.py +++ b/lib/matplotlib/backends/_backend_tk.py @@ -56,6 +56,7 @@ def _restore_foreground_window_at_end(): TK_PHOTO_COMPOSITE_OVERLAY = 0 # apply transparency rules pixel-wise TK_PHOTO_COMPOSITE_SET = 1 # set image buffer directly + def _blit(argsid): """ Thin wrapper to blit called via tkapp.call. @@ -64,8 +65,8 @@ def _blit(argsid): the ``_blit_args`` dict, since arguments cannot be passed directly. """ photoimage, dataptr, offsets, bboxptr, comp_rule = _blit_args.pop(argsid) - _tkagg.blit( - photoimage.tk.interpaddr(), str(photoimage), dataptr, comp_rule, offsets, bboxptr) + _tkagg.blit(photoimage.tk.interpaddr(), str(photoimage), dataptr, + comp_rule, offsets, bboxptr) def blit(photoimage, aggimage, offsets, bbox=None): From 9eb95f5d89bce92d2254ef3b655a83d4b089bd9e Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Sun, 15 Aug 2021 12:58:42 -0400 Subject: [PATCH 07/13] propagate memory errors from Tcl --- src/_tkagg.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/_tkagg.cpp b/src/_tkagg.cpp index 3581552efca6..cc626adf8b0b 100644 --- a/src/_tkagg.cpp +++ b/src/_tkagg.cpp @@ -64,6 +64,7 @@ static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) int height, width; unsigned char *data_ptr; int comp_rule; + int put_retval; int o0, o1, o2, o3; int x1, x2, y1, y2; Tk_PhotoHandle photo; @@ -99,9 +100,12 @@ static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) block.offset[1] = o1; block.offset[2] = o2; block.offset[3] = o3; - TK_PHOTO_PUT_BLOCK( + put_retval = TK_PHOTO_PUT_BLOCK( interp, photo, &block, x1, height - y2, x2 - x1, y2 - y1, comp_rule); Py_END_ALLOW_THREADS + if (put_retval) { + return PyErr_NoMemory(); + } exit: if (PyErr_Occurred()) { From 800a8ee12587c45baf9a881158409c5e0ab086de Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Mon, 16 Aug 2021 06:34:25 -0400 Subject: [PATCH 08/13] remove unneeded typedef --- src/_tkmini.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/_tkmini.h b/src/_tkmini.h index 09d41dc24fdf..910ef2a6e101 100644 --- a/src/_tkmini.h +++ b/src/_tkmini.h @@ -97,10 +97,6 @@ typedef Tk_PhotoHandle (*Tk_FindPhoto_t) (Tcl_Interp *interp, const char typedef int (*Tk_PhotoPutBlock_t) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); -/* Tk_PhotoPutBLock_NoComposite typedef */ -typedef void (*Tk_PhotoPutBlock_NoComposite_t) (Tk_PhotoHandle handle, - Tk_PhotoImageBlock *blockPtr, int x, int y, - int width, int height); #ifdef WIN32_DLL /* Typedefs derived from function signatures in Tcl header */ From 5376ab4518ff079361fa801d8255634c9f28b927 Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Mon, 16 Aug 2021 06:34:38 -0400 Subject: [PATCH 09/13] formatting --- src/_tkagg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_tkagg.cpp b/src/_tkagg.cpp index cc626adf8b0b..157fdb001866 100644 --- a/src/_tkagg.cpp +++ b/src/_tkagg.cpp @@ -85,7 +85,7 @@ static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) PyErr_SetString(PyExc_ValueError, "Attempting to draw out of bounds"); goto exit; } - if (comp_rule != TK_PHOTO_COMPOSITE_OVERLAY && comp_rule != TK_PHOTO_COMPOSITE_SET){ + if (comp_rule != TK_PHOTO_COMPOSITE_OVERLAY && comp_rule != TK_PHOTO_COMPOSITE_SET) { PyErr_SetString(PyExc_ValueError, "Invalid comp_rule argument"); goto exit; } From bb611bf778d85db1411a46dffb25f0339dceee76 Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Mon, 16 Aug 2021 09:03:49 -0400 Subject: [PATCH 10/13] Update dependencies.rst --- doc/devel/dependencies.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/devel/dependencies.rst b/doc/devel/dependencies.rst index 33a35b3dde1a..0a3c40da5524 100644 --- a/doc/devel/dependencies.rst +++ b/doc/devel/dependencies.rst @@ -40,7 +40,7 @@ Matplotlib figures can be rendered to various user interfaces. See :ref:`what-is-a-backend` for more details on the optional Matplotlib backends and the capabilities they provide. -* Tk_ (>= 8.3, != 8.6.0 or 8.6.1) [#]_: for the Tk-based backends. +* Tk_ (>= 8.4, != 8.6.0 or 8.6.1) [#]_: for the Tk-based backends. * PyQt6_ (>= 6.1), PySide6_, PyQt5_, or PySide2_: for the Qt-based backends. * PyGObject_: for the GTK3-based backends [#]_. * wxPython_ (>= 4) [#]_: for the wx-based backends. From ef27e2bbeb328a586325ad4a90a22fadeaf68ef4 Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Mon, 16 Aug 2021 09:14:12 -0400 Subject: [PATCH 11/13] Create 20840-RJS.rst --- doc/api/next_api_changes/development/20840-RJS.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 doc/api/next_api_changes/development/20840-RJS.rst diff --git a/doc/api/next_api_changes/development/20840-RJS.rst b/doc/api/next_api_changes/development/20840-RJS.rst new file mode 100644 index 000000000000..048d159c9758 --- /dev/null +++ b/doc/api/next_api_changes/development/20840-RJS.rst @@ -0,0 +1,13 @@ +Increase to minimum supported optional dependencies +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For Maptlotlib 3.5, the :ref:`minimum supported versions of optional dependencies ` +are being bumped: + ++------------+-----------------+---------------+ +| Dependency | min in mpl3.4 | min in mpl3.5 | ++============+=================+===============+ +| Tk | 8.3 | 8.4 | ++------------+-----------------+---------------+ + +This is consistent with our :ref:`min_deps_policy` From 8a051275c53c0c15b1976bf7837a3243839abc22 Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Thu, 19 Aug 2021 06:33:59 -0400 Subject: [PATCH 12/13] use Tcl return codes --- src/_tkagg.cpp | 2 +- src/_tkmini.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/_tkagg.cpp b/src/_tkagg.cpp index 157fdb001866..8c5ba4a4c800 100644 --- a/src/_tkagg.cpp +++ b/src/_tkagg.cpp @@ -103,7 +103,7 @@ static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) put_retval = TK_PHOTO_PUT_BLOCK( interp, photo, &block, x1, height - y2, x2 - x1, y2 - y1, comp_rule); Py_END_ALLOW_THREADS - if (put_retval) { + if (put_retval == TCL_ERROR) { return PyErr_NoMemory(); } diff --git a/src/_tkmini.h b/src/_tkmini.h index 910ef2a6e101..be7c13fa14d5 100644 --- a/src/_tkmini.h +++ b/src/_tkmini.h @@ -88,6 +88,8 @@ typedef struct Tk_PhotoImageBlock #define TK_PHOTO_COMPOSITE_OVERLAY 0 // apply transparency rules pixel-wise #define TK_PHOTO_COMPOSITE_SET 1 // set image buffer directly +#define TCL_OK 0 +#define TCL_ERROR 1 /* Typedefs derived from function signatures in Tk header */ /* Tk_FindPhoto typedef */ From 0919f3e4a838d3fc04331fc2598992b3aea94d8e Mon Sep 17 00:00:00 2001 From: richardsheridan Date: Thu, 19 Aug 2021 06:37:14 -0400 Subject: [PATCH 13/13] typo --- doc/api/next_api_changes/development/20840-RJS.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/next_api_changes/development/20840-RJS.rst b/doc/api/next_api_changes/development/20840-RJS.rst index 048d159c9758..443331d7c887 100644 --- a/doc/api/next_api_changes/development/20840-RJS.rst +++ b/doc/api/next_api_changes/development/20840-RJS.rst @@ -1,8 +1,8 @@ Increase to minimum supported optional dependencies ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -For Maptlotlib 3.5, the :ref:`minimum supported versions of optional dependencies ` -are being bumped: +For Matplotlib 3.5, the :ref:`minimum supported versions of optional dependencies +` are being bumped: +------------+-----------------+---------------+ | Dependency | min in mpl3.4 | min in mpl3.5 |