22Helper module for the *bbox_inches* parameter in `.Figure.savefig`.
33"""
44
5+ import contextlib
6+
7+ from matplotlib .cbook import _setattr_cm
58from matplotlib .transforms import Bbox , TransformedBbox , Affine2D
69
710
@@ -18,46 +21,23 @@ def adjust_bbox(fig, bbox_inches, fixed_dpi=None):
1821 def no_op_apply_aspect (position = None ):
1922 return
2023
21- origBbox = fig .bbox
22- origBboxInches = fig .bbox_inches
23- orig_tight_layout = fig .get_tight_layout ()
24- _boxout = fig .transFigure ._boxout
24+ stack = contextlib .ExitStack ()
2525
26+ stack .callback (fig .set_tight_layout , fig .get_tight_layout ())
2627 fig .set_tight_layout (False )
27- old_aspect = []
28- locator_list = []
29- sentinel = object ()
28+
3029 for ax in fig .axes :
3130 pos = ax .get_position (original = False ).frozen ()
32- locator_list .append (ax .get_axes_locator ())
3331
3432 def _l (a , r , pos = pos ):
3533 return pos
34+
35+ stack .callback (ax .set_axes_locator , ax .get_axes_locator ())
3636 ax .set_axes_locator (_l )
37+
3738 # override the method that enforces the aspect ratio
3839 # on the Axes
39- if 'apply_aspect' in ax .__dict__ :
40- old_aspect .append (ax .apply_aspect )
41- else :
42- old_aspect .append (sentinel )
43- ax .apply_aspect = no_op_apply_aspect
44-
45- def restore_bbox ():
46- for ax , loc , aspect in zip (fig .axes , locator_list , old_aspect ):
47- ax .set_axes_locator (loc )
48- if aspect is sentinel :
49- # delete our no-op function which un-hides the
50- # original method
51- del ax .apply_aspect
52- else :
53- ax .apply_aspect = aspect
54-
55- fig .bbox = origBbox
56- fig .bbox_inches = origBboxInches
57- fig .set_tight_layout (orig_tight_layout )
58- fig .transFigure ._boxout = _boxout
59- fig .transFigure .invalidate ()
60- fig .patch .set_bounds (0 , 0 , 1 , 1 )
40+ stack .enter_context (_setattr_cm (ax , apply_aspect = no_op_apply_aspect ))
6141
6242 if fixed_dpi is not None :
6343 tr = Affine2D ().scale (fixed_dpi )
@@ -68,19 +48,25 @@ def restore_bbox():
6848
6949 _bbox = TransformedBbox (bbox_inches , tr )
7050
71- fig .bbox_inches = Bbox .from_bounds (0 , 0 ,
72- bbox_inches .width , bbox_inches .height )
51+ stack .enter_context (
52+ _setattr_cm (fig , bbox_inches = Bbox .from_bounds (
53+ 0 , 0 , bbox_inches .width , bbox_inches .height )))
7354 x0 , y0 = _bbox .x0 , _bbox .y0
7455 w1 , h1 = fig .bbox .width * dpi_scale , fig .bbox .height * dpi_scale
75- fig .transFigure ._boxout = Bbox .from_bounds (- x0 , - y0 , w1 , h1 )
56+ stack .enter_context (
57+ _setattr_cm (fig .transFigure ,
58+ _boxout = Bbox .from_bounds (- x0 , - y0 , w1 , h1 )))
7659 fig .transFigure .invalidate ()
60+ stack .callback (fig .transFigure .invalidate )
7761
78- fig .bbox = TransformedBbox (fig .bbox_inches , tr )
62+ stack .enter_context (
63+ _setattr_cm (fig , bbox = TransformedBbox (fig .bbox_inches , tr )))
7964
65+ stack .callback (fig .patch .set_bounds , 0 , 0 , 1 , 1 )
8066 fig .patch .set_bounds (x0 / w1 , y0 / h1 ,
8167 fig .bbox .width / w1 , fig .bbox .height / h1 )
8268
83- return restore_bbox
69+ return stack . close
8470
8571
8672def process_figure_for_rasterizing (fig , bbox_inches_restore , fixed_dpi = None ):
0 commit comments