From bce36433f20a0539b5301b4244e913d9c28ffed4 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 2 Apr 2024 04:16:03 -0400 Subject: [PATCH 1/3] wx: Fix file extension for toolmanager-style toolbar Fixes AppVeyor failure noted in https://github.com/matplotlib/matplotlib/pull/26710#issuecomment-2031349546 --- lib/matplotlib/backends/backend_wx.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index 0ae70707ac0d..7db9d686baae 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -1161,6 +1161,8 @@ def set_history_buttons(self): # tools for matplotlib.backend_managers.ToolManager: class ToolbarWx(ToolContainerBase, wx.ToolBar): + _icon_extension = '.svg' + def __init__(self, toolmanager, parent=None, style=wx.TB_BOTTOM): if parent is None: parent = toolmanager.canvas.GetParent() From 39f28ccfb806e1dd63c4e8665803db98d36455a6 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 3 Apr 2024 01:52:31 -0400 Subject: [PATCH 2/3] wx: Continue supporting non-SVG for toolmanager's sake This falls back to the previous dark-mode setup for any other formats. It won't be HiDPI compatible, but that's probably not possible for raster formats. --- lib/matplotlib/backends/backend_wx.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index 7db9d686baae..cd2fe215464c 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -14,6 +14,9 @@ import sys import weakref +import numpy as np +import PIL.Image + import matplotlib as mpl from matplotlib.backend_bases import ( _Backend, FigureCanvasBase, FigureManagerBase, @@ -1071,7 +1074,6 @@ def _icon(name): *name*, including the extension and relative to Matplotlib's "images" data directory. """ - svg = cbook._get_data_path("images", name).read_bytes() try: dark = wx.SystemSettings.GetAppearance().IsDark() except AttributeError: # wxpython < 4.1 @@ -1082,10 +1084,24 @@ def _icon(name): bg_lum = (.299 * bg.red + .587 * bg.green + .114 * bg.blue) / 255 fg_lum = (.299 * fg.red + .587 * fg.green + .114 * fg.blue) / 255 dark = fg_lum - bg_lum > .2 - if dark: - svg = svg.replace(b'fill:black;', b'fill:white;') - toolbarIconSize = wx.ArtProvider().GetDIPSizeHint(wx.ART_TOOLBAR) - return wx.BitmapBundle.FromSVG(svg, toolbarIconSize) + + path = cbook._get_data_path('images', name) + if path.suffix == '.svg': + svg = path.read_bytes() + if dark: + svg = svg.replace(b'fill:black;', b'fill:white;') + toolbarIconSize = wx.ArtProvider().GetDIPSizeHint(wx.ART_TOOLBAR) + return wx.BitmapBundle.FromSVG(svg, toolbarIconSize) + else: + pilimg = PIL.Image.open(path) + # ensure RGBA as wx BitMap expects RGBA format + image = np.array(pilimg.convert("RGBA")) + if dark: + fg = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT) + black_mask = (image[..., :3] == 0).all(axis=-1) + image[black_mask, :3] = (fg.Red(), fg.Green(), fg.Blue()) + return wx.Bitmap.FromBufferRGBA( + image.shape[1], image.shape[0], image.tobytes()) def _update_buttons_checked(self): if "Pan" in self.wx_ids: From d8815fea31d272af198c691863d58ea73c45628a Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 3 Apr 2024 15:40:28 -0400 Subject: [PATCH 3/3] wx: Fix the zoom rubberband with toolmanager --- lib/matplotlib/backends/backend_wx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index cd2fe215464c..8064511ac28a 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -1152,7 +1152,7 @@ def save_figure(self, *args): def draw_rubberband(self, event, x0, y0, x1, y1): height = self.canvas.figure.bbox.height - sf = 1 if wx.Platform == '__WXMSW__' else self.GetDPIScaleFactor() + sf = 1 if wx.Platform == '__WXMSW__' else self.canvas.GetDPIScaleFactor() self.canvas._rubberband_rect = (x0/sf, (height - y0)/sf, x1/sf, (height - y1)/sf) self.canvas.Refresh()