Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 142d9fc

Browse files
committed
Make animation work in OSX backend
1 parent eea4d80 commit 142d9fc

File tree

4 files changed

+49
-57
lines changed

4 files changed

+49
-57
lines changed

lib/matplotlib/animation.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,8 @@ def _blit_clear(self, artists, bg_cache):
998998
# cache and restore.
999999
axes = set(a.axes for a in artists)
10001000
for a in axes:
1001-
a.figure.canvas.restore_region(bg_cache[a])
1001+
if a in bg_cache:
1002+
a.figure.canvas.restore_region(bg_cache[a])
10021003

10031004
def _setup_blit(self):
10041005
# Setting up the blit requires: a cache of the background for the

lib/matplotlib/backends/backend_agg.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ def print_raw(self, filename_or_obj, *args, **kwargs):
510510
finally:
511511
if close:
512512
filename_or_obj.close()
513-
renderer.dpi = original_dpi
513+
renderer.dpi = original_dpi
514514
print_rgba = print_raw
515515

516516
def print_png(self, filename_or_obj, *args, **kwargs):
@@ -529,16 +529,18 @@ def print_png(self, filename_or_obj, *args, **kwargs):
529529
finally:
530530
if close:
531531
filename_or_obj.close()
532-
renderer.dpi = original_dpi
532+
renderer.dpi = original_dpi
533533

534534
def print_to_buffer(self):
535535
FigureCanvasAgg.draw(self)
536536
renderer = self.get_renderer()
537537
original_dpi = renderer.dpi
538538
renderer.dpi = self.figure.dpi
539-
result = (renderer._renderer.buffer_rgba(),
540-
(int(renderer.width), int(renderer.height)))
541-
renderer.dpi = original_dpi
539+
try:
540+
result = (renderer._renderer.buffer_rgba(),
541+
(int(renderer.width), int(renderer.height)))
542+
finally:
543+
renderer.dpi = original_dpi
542544
return result
543545

544546
if _has_pil:

lib/matplotlib/backends/backend_macosx.py

Lines changed: 31 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import matplotlib
1919
from matplotlib.backends import _macosx
2020

21-
from .backend_agg import RendererAgg
21+
from .backend_agg import RendererAgg, FigureCanvasAgg
2222

2323

2424
class Show(ShowBase):
@@ -83,7 +83,7 @@ class TimerMac(_macosx.Timer, TimerBase):
8383
# completely implemented at the C-level (in _macosx.Timer)
8484

8585

86-
class FigureCanvasMac(_macosx.FigureCanvas, FigureCanvasBase):
86+
class FigureCanvasMac(_macosx.FigureCanvas, FigureCanvasAgg):
8787
"""
8888
The canvas the figure renders into. Calls the draw and print fig
8989
methods, creates the renderers, etc...
@@ -98,21 +98,19 @@ class FigureCanvasMac(_macosx.FigureCanvas, FigureCanvasBase):
9898
key_press_event, and key_release_event are called from there.
9999
"""
100100

101-
filetypes = FigureCanvasBase.filetypes.copy()
102-
filetypes['bmp'] = 'Windows bitmap'
103-
filetypes['jpeg'] = 'JPEG'
104-
filetypes['jpg'] = 'JPEG'
105-
filetypes['gif'] = 'Graphics Interchange Format'
106-
filetypes['tif'] = 'Tagged Image Format File'
107-
filetypes['tiff'] = 'Tagged Image Format File'
108-
109101
def __init__(self, figure):
110102
FigureCanvasBase.__init__(self, figure)
111103
width, height = self.get_width_height()
112104
_macosx.FigureCanvas.__init__(self, width, height)
105+
self._needs_draw = True
106+
self._device_scale = 1.0
107+
108+
def _set_device_scale(self, value):
109+
if self._device_scale != value:
110+
self.figure.dpi = self.figure.dpi / self._device_scale * value
111+
self._device_scale = value
113112

114-
@property
115-
def renderer(self):
113+
def get_renderer(self, cleared=False):
116114
l, b, w, h = self.figure.bbox.bounds
117115
key = w, h, self.figure.dpi
118116
try:
@@ -125,62 +123,48 @@ def renderer(self):
125123
if need_new_renderer:
126124
self._renderer = RendererAgg(w, h, self.figure.dpi)
127125
self._lastKey = key
126+
elif cleared:
127+
self._renderer.clear()
128128

129129
return self._renderer
130130

131-
def _draw(self, device_scale):
131+
def _draw(self):
132+
renderer = self.get_renderer()
133+
134+
if not self._needs_draw:
135+
return renderer
136+
132137
figure = self.figure
133138

134139
orig_dpi = figure.dpi
135140
try:
136-
figure.dpi *= device_scale
137-
renderer = self.renderer
138141
figure.draw(renderer)
139142
finally:
140143
figure.dpi = orig_dpi
141144

145+
self._needs_draw = False
146+
142147
return renderer
143148

149+
def draw(self):
150+
self._draw()
151+
self.invalidate()
152+
144153
def draw_idle(self, *args, **kwargs):
154+
self._needs_draw = True
155+
self.invalidate()
156+
157+
def blit(self, bbox):
145158
self.invalidate()
146159

147160
def resize(self, width, height):
148161
dpi = self.figure.dpi
149162
width /= dpi
150163
height /= dpi
151-
self.figure.set_size_inches(width, height)
164+
self.figure.set_size_inches(width * self._device_scale,
165+
height * self._device_scale)
152166
FigureCanvasBase.resize_event(self)
153-
154-
def _print_bitmap(self, filename, *args, **kwargs):
155-
# In backend_bases.py, print_figure changes the dpi of the figure.
156-
# But since we are essentially redrawing the picture, we need the
157-
# original dpi. Pick it up from the renderer.
158-
dpi = kwargs['dpi']
159-
old_dpi = self.figure.dpi
160-
self.figure.dpi = self.renderer.dpi
161-
width, height = self.figure.get_size_inches()
162-
width, height = width*dpi, height*dpi
163-
filename = six.text_type(filename)
164-
self.write_bitmap(filename, width, height, dpi)
165-
self.figure.dpi = old_dpi
166-
167-
def print_bmp(self, filename, *args, **kwargs):
168-
self._print_bitmap(filename, *args, **kwargs)
169-
170-
def print_jpg(self, filename, *args, **kwargs):
171-
self._print_bitmap(filename, *args, **kwargs)
172-
173-
def print_jpeg(self, filename, *args, **kwargs):
174-
self._print_bitmap(filename, *args, **kwargs)
175-
176-
def print_tif(self, filename, *args, **kwargs):
177-
self._print_bitmap(filename, *args, **kwargs)
178-
179-
def print_tiff(self, filename, *args, **kwargs):
180-
self._print_bitmap(filename, *args, **kwargs)
181-
182-
def print_gif(self, filename, *args, **kwargs):
183-
self._print_bitmap(filename, *args, **kwargs)
167+
self.draw_idle()
184168

185169
def new_timer(self, *args, **kwargs):
186170
"""

src/_macosx.m

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ - (int)index;
292292

293293
static CGFloat _get_device_scale(CGContextRef cr)
294294
{
295-
CGSize pixelSize = CGContextConvertSizeToDeviceSpace(cr, CGSizeMake(1,1));
295+
CGSize pixelSize = CGContextConvertSizeToDeviceSpace(cr, CGSizeMake(1, 1));
296296
return pixelSize.width;
297297
}
298298

@@ -2194,12 +2194,10 @@ - (void)setCanvas: (PyObject*)newCanvas
21942194
canvas = newCanvas;
21952195
}
21962196

2197-
21982197
static void _buffer_release(void* info, const void* data, size_t size) {
21992198
PyBuffer_Release((Py_buffer *)info);
22002199
}
22012200

2202-
22032201
static int _copy_agg_buffer(CGContextRef cr, PyObject *renderer)
22042202
{
22052203
Py_buffer buffer;
@@ -2276,7 +2274,14 @@ -(void)drawRect:(NSRect)rect
22762274

22772275
CGContextRef cr = [[NSGraphicsContext currentContext] graphicsPort];
22782276

2279-
renderer = PyObject_CallMethod(canvas, "_draw", "d", _get_device_scale(cr));
2277+
double device_scale = _get_device_scale(cr);
2278+
2279+
if (!PyObject_CallMethod(canvas, "_set_device_scale", "d", device_scale, NULL)) {
2280+
PyErr_Print();
2281+
goto exit;
2282+
}
2283+
2284+
renderer = PyObject_CallMethod(canvas, "_draw", "", NULL);
22802285
if (!renderer)
22812286
{
22822287
PyErr_Print();

0 commit comments

Comments
 (0)