diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py index 7aef9ed7e8b3..15f56959bc4f 100644 --- a/lib/matplotlib/legend.py +++ b/lib/matplotlib/legend.py @@ -585,8 +585,12 @@ def _get_loc(self): _loc = property(_get_loc, _set_loc) - def _findoffset(self, width, height, xdescent, ydescent, renderer): + def _findoffset(self): """Helper function to locate the legend.""" + renderer = (self.figure._cachedRenderer + or self._legend_box._cached_renderer) + width, height, xdescent, ydescent = self._legend_box.get_extent( + renderer) if self._loc == 0: # "best". x, y = self._find_best_position(width, height, renderer) @@ -883,6 +887,8 @@ def get_window_extent(self, renderer=None): # docstring inherited if renderer is None: renderer = self.figure._cachedRenderer + # May not be cached on the figure, so cache it ourselves. + self._cached_renderer = renderer return self._legend_box.get_window_extent(renderer=renderer) def get_tightbbox(self, renderer): diff --git a/lib/matplotlib/offsetbox.py b/lib/matplotlib/offsetbox.py index 229158066675..deb624f8be1a 100644 --- a/lib/matplotlib/offsetbox.py +++ b/lib/matplotlib/offsetbox.py @@ -263,32 +263,35 @@ def set_offset(self, xy): xy : (float, float) or callable The (x, y) coordinates of the offset in display units. These can either be given explicitly as a tuple (x, y), or by providing a - function that converts the extent into the offset. This function - must have the signature:: + function that dynamically computes an offset (taking the arguments + passed to `.OffsetBox.get_offset`). It is recommended to make such + functions take no arguments. + + Before version 3.6, the callable had to have the signature:: def offset(width, height, xdescent, ydescent, renderer) \ -> (float, float) + + For backwards compatibility, callables with arbitrary signatures + are currently accepted as long as compatible arguments are + passed in calls to `.set_offset`. This should be considered an + implementation detail, and may be deprecated in the future. """ self._offset = xy self.stale = True - def get_offset(self, width, height, xdescent, ydescent, renderer): + def get_offset(self, *args, **kwargs): """ - Return the offset as a tuple (x, y). - - The extent parameters have to be provided to handle the case where the - offset is dynamically determined by a callable (see - `~.OffsetBox.set_offset`). - - Parameters - ---------- - width, height, xdescent, ydescent - Extent parameters. - renderer : `.RendererBase` subclass + Return the (x, y) offset. + Parameters are usually not necessary. The only exception can occur + if you have defined a callable to calculate the offset dynamically (see + `~.OffsetBox.set_offset`). It is now recommended that such a + callable does not take parameters. However, for backward-compatibility, + callables with parameters are still supported; these parameters must be + provided to `.get_offset` so that we can pass them on. """ - return (self._offset(width, height, xdescent, ydescent, renderer) - if callable(self._offset) + return (self._offset(*args, **kwargs) if callable(self._offset) else self._offset) def set_width(self, width): @@ -347,8 +350,10 @@ def get_extent(self, renderer): def get_window_extent(self, renderer): # docstring inherited - w, h, xd, yd, offsets = self.get_extent_offsets(renderer) - px, py = self.get_offset(w, h, xd, yd, renderer) + w, h, xd, yd = self.get_extent(renderer) + # dynamic offset compute callables may need to access the renderer. + self._cached_renderer = renderer + px, py = self.get_offset() return mtransforms.Bbox.from_bounds(px - xd, py - yd, w, h) def draw(self, renderer): @@ -357,7 +362,7 @@ def draw(self, renderer): to the given *renderer*. """ w, h, xdescent, ydescent, offsets = self.get_extent_offsets(renderer) - px, py = self.get_offset(w, h, xdescent, ydescent, renderer) + px, py = self.get_offset() for c, (ox, oy) in zip(self.get_visible_children(), offsets): c.set_offset((px + ox, py + oy)) c.draw(renderer) @@ -538,7 +543,7 @@ def get_extent_offsets(self, renderer): def draw(self, renderer): # docstring inherited w, h, xdescent, ydescent, offsets = self.get_extent_offsets(renderer) - px, py = self.get_offset(w, h, xdescent, ydescent, renderer) + px, py = self.get_offset() for c, (ox, oy) in zip(self.get_visible_children(), offsets): c.set_offset((px + ox, py + oy)) @@ -622,21 +627,9 @@ def set_offset(self, xy): xy : (float, float) The (x, y) coordinates of the offset in display units. """ - self._offset = xy self.offset_transform.clear() self.offset_transform.translate(xy[0], xy[1]) - self.stale = True - - def get_offset(self): - """Return offset of the container.""" - return self._offset - - def get_window_extent(self, renderer): - # docstring inherited - 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) + super().set_offset(xy) def get_extent(self, renderer): """Return width, height, xdescent, ydescent of box.""" @@ -782,20 +775,9 @@ def set_offset(self, xy): xy : (float, float) The (x, y) coordinates of the offset in display units. """ - self._offset = xy self.offset_transform.clear() self.offset_transform.translate(xy[0], xy[1]) - self.stale = True - - def get_offset(self): - """Return offset of the container.""" - return self._offset - - def get_window_extent(self, renderer): - # docstring inherited - w, h, xd, yd = self.get_extent(renderer) - ox, oy = self.get_offset() - return mtransforms.Bbox.from_bounds(ox - xd, oy - yd, w, h) + super().set_offset(xy) def get_extent(self, renderer): _, h_, d_ = renderer.get_text_width_height_descent( @@ -883,20 +865,9 @@ def set_offset(self, xy): xy : (float, float) The (x, y) coordinates of the offset in display units. """ - self._offset = xy self.offset_transform.clear() self.offset_transform.translate(xy[0], xy[1]) - self.stale = True - - def get_offset(self): - """Return offset of the container.""" - return self._offset - - def get_window_extent(self, renderer): - # docstring inherited - 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) + super().set_offset(xy) def get_extent(self, renderer): # clear the offset transforms @@ -1076,29 +1047,20 @@ def set_bbox_to_anchor(self, bbox, transform=None): def get_window_extent(self, renderer): # docstring inherited - self._update_offset_func(renderer) + # Update the offset func, which depends on the dpi of the renderer + # (because of the padding). w, h, xd, yd = self.get_extent(renderer) - ox, oy = self.get_offset(w, h, xd, yd, renderer) - return Bbox.from_bounds(ox - xd, oy - yd, w, h) - - def _update_offset_func(self, renderer, fontsize=None): - """ - Update the offset func which depends on the dpi of the - renderer (because of the padding). - """ - if fontsize is None: - fontsize = renderer.points_to_pixels( - self.prop.get_size_in_points()) + fontsize = renderer.points_to_pixels(self.prop.get_size_in_points()) - def _offset(w, h, xd, yd, renderer): + def _offset(*args, **kwargs): # args are ignored; left for backcompat. bbox = Bbox.from_bounds(0, 0, w, h) - borderpad = self.borderpad * fontsize + pad = self.borderpad * fontsize bbox_to_anchor = self.get_bbox_to_anchor() - x0, y0 = _get_anchored_bbox( - self.loc, bbox, bbox_to_anchor, borderpad) + x0, y0 = _get_anchored_bbox(self.loc, bbox, bbox_to_anchor, pad) return x0 + xd, y0 + yd self.set_offset(_offset) + return super().get_window_extent(renderer) def update_frame(self, bbox, fontsize=None): self.patch.set_bounds(bbox.bounds) @@ -1110,17 +1072,13 @@ def draw(self, renderer): if not self.get_visible(): return - fontsize = renderer.points_to_pixels(self.prop.get_size_in_points()) - self._update_offset_func(renderer, fontsize) - # update the location and size of the legend bbox = self.get_window_extent(renderer) + fontsize = renderer.points_to_pixels(self.prop.get_size_in_points()) self.update_frame(bbox, fontsize) self.patch.draw(renderer) - width, height, xdescent, ydescent = self.get_extent(renderer) - - px, py = self.get_offset(width, height, xdescent, ydescent, renderer) + px, py = self.get_offset() self.get_child().set_offset((px, py)) self.get_child().draw(renderer) @@ -1230,10 +1188,6 @@ def set_zoom(self, zoom): def get_zoom(self): return self._zoom - def get_offset(self): - """Return offset of the container.""" - return self._offset - def get_children(self): return [self.image] @@ -1603,8 +1557,7 @@ def __init__(self, ref_artist, offsetbox, use_blit=False): def save_offset(self): offsetbox = self.offsetbox renderer = offsetbox.figure._cachedRenderer - w, h, xd, yd = offsetbox.get_extent(renderer) - offset = offsetbox.get_offset(w, h, xd, yd, renderer) + offset = offsetbox.get_offset() self.offsetbox_x, self.offsetbox_y = offset self.offsetbox.set_offset(offset) diff --git a/lib/mpl_toolkits/axes_grid1/inset_locator.py b/lib/mpl_toolkits/axes_grid1/inset_locator.py index 56e3b83573b1..a67126b37a22 100644 --- a/lib/mpl_toolkits/axes_grid1/inset_locator.py +++ b/lib/mpl_toolkits/axes_grid1/inset_locator.py @@ -70,18 +70,11 @@ def draw(self, renderer): def __call__(self, ax, renderer): self.axes = ax - - fontsize = renderer.points_to_pixels(self.prop.get_size_in_points()) - self._update_offset_func(renderer, fontsize) - - width, height, xdescent, ydescent = self.get_extent(renderer) - - px, py = self.get_offset(width, height, 0, 0, renderer) - bbox_canvas = Bbox.from_bounds(px, py, width, height) + bbox = self.get_window_extent(renderer) + px, py = self.get_offset() + bbox_canvas = Bbox.from_bounds(px, py, bbox.width, bbox.height) tr = ax.figure.transFigure.inverted() - bb = TransformedBbox(bbox_canvas, tr) - - return bb + return TransformedBbox(bbox_canvas, tr) class AnchoredSizeLocator(AnchoredLocatorBase):
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: