Skip to content

Commit ab61cbe

Browse files
committed
Convert macosx backend to use device_pixel_ratio
This was not originally implemented in #19126, but causes some inconsistencies with other backends. This also sets the initial scale as implemented in #18274.
1 parent a1eef38 commit ab61cbe

File tree

2 files changed

+38
-23
lines changed

2 files changed

+38
-23
lines changed

lib/matplotlib/backends/backend_macosx.py

+5-14
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,6 @@ def __init__(self, figure):
3030
FigureCanvasBase.__init__(self, figure)
3131
width, height = self.get_width_height()
3232
_macosx.FigureCanvas.__init__(self, width, height)
33-
self._dpi_ratio = 1.0
34-
35-
def _set_device_scale(self, value):
36-
if self._dpi_ratio != value:
37-
# Need the new value in place before setting figure.dpi, which
38-
# will trigger a resize
39-
self._dpi_ratio, old_value = value, self._dpi_ratio
40-
self.figure.dpi = self.figure.dpi / old_value * self._dpi_ratio
4133

4234
def set_cursor(self, cursor):
4335
# docstring inherited
@@ -60,12 +52,11 @@ def blit(self, bbox=None):
6052
self.draw_idle()
6153

6254
def resize(self, width, height):
63-
dpi = self.figure.dpi
64-
width /= dpi
65-
height /= dpi
66-
self.figure.set_size_inches(width * self._dpi_ratio,
67-
height * self._dpi_ratio,
68-
forward=False)
55+
# Size from macOS is logical pixels, dpi is physical.
56+
scale = self.figure.dpi / self.device_pixel_ratio
57+
width /= scale
58+
height /= scale
59+
self.figure.set_size_inches(width, height, forward=False)
6960
FigureCanvasBase.resize_event(self)
7061
self.draw_idle()
7162

src/_macosx.m

+33-9
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ @interface View : NSView <NSWindowDelegate>
237237
}
238238
- (void)dealloc;
239239
- (void)drawRect:(NSRect)rect;
240+
- (void)updateDevicePixelRatio:(double)scale;
241+
- (void)windowDidChangeBackingProperties:(NSNotification*)notification;
240242
- (void)windowDidResize:(NSNotification*)notification;
241243
- (View*)initWithFrame:(NSRect)rect;
242244
- (void)setCanvas: (PyObject*)newCanvas;
@@ -706,6 +708,7 @@ static CGFloat _get_device_scale(CGContextRef cr)
706708
[window setDelegate: view];
707709
[window makeFirstResponder: view];
708710
[[window contentView] addSubview: view];
711+
[view updateDevicePixelRatio: [window backingScaleFactor]];
709712

710713
return 0;
711714
}
@@ -801,6 +804,9 @@ static CGFloat _get_device_scale(CGContextRef cr)
801804
Window* window = self->window;
802805
if(window)
803806
{
807+
CGFloat device_pixel_ratio = [window backingScaleFactor];
808+
width /= device_pixel_ratio;
809+
height /= device_pixel_ratio;
804810
// 36 comes from hard-coded size of toolbar later in code
805811
[window setContentSize: NSMakeSize(width, height + 36.)];
806812
}
@@ -1654,15 +1660,6 @@ -(void)drawRect:(NSRect)rect
16541660

16551661
CGContextRef cr = [[NSGraphicsContext currentContext] CGContext];
16561662

1657-
double new_device_scale = _get_device_scale(cr);
1658-
1659-
if (device_scale != new_device_scale) {
1660-
device_scale = new_device_scale;
1661-
if (!PyObject_CallMethod(canvas, "_set_device_scale", "d", device_scale, NULL)) {
1662-
PyErr_Print();
1663-
goto exit;
1664-
}
1665-
}
16661663
if (!(renderer = PyObject_CallMethod(canvas, "_draw", "", NULL))
16671664
|| !(renderer_buffer = PyObject_GetAttrString(renderer, "_renderer"))) {
16681665
PyErr_Print();
@@ -1683,6 +1680,33 @@ -(void)drawRect:(NSRect)rect
16831680
PyGILState_Release(gstate);
16841681
}
16851682

1683+
- (void)updateDevicePixelRatio:(double)scale
1684+
{
1685+
PyObject* change = NULL;
1686+
PyGILState_STATE gstate = PyGILState_Ensure();
1687+
1688+
device_scale = scale;
1689+
if (!(change = PyObject_CallMethod(canvas, "_set_device_pixel_ratio", "d", device_scale, NULL))) {
1690+
PyErr_Print();
1691+
goto exit;
1692+
}
1693+
if (PyObject_IsTrue(change)) {
1694+
[self setNeedsDisplay: YES];
1695+
}
1696+
1697+
exit:
1698+
Py_XDECREF(change);
1699+
1700+
PyGILState_Release(gstate);
1701+
}
1702+
1703+
- (void)windowDidChangeBackingProperties:(NSNotification *)notification
1704+
{
1705+
Window* window = [notification object];
1706+
1707+
[self updateDevicePixelRatio: [window backingScaleFactor]];
1708+
}
1709+
16861710
- (void)windowDidResize: (NSNotification*)notification
16871711
{
16881712
int width, height;

0 commit comments

Comments
 (0)