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 | pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy