32
32
The base class for the messaging area.
33
33
"""
34
34
35
- from contextlib import contextmanager
35
+ from contextlib import contextmanager , suppress
36
36
from enum import IntEnum
37
37
import functools
38
38
import importlib
52
52
from matplotlib ._pylab_helpers import Gcf
53
53
from matplotlib .transforms import Affine2D
54
54
from matplotlib .path import Path
55
+ from matplotlib .cbook import _setattr_cm
55
56
56
57
try :
57
58
from PIL import __version__ as PILLOW_VERSION
@@ -712,6 +713,23 @@ def stop_filter(self, filter_func):
712
713
Currently only supported by the agg renderer.
713
714
"""
714
715
716
+ def _draw_disabled (self ):
717
+ """
718
+ Context manager to temporary disable drawing.
719
+
720
+ This is used for getting the drawn size of Artists. This lets us
721
+ run the draw process to update any Python state but does not pay the
722
+ cost of the draw_XYZ calls on the canvas.
723
+ """
724
+ no_ops = {
725
+ meth_name : lambda * args , ** kwargs : None
726
+ for meth_name in dir (RendererBase )
727
+ if (meth_name .startswith ("draw_" )
728
+ or meth_name in ["open_group" , "close_group" ])
729
+ }
730
+
731
+ return _setattr_cm (self , ** no_ops )
732
+
715
733
716
734
class GraphicsContextBase :
717
735
"""An abstract base class that provides color, line styles, etc."""
@@ -1520,15 +1538,14 @@ def __init__(self, name, canvas, key, x=0, y=0, guiEvent=None):
1520
1538
LocationEvent .__init__ (self , name , canvas , x , y , guiEvent = guiEvent )
1521
1539
1522
1540
1523
- def _get_renderer (figure , print_method , * , draw_disabled = False ):
1541
+ def _get_renderer (figure , print_method ):
1524
1542
"""
1525
1543
Get the renderer that would be used to save a `~.Figure`, and cache it on
1526
1544
the figure.
1527
1545
1528
- If *draw_disabled* is True, additionally replace drawing methods on
1529
- *renderer* by no-ops. This is used by the tight-bbox-saving renderer,
1530
- which needs to walk through the artist tree to compute the tight-bbox, but
1531
- for which the output file may be closed early.
1546
+ If you need a renderer without any active draw methods use
1547
+ renderer._draw_disabled to temporary patch them out at your call site.
1548
+
1532
1549
"""
1533
1550
# This is implemented by triggering a draw, then immediately jumping out of
1534
1551
# Figure.draw() by raising an exception.
@@ -1544,12 +1561,6 @@ def _draw(renderer): raise Done(renderer)
1544
1561
except Done as exc :
1545
1562
renderer , = figure ._cachedRenderer , = exc .args
1546
1563
1547
- if draw_disabled :
1548
- for meth_name in dir (RendererBase ):
1549
- if (meth_name .startswith ("draw_" )
1550
- or meth_name in ["open_group" , "close_group" ]):
1551
- setattr (renderer , meth_name , lambda * args , ** kwargs : None )
1552
-
1553
1564
return renderer
1554
1565
1555
1566
@@ -2080,8 +2091,11 @@ def print_figure(self, filename, dpi=None, facecolor=None, edgecolor=None,
2080
2091
self .figure ,
2081
2092
functools .partial (
2082
2093
print_method , dpi = dpi , orientation = orientation ),
2083
- draw_disabled = True )
2084
- self .figure .draw (renderer )
2094
+ ctx = (renderer ._draw_disabled ()
2095
+ if hasattr (renderer , '_draw_disabled' )
2096
+ else suppress ())
2097
+ with ctx :
2098
+ self .figure .draw (renderer )
2085
2099
bbox_artists = kwargs .pop ("bbox_extra_artists" , None )
2086
2100
bbox_inches = self .figure .get_tightbbox (renderer ,
2087
2101
bbox_extra_artists = bbox_artists )
0 commit comments