Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MNT: Don't require renderer for window_extent and tightbbox #22745

Merged
merged 1 commit into from
Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions doc/api/next_api_changes/behavior/22745-JMK.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
No need to specify renderer for get_tightbbox and get_window_extent
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``get_tightbbox`` and `~.Artist.get_window_extent` methods
no longer require the *renderer* kwarg, saving users from having to
querry it from ``fig.canvas.get_renderer``. If the *renderer*
kwarg is not supplied these methods first check if there is a cached renderer
from a previous draw and use that. If there is no cahched renderer, then
the methods will use ``fig.canvas.get_renderer()`` as a fallback.
3 changes: 1 addition & 2 deletions lib/matplotlib/_constrained_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
import numpy as np

from matplotlib import _api, artist as martist
from matplotlib._tight_layout import get_renderer
import matplotlib.transforms as mtransforms
import matplotlib._layoutgrid as mlayoutgrid

Expand Down Expand Up @@ -94,7 +93,7 @@ def do_constrained_layout(fig, h_pad, w_pad,
layoutgrid : private debugging structure
"""

renderer = get_renderer(fig)
renderer = fig._get_renderer()
# make layoutgrid tree...
layoutgrids = make_layoutgrids(fig, None, rect=rect)
if not layoutgrids['hasgrids']:
Expand Down
12 changes: 0 additions & 12 deletions lib/matplotlib/_tight_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,18 +198,6 @@ def auto_adjust_subplotpars(
ax_bbox_list, pad, h_pad, w_pad, rect)


def get_renderer(fig):
if fig._cachedRenderer:
return fig._cachedRenderer
else:
canvas = fig.canvas
if canvas and hasattr(canvas, "get_renderer"):
return canvas.get_renderer()
else:
from . import backend_bases
return backend_bases._get_renderer(fig)


def get_subplotspec_list(axes_list, grid_spec=None):
"""
Return a list of subplotspec from the given list of axes.
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/artist.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ def stale(self, val):
if val and self.stale_callback is not None:
self.stale_callback(self, val)

def get_window_extent(self, renderer):
def get_window_extent(self, renderer=None):
"""
Get the artist's bounding box in display space.

Expand All @@ -318,7 +318,7 @@ def get_window_extent(self, renderer):
"""
return Bbox([[0, 0], [0, 0]])

def get_tightbbox(self, renderer):
def get_tightbbox(self, renderer=None):
"""
Like `.Artist.get_window_extent`, but includes any clipping.

Expand Down
4 changes: 3 additions & 1 deletion lib/matplotlib/axes/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4441,7 +4441,7 @@ def get_default_bbox_extra_artists(self):
return [a for a in artists if a.get_visible() and a.get_in_layout()
and (isinstance(a, noclip) or not a._fully_clipped_to_axes())]

def get_tightbbox(self, renderer, call_axes_locator=True,
def get_tightbbox(self, renderer=None, call_axes_locator=True,
bbox_extra_artists=None, *, for_layout_only=False):
"""
Return the tight bounding box of the Axes, including axis and their
Expand Down Expand Up @@ -4485,6 +4485,8 @@ def get_tightbbox(self, renderer, call_axes_locator=True,
"""

bb = []
if renderer is None:
renderer = self.figure._get_renderer()

if not self.get_visible():
return None
Expand Down
9 changes: 6 additions & 3 deletions lib/matplotlib/axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -1198,14 +1198,16 @@ def _update_ticks(self):

return ticks_to_draw

def _get_ticklabel_bboxes(self, ticks, renderer):
def _get_ticklabel_bboxes(self, ticks, renderer=None):
"""Return lists of bboxes for ticks' label1's and label2's."""
if renderer is None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need to normalize here; just let the labels do it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That depends not he strategy we want to employ - it could wait to normalize until the end, but this does save a bunch of calls to _get_renderer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair.

renderer = self.figure._get_renderer()
return ([tick.label1.get_window_extent(renderer)
for tick in ticks if tick.label1.get_visible()],
[tick.label2.get_window_extent(renderer)
for tick in ticks if tick.label2.get_visible()])

def get_tightbbox(self, renderer, *, for_layout_only=False):
def get_tightbbox(self, renderer=None, *, for_layout_only=False):
"""
Return a bounding box that encloses the axis. It only accounts
tick labels, axis label, and offsetText.
Expand All @@ -1217,7 +1219,8 @@ def get_tightbbox(self, renderer, *, for_layout_only=False):
"""
if not self.get_visible():
return

if renderer is None:
renderer = self.figure._get_renderer()
ticks_to_draw = self._update_ticks()

self._update_label_position(renderer)
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ def get_datalim(self, transData):
return bbox
return transforms.Bbox.null()

def get_window_extent(self, renderer):
def get_window_extent(self, renderer=None):
# TODO: check to ensure that this does not fail for
# cases other than scatter plot legend
return self.get_datalim(transforms.IdentityTransform())
Expand Down
6 changes: 4 additions & 2 deletions lib/matplotlib/contour.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,23 +251,25 @@ def too_close(self, x, y, lw):
def _get_nth_label_width(self, nth):
"""Return the width of the *nth* label, in pixels."""
fig = self.axes.figure
renderer = fig._get_renderer()
return (
text.Text(0, 0,
self.get_text(self.labelLevelList[nth], self.labelFmt),
figure=fig,
size=self.labelFontSizeList[nth],
fontproperties=self.labelFontProps)
.get_window_extent(mpl._tight_layout.get_renderer(fig)).width)
.get_window_extent(renderer).width)

@_api.deprecated("3.5")
def get_label_width(self, lev, fmt, fsize):
"""Return the width of the label in points."""
if not isinstance(lev, str):
lev = self.get_text(lev, fmt)
fig = self.axes.figure
renderer = fig._get_renderer()
width = (text.Text(0, 0, lev, figure=fig,
size=fsize, fontproperties=self.labelFontProps)
.get_window_extent(mpl._tight_layout.get_renderer(fig)).width)
.get_window_extent(renderer).width)
width *= 72 / fig.dpi
return width

Expand Down
24 changes: 15 additions & 9 deletions lib/matplotlib/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -1618,7 +1618,7 @@ def get_default_bbox_extra_artists(self):
bbox_artists.extend(ax.get_default_bbox_extra_artists())
return bbox_artists

def get_tightbbox(self, renderer, bbox_extra_artists=None):
def get_tightbbox(self, renderer=None, bbox_extra_artists=None):
"""
Return a (tight) bounding box of the figure *in inches*.

Expand All @@ -1645,6 +1645,9 @@ def get_tightbbox(self, renderer, bbox_extra_artists=None):
containing the bounding box (in figure inches).
"""

if renderer is None:
renderer = self.figure._get_renderer()

bb = []
if bbox_extra_artists is None:
artists = self.get_default_bbox_extra_artists()
Expand Down Expand Up @@ -2060,13 +2063,8 @@ def dpi(self):
def dpi(self, value):
self._parent.dpi = value

@property
def _cachedRenderer(self):
return self._parent._cachedRenderer

@_cachedRenderer.setter
def _cachedRenderer(self, renderer):
self._parent._cachedRenderer = renderer
def _get_renderer(self):
return self._parent._get_renderer()

def _redo_transform_rel_fig(self, bbox=None):
"""
Expand Down Expand Up @@ -2496,6 +2494,14 @@ def axes(self):

get_axes = axes.fget

def _get_renderer(self):
if self._cachedRenderer is not None:
return self._cachedRenderer
elif hasattr(self.canvas, 'get_renderer'):
return self.canvas.get_renderer()
else:
return _get_renderer(self)

def _get_dpi(self):
return self._dpi

Expand Down Expand Up @@ -2644,7 +2650,7 @@ def get_constrained_layout_pads(self, relative=False):
hspace = info['hspace']

if relative and (w_pad is not None or h_pad is not None):
renderer = _get_renderer(self)
renderer = self._get_renderer()
dpi = renderer.dpi
w_pad = w_pad * dpi / renderer.width
h_pad = h_pad * dpi / renderer.height
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/gridspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ def tight_layout(self, figure, renderer=None,
"might be incorrect.")

if renderer is None:
renderer = _tight_layout.get_renderer(figure)
renderer = figure._get_renderer()

kwargs = _tight_layout.get_tight_layout_figure(
figure, figure.axes, subplotspec_list, renderer,
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -1425,7 +1425,7 @@ def __init__(self, bbox,

def get_window_extent(self, renderer=None):
if renderer is None:
renderer = self.get_figure()._cachedRenderer
renderer = self.get_figure()._get_renderer()

if isinstance(self.bbox, BboxBase):
return self.bbox
Expand Down
4 changes: 1 addition & 3 deletions lib/matplotlib/layout_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
from matplotlib._constrained_layout import do_constrained_layout
from matplotlib._tight_layout import (get_subplotspec_list,
get_tight_layout_figure)
# from matplotlib.backend_bases import _get_renderer
from matplotlib._tight_layout import get_renderer


class LayoutEngine:
Expand Down Expand Up @@ -154,7 +152,7 @@ def execute(self, fig):
_api.warn_external("This figure includes Axes that are not "
"compatible with tight_layout, so results "
"might be incorrect.")
renderer = get_renderer(fig)
renderer = fig._get_renderer()
with getattr(renderer, "_draw_disabled", nullcontext)():
kwargs = get_tight_layout_figure(
fig, fig.axes, subplotspec_list, renderer,
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/legend.py
Original file line number Diff line number Diff line change
Expand Up @@ -883,10 +883,10 @@ def get_title(self):
def get_window_extent(self, renderer=None):
# docstring inherited
if renderer is None:
renderer = self.figure._cachedRenderer
renderer = self.figure._get_renderer()
return self._legend_box.get_window_extent(renderer=renderer)

def get_tightbbox(self, renderer):
def get_tightbbox(self, renderer=None):
# docstring inherited
return self._legend_box.get_window_extent(renderer)

Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ def get_bbox(self):
bbox.update_from_data_xy(self.get_xydata())
return bbox

def get_window_extent(self, renderer):
def get_window_extent(self, renderer=None):
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()),
Expand Down
41 changes: 29 additions & 12 deletions lib/matplotlib/offsetbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,10 @@ def get_extent(self, renderer):
w, h, xd, yd, offsets = self.get_extent_offsets(renderer)
return w, h, xd, yd

def get_window_extent(self, renderer):
def get_window_extent(self, renderer=None):
# docstring inherited
if renderer is None:
renderer = self.figure._get_renderer()
w, h, xd, yd, offsets = self.get_extent_offsets(renderer)
px, py = self.get_offset(w, h, xd, yd, renderer)
return mtransforms.Bbox.from_bounds(px - xd, py - yd, w, h)
Expand Down Expand Up @@ -631,8 +633,10 @@ def get_offset(self):
"""Return offset of the container."""
return self._offset

def get_window_extent(self, renderer):
def get_window_extent(self, renderer=None):
# docstring inherited
if renderer is None:
renderer = self.figure._get_renderer()
w, h, xd, yd = self.get_extent(renderer)
ox, oy = self.get_offset() # w, h, xd, yd)

Expand Down Expand Up @@ -765,8 +769,10 @@ def get_offset(self):
"""Return offset of the container."""
return self._offset

def get_window_extent(self, renderer):
def get_window_extent(self, renderer=None):
# docstring inherited
if renderer is None:
renderer = self.figure._get_renderer()
w, h, xd, yd = self.get_extent(renderer)
ox, oy = self.get_offset()
return mtransforms.Bbox.from_bounds(ox - xd, oy - yd, w, h)
Expand Down Expand Up @@ -866,8 +872,10 @@ def get_offset(self):
"""Return offset of the container."""
return self._offset

def get_window_extent(self, renderer):
def get_window_extent(self, renderer=None):
# docstring inherited
if renderer is None:
renderer = self.figure._get_renderer()
w, h, xd, yd = self.get_extent(renderer)
ox, oy = self.get_offset() # w, h, xd, yd)
return mtransforms.Bbox.from_bounds(ox - xd, oy - yd, w, h)
Expand Down Expand Up @@ -1048,8 +1056,11 @@ def set_bbox_to_anchor(self, bbox, transform=None):
self._bbox_to_anchor_transform = transform
self.stale = True

def get_window_extent(self, renderer):
def get_window_extent(self, renderer=None):
# docstring inherited
if renderer is None:
renderer = self.figure._get_renderer()

self._update_offset_func(renderer)
w, h, xd, yd = self.get_extent(renderer)
ox, oy = self.get_offset(w, h, xd, yd, renderer)
Expand Down Expand Up @@ -1211,8 +1222,10 @@ def get_offset(self):
def get_children(self):
return [self.image]

def get_window_extent(self, renderer):
def get_window_extent(self, renderer=None):
# docstring inherited
if renderer is None:
renderer = self.figure._get_renderer()
w, h, xd, yd = self.get_extent(renderer)
ox, oy = self.get_offset()
return mtransforms.Bbox.from_bounds(ox - xd, oy - yd, w, h)
Expand Down Expand Up @@ -1390,12 +1403,14 @@ def get_fontsize(self):
"""Return the fontsize in points."""
return self.prop.get_size_in_points()

def get_window_extent(self, renderer):
def get_window_extent(self, renderer=None):
# docstring inherited
if renderer is None:
renderer = self.figure._get_renderer()
return Bbox.union([child.get_window_extent(renderer)
for child in self.get_children()])

def get_tightbbox(self, renderer):
def get_tightbbox(self, renderer=None):
# docstring inherited
return Bbox.union([child.get_tightbbox(renderer)
for child in self.get_children()])
Expand Down Expand Up @@ -1511,7 +1526,8 @@ def on_motion(self, evt):
self.update_offset(dx, dy)
if self._use_blit:
self.canvas.restore_region(self.background)
self.ref_artist.draw(self.ref_artist.figure._cachedRenderer)
self.ref_artist.draw(
self.ref_artist.figure._get_renderer())
self.canvas.blit()
else:
self.canvas.draw()
Expand All @@ -1526,7 +1542,8 @@ def on_pick(self, evt):
self.canvas.draw()
self.background = \
self.canvas.copy_from_bbox(self.ref_artist.figure.bbox)
self.ref_artist.draw(self.ref_artist.figure._cachedRenderer)
self.ref_artist.draw(
self.ref_artist.figure._get_renderer())
self.canvas.blit()
self._c1 = self.canvas.callbacks._connect_picklable(
"motion_notify_event", self.on_motion)
Expand Down Expand Up @@ -1576,7 +1593,7 @@ def __init__(self, ref_artist, offsetbox, use_blit=False):

def save_offset(self):
offsetbox = self.offsetbox
renderer = offsetbox.figure._cachedRenderer
renderer = offsetbox.figure._get_renderer()
w, h, xd, yd = offsetbox.get_extent(renderer)
offset = offsetbox.get_offset(w, h, xd, yd, renderer)
self.offsetbox_x, self.offsetbox_y = offset
Expand All @@ -1588,7 +1605,7 @@ def update_offset(self, dx, dy):

def get_loc_in_canvas(self):
offsetbox = self.offsetbox
renderer = offsetbox.figure._cachedRenderer
renderer = offsetbox.figure._get_renderer()
w, h, xd, yd = offsetbox.get_extent(renderer)
ox, oy = offsetbox._offset
loc_in_canvas = (ox - xd, oy - yd)
Expand Down