Skip to content

Commit b8bc21f

Browse files
committed
bbox_inches=tight support for *all* figure artists.
1 parent 4ac6780 commit b8bc21f

17 files changed

+1633
-27
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ install:
2222
script:
2323
- mkdir ../foo
2424
- cd ../foo
25-
- python ../matplotlib/tests.py
25+
- python ../matplotlib/tests.py -sv

lib/matplotlib/artist.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,15 @@ def get_axes(self):
180180
"""
181181
return self.axes
182182

183+
def get_window_extent(self, renderer):
184+
"""
185+
Get the axes bounding box in display space.
186+
Subclasses should override for inclusion in the bounding box
187+
"tight" calculation. Default is to return an empty bounding
188+
box at 0, 0.
189+
"""
190+
return Bbox([[0, 0], [0, 0]])
191+
183192
def add_callback(self, func):
184193
"""
185194
Adds a callback function that will be called whenever one of

lib/matplotlib/axes.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9072,13 +9072,8 @@ def matshow(self, Z, **kwargs):
90729072
return im
90739073

90749074
def get_default_bbox_extra_artists(self):
9075-
bbox_extra_artists = [t for t in self.texts if t.get_visible()]
9076-
if self.legend_:
9077-
bbox_extra_artists.append(self.legend_)
9078-
if self.tables:
9079-
for t in self.tables:
9080-
bbox_extra_artists.append(t)
9081-
return bbox_extra_artists
9075+
return [artist for artist in self.get_children()
9076+
if artist.get_visible()]
90829077

90839078
def get_tightbbox(self, renderer, call_axes_locator=True):
90849079
"""

lib/matplotlib/backend_bases.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,15 +2092,28 @@ def print_figure(self, filename, dpi=None, facecolor='w', edgecolor='w',
20922092
renderer = self.figure._cachedRenderer
20932093
bbox_inches = self.figure.get_tightbbox(renderer)
20942094

2095-
bbox_extra_artists = kwargs.pop("bbox_extra_artists", None)
2096-
if bbox_extra_artists is None:
2097-
bbox_extra_artists = self.figure.get_default_bbox_extra_artists()
2095+
bbox_artists = kwargs.pop("bbox_extra_artists", None)
2096+
if bbox_artists is None:
2097+
bbox_artists = self.figure.get_default_bbox_extra_artists()
2098+
2099+
bbox_filtered = []
2100+
for a in bbox_artists:
2101+
bbox = a.get_window_extent(renderer)
2102+
# print('{0:40} - {1.width:5}, {1.height:5} '
2103+
# '{1}'.format(type(a), bbox))
2104+
if a.get_clip_on():
2105+
clip_box = a.get_clip_box()
2106+
if clip_box is not None:
2107+
bbox = Bbox.intersection(bbox, clip_box)
2108+
clip_path = a.get_clip_path()
2109+
if clip_path is not None and bbox is not None:
2110+
clip_path = clip_path.get_fully_transformed_path()
2111+
bbox = Bbox.intersection(bbox,
2112+
clip_path.get_extents())
2113+
if bbox is not None and (bbox.width != 0 or
2114+
bbox.height != 0):
2115+
bbox_filtered.append(bbox)
20982116

2099-
bb = [a.get_window_extent(renderer)
2100-
for a in bbox_extra_artists]
2101-
2102-
bbox_filtered = [b for b in bb
2103-
if b.width != 0 or b.height != 0]
21042117
if bbox_filtered:
21052118
_bbox = Bbox.union(bbox_filtered)
21062119
trans = Affine2D().scale(1.0 / self.figure.dpi)

lib/matplotlib/collections.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,9 @@ def get_datalim(self, transData):
193193
return result
194194

195195
def get_window_extent(self, renderer):
196-
bbox = self.get_datalim(transforms.IdentityTransform())
197-
#TODO:check to ensure that this does not fail for
198-
#cases other than scatter plot legend
199-
return bbox
196+
# TODO:check to ensure that this does not fail for
197+
# cases other than scatter plot legend
198+
return self.get_datalim(transforms.IdentityTransform())
200199

201200
def _prepare_points(self):
202201
"""Point prep for drawing and hit testing"""

lib/matplotlib/figure.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,11 +1504,14 @@ def waitforbuttonpress(self, timeout=-1):
15041504
return blocking_input(timeout=timeout)
15051505

15061506
def get_default_bbox_extra_artists(self):
1507-
bbox_extra_artists = [t for t in self.texts if t.get_visible()]
1507+
bbox_artists = [artist for artist in self.get_children()
1508+
if artist.get_visible()]
15081509
for ax in self.axes:
15091510
if ax.get_visible():
1510-
bbox_extra_artists.extend(ax.get_default_bbox_extra_artists())
1511-
return bbox_extra_artists
1511+
bbox_artists.extend(ax.get_default_bbox_extra_artists())
1512+
# we don't want the figure's patch to influence the bbox calculation
1513+
bbox_artists.remove(self.patch)
1514+
return bbox_artists
15121515

15131516
def get_tightbbox(self, renderer):
15141517
"""

lib/matplotlib/lines.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -374,10 +374,10 @@ def set_picker(self, p):
374374
self._picker = p
375375

376376
def get_window_extent(self, renderer):
377-
bbox = Bbox.unit()
378-
bbox.update_from_data_xy(
379-
self.get_transform().transform(self.get_xydata()),
380-
ignore=True)
377+
bbox = Bbox([[0, 0], [0, 0]])
378+
trans_data_to_xy = self.get_transform().transform
379+
bbox.update_from_data_xy(trans_data_to_xy(self.get_xydata()),
380+
ignore=True)
381381
# correct for marker size, if any
382382
if self._marker:
383383
ms = (self._markersize / 72.0 * self.figure.dpi) * 0.5

lib/matplotlib/table.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ def __init__(self, ax, loc=None, bbox=None):
202202
self._autoColumns = []
203203
self._autoFontsize = True
204204

205+
self.set_clip_on(False)
206+
205207
self._cachedRenderer = None
206208

207209
def add_cell(self, row, col, *args, **kwargs):
Loading

0 commit comments

Comments
 (0)