1414import sys
1515import weakref
1616
17- import numpy as np
18- import PIL .Image
19-
2017import matplotlib as mpl
2118from matplotlib .backend_bases import (
2219 _Backend , FigureCanvasBase , FigureManagerBase ,
3027from matplotlib .transforms import Affine2D
3128
3229import wx
30+ import wx .svg
3331
3432_log = logging .getLogger (__name__ )
3533
@@ -473,10 +471,8 @@ def __init__(self, parent, id, figure=None):
473471 FigureCanvasBase .__init__ (self , figure )
474472 w , h = map (math .ceil , self .figure .bbox .size )
475473 # Set preferred window size hint - helps the sizer, if one is connected
476- wx .Panel .__init__ (self , parent , id , size = wx .Size (w , h ))
477- # Create the drawing bitmap
478- self .bitmap = wx .Bitmap (w , h )
479- _log .debug ("%s - __init__() - bitmap w:%d h:%d" , type (self ), w , h )
474+ wx .Panel .__init__ (self , parent , id , size = parent .FromDIP (wx .Size (w , h )))
475+ self .bitmap = None
480476 self ._isDrawn = False
481477 self ._rubberband_rect = None
482478 self ._rubberband_pen_black = wx .Pen ('BLACK' , 1 , wx .PENSTYLE_SHORT_DASH )
@@ -512,6 +508,12 @@ def __init__(self, parent, id, figure=None):
512508 self .SetBackgroundStyle (wx .BG_STYLE_PAINT ) # Reduce flicker.
513509 self .SetBackgroundColour (wx .WHITE )
514510
511+ if wx .Platform == '__WXMAC__' :
512+ # Initial scaling. Other platforms handle this automatically
513+ dpiScale = self .GetDPIScaleFactor ()
514+ self .SetInitialSize (self .GetSize ()* (1 / dpiScale ))
515+ self ._set_device_pixel_ratio (dpiScale )
516+
515517 def Copy_to_Clipboard (self , event = None ):
516518 """Copy bitmap of canvas to system clipboard."""
517519 bmp_obj = wx .BitmapDataObject ()
@@ -524,6 +526,12 @@ def Copy_to_Clipboard(self, event=None):
524526 wx .TheClipboard .Flush ()
525527 wx .TheClipboard .Close ()
526528
529+ def _update_device_pixel_ratio (self , * args , ** kwargs ):
530+ # We need to be careful in cases with mixed resolution displays if
531+ # device_pixel_ratio changes.
532+ if self ._set_device_pixel_ratio (self .GetDPIScaleFactor ()):
533+ self .draw ()
534+
527535 def draw_idle (self ):
528536 # docstring inherited
529537 _log .debug ("%s - draw_idle()" , type (self ))
@@ -631,7 +639,7 @@ def _on_size(self, event):
631639 In this application we attempt to resize to fit the window, so it
632640 is better to take the performance hit and redraw the whole window.
633641 """
634-
642+ self . _update_device_pixel_ratio ()
635643 _log .debug ("%s - _on_size()" , type (self ))
636644 sz = self .GetParent ().GetSizer ()
637645 if sz :
@@ -655,9 +663,10 @@ def _on_size(self, event):
655663 return # Empty figure
656664
657665 # Create a new, correctly sized bitmap
658- self .bitmap = wx .Bitmap (self ._width , self ._height )
659-
660666 dpival = self .figure .dpi
667+ if not wx .Platform == '__WXMSW__' :
668+ scale = self .GetDPIScaleFactor ()
669+ dpival /= scale
661670 winch = self ._width / dpival
662671 hinch = self ._height / dpival
663672 self .figure .set_size_inches (winch , hinch , forward = False )
@@ -712,7 +721,11 @@ def _mpl_coords(self, pos=None):
712721 else :
713722 x , y = pos .X , pos .Y
714723 # flip y so y=0 is bottom of canvas
715- return x , self .figure .bbox .height - y
724+ if not wx .Platform == '__WXMSW__' :
725+ scale = self .GetDPIScaleFactor ()
726+ return x * scale , self .figure .bbox .height - y * scale
727+ else :
728+ return x , self .figure .bbox .height - y
716729
717730 def _on_key_down (self , event ):
718731 """Capture key press."""
@@ -898,8 +911,8 @@ def __init__(self, num, fig, *, canvas_class):
898911 # On Windows, canvas sizing must occur after toolbar addition;
899912 # otherwise the toolbar further resizes the canvas.
900913 w , h = map (math .ceil , fig .bbox .size )
901- self .canvas .SetInitialSize (wx .Size (w , h ))
902- self .canvas .SetMinSize (( 2 , 2 ))
914+ self .canvas .SetInitialSize (self . FromDIP ( wx .Size (w , h ) ))
915+ self .canvas .SetMinSize (self . FromDIP ( wx . Size ( 2 , 2 ) ))
903916 self .canvas .SetFocus ()
904917
905918 self .Fit ()
@@ -1017,9 +1030,9 @@ def _set_frame_icon(frame):
10171030class NavigationToolbar2Wx (NavigationToolbar2 , wx .ToolBar ):
10181031 def __init__ (self , canvas , coordinates = True , * , style = wx .TB_BOTTOM ):
10191032 wx .ToolBar .__init__ (self , canvas .GetParent (), - 1 , style = style )
1033+ if wx .Platform == '__WXMAC__' :
1034+ self .SetToolBitmapSize (self .GetToolBitmapSize ()* self .GetDPIScaleFactor ())
10201035
1021- if 'wxMac' in wx .PlatformInfo :
1022- self .SetToolBitmapSize ((24 , 24 ))
10231036 self .wx_ids = {}
10241037 for text , tooltip_text , image_file , callback in self .toolitems :
10251038 if text is None :
@@ -1028,7 +1041,7 @@ def __init__(self, canvas, coordinates=True, *, style=wx.TB_BOTTOM):
10281041 self .wx_ids [text ] = (
10291042 self .AddTool (
10301043 - 1 ,
1031- bitmap = self ._icon (f"{ image_file } .png " ),
1044+ bitmap = self ._icon (f"{ image_file } .svg " ),
10321045 bmpDisabled = wx .NullBitmap ,
10331046 label = text , shortHelp = tooltip_text ,
10341047 kind = (wx .ITEM_CHECK if text in ["Pan" , "Zoom" ]
@@ -1054,9 +1067,7 @@ def _icon(name):
10541067 *name*, including the extension and relative to Matplotlib's "images"
10551068 data directory.
10561069 """
1057- pilimg = PIL .Image .open (cbook ._get_data_path ("images" , name ))
1058- # ensure RGBA as wx BitMap expects RGBA format
1059- image = np .array (pilimg .convert ("RGBA" ))
1070+ svg = cbook ._get_data_path ("images" , name ).read_bytes ()
10601071 try :
10611072 dark = wx .SystemSettings .GetAppearance ().IsDark ()
10621073 except AttributeError : # wxpython < 4.1
@@ -1068,11 +1079,9 @@ def _icon(name):
10681079 fg_lum = (.299 * fg .red + .587 * fg .green + .114 * fg .blue ) / 255
10691080 dark = fg_lum - bg_lum > .2
10701081 if dark :
1071- fg = wx .SystemSettings .GetColour (wx .SYS_COLOUR_WINDOWTEXT )
1072- black_mask = (image [..., :3 ] == 0 ).all (axis = - 1 )
1073- image [black_mask , :3 ] = (fg .Red (), fg .Green (), fg .Blue ())
1074- return wx .Bitmap .FromBufferRGBA (
1075- image .shape [1 ], image .shape [0 ], image .tobytes ())
1082+ svg = svg .replace (b'fill:black;' , b'fill:white;' )
1083+ toolbarIconSize = wx .ArtProvider ().GetDIPSizeHint (wx .ART_TOOLBAR )
1084+ return wx .BitmapBundle .FromSVG (svg , toolbarIconSize )
10761085
10771086 def _update_buttons_checked (self ):
10781087 if "Pan" in self .wx_ids :
@@ -1123,7 +1132,9 @@ def save_figure(self, *args):
11231132
11241133 def draw_rubberband (self , event , x0 , y0 , x1 , y1 ):
11251134 height = self .canvas .figure .bbox .height
1126- self .canvas ._rubberband_rect = (x0 , height - y0 , x1 , height - y1 )
1135+ sf = self .GetDPIScaleFactor ()
1136+ self .canvas ._rubberband_rect = (x0 / sf , (height - y0 )/ sf ,
1137+ x1 / sf , (height - y1 )/ sf )
11271138 self .canvas .Refresh ()
11281139
11291140 def remove_rubberband (self ):
0 commit comments