Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions lib/matplotlib/axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -1422,25 +1422,41 @@ def _update_ticks(self):
if (self._tick_group_visible(self._major_tick_kw)
and not isinstance(self.get_major_locator(), NullLocator)):
major_locs = self.get_majorticklocs()
major_labels = self.major.formatter.format_ticks(major_locs)
major_formatter = self.major.formatter
major_labels = major_formatter.format_ticks(major_locs)
major_is_custom = (
isinstance(major_formatter, mticker.FuncFormatter)
and getattr(major_formatter,
"_is_custom_ticklabel_formatter", True))
major_ticks = self.get_major_ticks(len(major_locs))
for tick, loc, label in zip(major_ticks, major_locs, major_labels):
tick.update_position(loc)
tick.label1.set_text(label)
tick.label2.set_text(label)
# Custom formatters can produce labels with different
# ascenders, so let Text use a common line box for them.
tick.label1._is_ticklabel = major_is_custom
tick.label2._is_ticklabel = major_is_custom
else:
major_ticks = []

# Check if minor ticks should be computed.
if (self._tick_group_visible(self._minor_tick_kw)
and not isinstance(self.get_minor_locator(), NullLocator)):
minor_locs = self.get_minorticklocs()
minor_labels = self.minor.formatter.format_ticks(minor_locs)
minor_formatter = self.minor.formatter
minor_labels = minor_formatter.format_ticks(minor_locs)
minor_is_custom = (
isinstance(minor_formatter, mticker.FuncFormatter)
and getattr(minor_formatter,
"_is_custom_ticklabel_formatter", True))
minor_ticks = self.get_minor_ticks(len(minor_locs))
for tick, loc, label in zip(minor_ticks, minor_locs, minor_labels):
tick.update_position(loc)
tick.label1.set_text(label)
tick.label2.set_text(label)
tick.label1._is_ticklabel = minor_is_custom
tick.label2._is_ticklabel = minor_is_custom
else:
minor_ticks = []

Expand Down Expand Up @@ -2345,6 +2361,10 @@ def set_ticklabels(self, labels, *, minor=False, fontdict=None, **kwargs):
tickd = {loc: lab for loc, lab in zip(fixed_locator.locs, labels)}
func = functools.partial(self._format_with_dict, tickd)
formatter = mticker.FuncFormatter(func)
# ``set_ticklabels`` uses a ``FuncFormatter`` internally, but
# these are fixed labels rather than user-defined formatting.
# Keep them on the existing text-layout path.
formatter._is_custom_ticklabel_formatter = False
else:
_api.warn_external(
"set_ticklabels() should only be used with a fixed number of "
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/boxplot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/bxp_baseline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/bxp_rangewhis.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/extent_units.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/grouped_bar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions lib/matplotlib/tests/test_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,21 @@ def draw_box(ax, tt):
ax.text(1.2, 0.1, 'Bot align, rot20', color='C2')


def test_top_aligned_text_has_consistent_baseline():
fig, ax = plt.subplots(figsize=(.5, .5), layout="constrained")
ax.set_yticks([])
ax.set_xlim(-2, 3)
ax.set_xticks([0, 1])
ax.xaxis.set_major_formatter(
lambda x, pos: "pol." if x == 0 else str(int(x)))

fig.canvas.draw()
bboxes = [label.get_window_extent() for label in ax.get_xticklabels()]

# Labels with different ascenders must still share a baseline.
assert_almost_equal(bboxes[0].y0, bboxes[1].y0)


@image_comparison(['antialiased.png'], style='mpl20')
def test_antialiasing():
mpl.rcParams['text.antialiased'] = False # Passed arguments should override.
Expand Down
16 changes: 16 additions & 0 deletions lib/matplotlib/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,22 @@ def _get_layout(self, renderer):
min_ascent = h - min_descent
line_gap = 0

if (getattr(self, "_is_ticklabel", False)
and self._verticalalignment == "top"
and self.get_rotation() == 0
and len(lines) == 1):
# Top-aligned single-line text should use a common line box. In
# particular, this keeps the baselines of tick labels with
# different ascenders aligned (e.g. ``"pol."`` and ``"1"``).
# The font tables alone do not necessarily include the full
# ascent of the glyphs used by the renderer.
_, lp_h, lp_d = _get_text_metrics_with_cache(
renderer, "lp", self._fontproperties,
ismath="TeX" if self.get_usetex() else False,
dpi=dpi)
min_ascent = max(min_ascent, lp_h - lp_d)
min_descent = max(min_descent, lp_d)

# Don't increase text height too much if it's not multiple lines.
if len(lines) == 1:
line_gap = 0
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading