Skip to content

Commit f6dbc7f

Browse files
committed
FIX: fastpath clipped artists
1 parent 146de7f commit f6dbc7f

2 files changed

Lines changed: 35 additions & 12 deletions

File tree

lib/matplotlib/artist.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,23 @@ def get_window_extent(self, renderer):
249249
"""
250250
return Bbox([[0, 0], [0, 0]])
251251

252+
def _get_clip_bbox(self):
253+
"""
254+
Return the intersection of the clip_path and clip_box for this
255+
artist. Returns None if both of these are None, or ``get_clip_on``
256+
is False.
257+
"""
258+
bbox = None
259+
if self.get_clip_on():
260+
clip_box = self.get_clip_box()
261+
if clip_box is not None:
262+
bbox = clip_box
263+
clip_path = self.get_clip_path()
264+
if clip_path is not None and bbox is not None:
265+
clip_path = clip_path.get_fully_transformed_path()
266+
bbox = Bbox.intersection(bbox, clip_path.get_extents())
267+
return bbox
268+
252269
def get_tightbbox(self, renderer):
253270
"""
254271
Like `Artist.get_window_extent`, but includes any clipping.
@@ -266,13 +283,9 @@ def get_tightbbox(self, renderer):
266283
"""
267284
bbox = self.get_window_extent(renderer)
268285
if self.get_clip_on():
269-
clip_box = self.get_clip_box()
286+
clip_box = self._get_clip_bbox()
270287
if clip_box is not None:
271288
bbox = Bbox.intersection(bbox, clip_box)
272-
clip_path = self.get_clip_path()
273-
if clip_path is not None and bbox is not None:
274-
clip_path = clip_path.get_fully_transformed_path()
275-
bbox = Bbox.intersection(bbox, clip_path.get_extents())
276289
return bbox
277290

278291
def add_callback(self, func):

lib/matplotlib/axes/_base.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4292,6 +4292,7 @@ def get_default_bbox_extra_artists(self):
42924292
"""
42934293

42944294
artists = self.get_children()
4295+
42954296
if not (self.axison and self._frameon):
42964297
# don't do bbox on spines if frame not on.
42974298
for spine in self.spines.values():
@@ -4366,7 +4367,8 @@ def get_tightbbox(self, renderer, call_axes_locator=True,
43664367
bb.append(bb_yaxis)
43674368

43684369
self._update_title_position(renderer)
4369-
bb.append(self.get_window_extent(renderer))
4370+
axbbox = self.get_window_extent(renderer)
4371+
bb.append(axbbox)
43704372

43714373
self._update_title_position(renderer)
43724374
if self.title.get_visible():
@@ -4383,12 +4385,20 @@ def get_tightbbox(self, renderer, call_axes_locator=True,
43834385
bbox_artists = self.get_default_bbox_extra_artists()
43844386

43854387
for a in bbox_artists:
4386-
bbox = a.get_tightbbox(renderer)
4387-
if (bbox is not None
4388-
and 0 < bbox.width < np.inf
4389-
and 0 < bbox.height < np.inf):
4390-
bb.append(bbox)
4391-
4388+
# Extra check here to quickly see if clipping is on and
4389+
# contained in the axes. If it is, don't get the tightbbox for
4390+
# this artist because this can be expensive:
4391+
clip_extent = a._get_clip_bbox()
4392+
if clip_extent is not None:
4393+
clip_extent = mtransforms.Bbox.intersection(clip_extent,
4394+
axbbox)
4395+
inside_axes = np.all(clip_extent.extents == axbbox.extents)
4396+
if clip_extent is None or not inside_axes:
4397+
bbox = a.get_tightbbox(renderer)
4398+
if (bbox is not None
4399+
and 0 < bbox.width < np.inf
4400+
and 0 < bbox.height < np.inf):
4401+
bb.append(bbox)
43924402
_bbox = mtransforms.Bbox.union(
43934403
[b for b in bb if b.width != 0 or b.height != 0])
43944404

0 commit comments

Comments
 (0)