8000 Merge pull request #6956 from jenshnielsen/backport5383 · Kojoley/matplotlib@0bf79ea · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 0bf79ea

Browse files
authored
Merge pull request matplotlib#6956 from jenshnielsen/backport5383
Backport matplotlib#5383 Needed for retina support in ipympl
2 parents 1f6fb31 + 5bf037e commit 0bf79ea

File tree

4 files changed

+50
-12
lines changed

4 files changed

+50
-12
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Support for HiDPI (Retina) displays in the NbAgg and WebAgg backends
2+
--------------------------------------------------------------------
3+
4+
The NbAgg and WebAgg backends will now use the full resolution of your
5+
high-pixel-density display.

lib/matplotlib/backends/backend_webagg_core.py

Lines changed: 19 additions & 2 deletions
< 10000 /div>
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ def __init__(self, *args, **kwargs):
159159
# to the connected clients.
160160
self._current_image_mode = 'full'
161161

162+
# Store the DPI ratio of the browser. This is the scaling that
163+
# occurs automatically for all images on a HiDPI display.
164+
self._dpi_ratio = 1
165+
162166
def show(self):
163167
# show the figure window
164168
from matplotlib.pyplot import show
@@ -334,7 +338,7 @@ def handle_event(self, event):
334338

335339
def handle_resize(self, event):
336340
x, y = event.get('width', 800), event.get('height', 800)
337-
x, y = int(x), int(y)
341+
x, y = int(x) * self._dpi_ratio, int(y) * self._dpi_ratio
338342
fig = self.figure
339343
# An attempt at approximating the figure size in pixels.
340344
fig.set_size_inches(x / fig.dpi, y / fig.dpi, forward=False)
@@ -351,6 +355,17 @@ def handle_send_image_mode(self, event):
351355
# The client requests notification of what the current image mode is.
352356
self.send_event('image_mode', mode=self._current_image_mode)
353357

358+
def handle_set_dpi_ratio(self, event):
359+
dpi_ratio = event.get('dpi_ratio', 1)
360+
if dpi_ratio != self._dpi_ratio:
361+
# We don't want to scale up the figure dpi more than once.
362+
if not hasattr(self.figure, '_original_dpi'):
363+
self.figure._original_dpi = self.figure.dpi
364+
self.figure.dpi = dpi_ratio * self.figure._original_dpi
365+
self._dpi_ratio = dpi_ratio
366+
self._force_full = True
367+
self.draw_idle()
368+
354369
def send_event(self, event_type, **kwargs):
355370
self.manager._send_event(event_type, **kwargs)
356371

@@ -436,7 +451,9 @@ def _get_toolbar(self, canvas):
436451
return toolbar
437452

438453
def resize(self, w, h):
439-
self._send_event('resize', size=(w, h))
454+
self._send_event(
455+
'resize',
456+
size=(w / self.canvas._dpi_ratio, h / self.canvas._dpi_ratio))
440457

441458
def set_window_title(self, title):
442459
self._send_event('figure_label', label=title)

lib/matplotlib/backends/web_backend/mpl.js

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* Put everything inside the global mpl namespace */
22
window.mpl = {};
33

4+
45
mpl.get_websocket_type = function() {
56
if (typeof(WebSocket) !== 'undefined') {
67
return WebSocket;
@@ -59,6 +60,9 @@ mpl.figure = function(figure_id, websocket, ondownload, parent_element) {
5960
this.ws.onopen = function () {
6061
fig.send_message("supports_binary", {value: fig.supports_binary});
6162
fig.send_message("send_image_mode", {});
63+
if (mpl.ratio != 1) {
64+
fig.send_message("set_dpi_ratio", {'dpi_ratio': mpl.ratio});
65+
}
6266
fig.send_message("refresh", {});
6367
}
6468

@@ -128,6 +132,15 @@ mpl.figure.prototype._init_canvas = function() {
128132
this.canvas = canvas[0];
129133
this.context = canvas[0].getContext("2d");
130134

135+
var backingStore = this.context.backingStorePixelRatio ||
136+
this.context.webkitBackingStorePixelRatio ||
137+
this.context.mozBackingStorePixelRatio ||
138+
this.context.msBackingStorePixelRatio ||
139+
this.context.oBackingStorePixelRatio ||
140+
this.context.backingStorePixelRatio || 1;
141+
142+
mpl.ratio = (window.devicePixelRatio || 1) / backingStore;
143+
131144
var rubberband = $('<canvas/>');
132145
rubberband.attr('style', "position: absolute; left: 0; top: 0; z-index: 1;")
133146

@@ -184,8 +197,9 @@ mpl.figure.prototype._init_canvas = function() {
184197
canvas_div.css('width', width)
185198
canvas_div.css('height', height)
186199

187-
canvas.attr('width', width);
188-
canvas.attr('height', height);
200+
canvas.attr('width', width * mpl.ratio);
201+
canvas.attr('height', height * mpl.ratio);
202+
canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');
189203

190204
rubberband.attr('width', width);
191205
rubberband.attr('height', height);
@@ -318,10 +332,10 @@ mpl.figure.prototype.handle_resize = function(fig, msg) {
318332
}
319333

320334
mpl.figure.prototype.handle_rubberband = function(fig, msg) {
321-
var x0 = msg['x0'];
322-
var y0 = fig.canvas.height - msg['y0'];
323-
var x1 = msg['x1'];
324-
var y1 = fig.canvas.height - msg['y1'];
335+
var x0 = msg['x0'] / mpl.ratio;
336+
var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;
337+
var x1 = msg['x1'] / mpl.ratio;
338+
var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;
325339
x0 = Math.floor(x0) + 0.5;
326340
y0 = Math.floor(y0) + 0.5;
327341
x1 = Math.floor(x1) + 0.5;
@@ -477,8 +491,8 @@ mpl.figure.prototype.mouse_event = function(event, name) {
477491
this.canvas_div.focus();
478492
}
479493

480-
var x = canvas_pos.x;
481-
var y = canvas_pos.y;
494+
var x = canvas_pos.x * mpl.ratio;
495+
var y = canvas_pos.y * mpl.ratio;
482496

483497
this.send_message(name, {x: x, y: y, button: event.button,
484498
step: event.step,

lib/matplotlib/backends/web_backend/nbagg_mpl.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ mpl.mpl_figure_comm = function(comm, msg) {
5555
};
5656

5757
mpl.figure.prototype.handle_close = function(fig, msg) {
58+
var width = fig.canvas.width/mpl.ratio
5859
fig.root.unbind('remove')
5960

6061
// Update the output cell to use the data from the current canvas.
@@ -63,7 +64,7 @@ mpl.figure.prototype.handle_close = function(fig, msg) {
6364
// Re-enable the keyboard manager in IPython - without this line, in FF,
6465
// the notebook keyboard shortcuts fail.
6566
IPython.keyboard_manager.enable()
66-
$(fig.parent_element).html('<img src="' + dataURL + '">');
67+
$(fig.parent_element).html('<img src="' + dataURL + '" width="' + width + '">');
6768
fig.close_ws(fig, msg);
6869
}
6970

@@ -74,8 +75,9 @@ mpl.figure.prototype.close_ws = function(fig, msg){
7475

7576
mpl.figure.prototype.push_to_output = function(remove_interactive) {
7677
// Turn the data on the canvas into data in the output cell.
78+
var width = this.canvas.width/mpl.ratio
7779
var dataURL = this.canvas.toDataURL();
78-
this.cell_info[1]['text/html'] = '<img src="' + dataURL + '">';
80+
this.cell_info[1]['text/html'] = '<img src="' + dataURL + '" width="' + width + '">';
7981
}
8082

8183
mpl.figure.prototype.updated_canvas_event = function() {

0 commit comments

Comments
 (0)
0