Skip to content

Commit

Permalink
Merge pull request #1448 from pelson/bbox_tight_all_artists
Browse files Browse the repository at this point in the history
```bbox_inches="tight"``` support for *all* figure artists.
  • Loading branch information
dmcdougall committed Mar 31, 2013
2 parents cf6b26f + 6569ca7 commit 8605579
Show file tree
Hide file tree
Showing 18 changed files with 1,638 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -22,4 +22,4 @@ install:
script:
- mkdir ../foo
- cd ../foo
- python ../matplotlib/tests.py
- python ../matplotlib/tests.py -sv
7 changes: 7 additions & 0 deletions doc/users/whats_new.rst
Expand Up @@ -40,6 +40,13 @@ They may be symmetric or weighted.

.. plot:: mpl_examples/pylab_examples/stackplot_demo2.py

Improved ``bbox_inches="tight"`` functionality
----------------------------------------------
Passing ``bbox_inches="tight"`` through to :func:`plt.save` now takes into account
*all* artists on a figure - this was previously not the case and led to several
corner cases which did not function as expected.


Remember save directory
-----------------------
Martin Spacek made the save figure dialog remember the last directory saved
Expand Down
9 changes: 9 additions & 0 deletions lib/matplotlib/artist.py
Expand Up @@ -180,6 +180,15 @@ def get_axes(self):
"""
return self.axes

def get_window_extent(self, renderer):
"""
Get the axes bounding box in display space.
Subclasses should override for inclusion in the bounding box
"tight" calculation. Default is to return an empty bounding
box at 0, 0.
"""
return Bbox([[0, 0], [0, 0]])

def add_callback(self, func):
"""
Adds a callback function that will be called whenever one of
Expand Down
9 changes: 2 additions & 7 deletions lib/matplotlib/axes.py
Expand Up @@ -9076,13 +9076,8 @@ def matshow(self, Z, **kwargs):
return im

def get_default_bbox_extra_artists(self):
bbox_extra_artists = [t for t in self.texts if t.get_visible()]
if self.legend_:
bbox_extra_artists.append(self.legend_)
if self.tables:
for t in self.tables:
bbox_extra_artists.append(t)
return bbox_extra_artists
return [artist for artist in self.get_children()
if artist.get_visible()]

def get_tightbbox(self, renderer, call_axes_locator=True):
"""
Expand Down
27 changes: 19 additions & 8 deletions lib/matplotlib/backend_bases.py
Expand Up @@ -2094,15 +2094,26 @@ def print_figure(self, filename, dpi=None, facecolor='w', edgecolor='w',
renderer = self.figure._cachedRenderer
bbox_inches = self.figure.get_tightbbox(renderer)

bbox_extra_artists = kwargs.pop("bbox_extra_artists", None)
if bbox_extra_artists is None:
bbox_extra_artists = self.figure.get_default_bbox_extra_artists()
bbox_artists = kwargs.pop("bbox_extra_artists", None)
if bbox_artists is None:
bbox_artists = self.figure.get_default_bbox_extra_artists()

bbox_filtered = []
for a in bbox_artists:
bbox = a.get_window_extent(renderer)
if a.get_clip_on():
clip_box = a.get_clip_box()
if clip_box is not None:
bbox = Bbox.intersection(bbox, clip_box)
clip_path = a.get_clip_path()
if clip_path is not None and bbox is not None:
clip_path = clip_path.get_fully_transformed_path()
bbox = Bbox.intersection(bbox,
clip_path.get_extents())
if bbox is not None and (bbox.width != 0 or
bbox.height != 0):
bbox_filtered.append(bbox)

bb = [a.get_window_extent(renderer)
for a in bbox_extra_artists]

bbox_filtered = [b for b in bb
if b.width != 0 or b.height != 0]
if bbox_filtered:
_bbox = Bbox.union(bbox_filtered)
trans = Affine2D().scale(1.0 / self.figure.dpi)
Expand Down
7 changes: 3 additions & 4 deletions lib/matplotlib/collections.py
Expand Up @@ -193,10 +193,9 @@ def get_datalim(self, transData):
return result

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

def _prepare_points(self):
"""Point prep for drawing and hit testing"""
Expand Down
9 changes: 6 additions & 3 deletions lib/matplotlib/figure.py
Expand Up @@ -1504,11 +1504,14 @@ def waitforbuttonpress(self, timeout=-1):
return blocking_input(timeout=timeout)

def get_default_bbox_extra_artists(self):
bbox_extra_artists = [t for t in self.texts if t.get_visible()]
bbox_artists = [artist for artist in self.get_children()
if artist.get_visible()]
for ax in self.axes:
if ax.get_visible():
bbox_extra_artists.extend(ax.get_default_bbox_extra_artists())
return bbox_extra_artists
bbox_artists.extend(ax.get_default_bbox_extra_artists())
# we don't want the figure's patch to influence the bbox calculation
bbox_artists.remove(self.patch)
return bbox_artists

def get_tightbbox(self, renderer):
"""
Expand Down
8 changes: 4 additions & 4 deletions lib/matplotlib/lines.py
Expand Up @@ -374,10 +374,10 @@ def set_picker(self, p):
self._picker = p

def get_window_extent(self, renderer):
bbox = Bbox.unit()
bbox.update_from_data_xy(
self.get_transform().transform(self.get_xydata()),
ignore=True)
bbox = Bbox([[0, 0], [0, 0]])
trans_data_to_xy = self.get_transform().transform
bbox.update_from_data_xy(trans_data_to_xy(self.get_xydata()),
ignore=True)
# correct for marker size, if any
if self._marker:
ms = (self._markersize / 72.0 * self.figure.dpi) * 0.5
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/table.py
Expand Up @@ -202,6 +202,8 @@ def __init__(self, ax, loc=None, bbox=None):
self._autoColumns = []
self._autoFontsize = True

self.set_clip_on(False)

self._cachedRenderer = None

def add_cell(self, row, col, *args, **kwargs):
Expand Down
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8605579

Please sign in to comment.