Skip to content

[Bug]: Changing text.latex.preamble does not invalidate cached usetex text metrics #32413

Description

@thiebes

Bug summary

With usetex, Matplotlib caches text metrics without the LaTeX preamble in the cache key. After text.latex.preamble changes, redrawing an existing figure keeps the old text widths. On 3.10 and later, a new Text in the same figure also gets the old width. Only a new figure measures the text correctly.

Code for reproduction

import matplotlib
matplotlib.use("Agg")
import matplotlib as mpl
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
text = ax.text(0.1, 0.5, "Hmx minimum", usetex=True, fontsize=30)
fig.canvas.draw()
print("before:", text.get_window_extent().width)

with mpl.rc_context({"text.latex.preamble": r"\usepackage{helvet}"}):
    fig.canvas.draw()
    print("after, same Text:", text.get_window_extent().width)

    new = ax.text(0.1, 0.2, "Hmx minimum", usetex=True, fontsize=30)
    fig.canvas.draw()
    print("after, new Text in the same figure:", new.get_window_extent().width)

    fig2, ax2 = plt.subplots()
    fresh = ax2.text(0.1, 0.5, "Hmx minimum", usetex=True, fontsize=30)
    fig2.canvas.draw()
    print("after, new figure:", fresh.get_window_extent().width)

Actual outcome

On 3.11.2 (3.10.9 gives the same):

  • before: 240.82454619639245
  • after, same Text: 240.82454619639245
  • after, new Text in the same figure: 240.82454619639245
  • after, new figure: 264.75527647110005

On 3.5.3, the new Text in the same figure measures 264.755 and the same Text keeps 240.825.

Expected outcome

All three "after" widths should be 264.755, the width of the text set in Helvetica.

Additional information

matplotlib.text._get_text_metrics_with_cache keys its cache on the renderer, the text, a copy of the font properties, ismath, and dpi. For ismath="TeX" the metrics also depend on text.latex.preamble, which is not in the key, so a cached Computer Modern measurement is reused for Helvetica text. Before 3.10 the layout cache was per Text, which is why 3.5.3 measures a new Text correctly but still reuses the old width for an existing one. Other rcParams TexManager reads, such as font.family, are probably affected the same way; I verified only the preamble.

A possible fix: when ismath="TeX", include the TeX font configuration in the key, for example text.latex.preamble and the font settings TexManager reads.

I found this while adding usetex support to curved-text, a library that draws text along curves; its labels inherit the same stale widths.

Operating system

Windows 11

Matplotlib Version

3.11.2 (also 3.10.9 and 3.5.3)

Matplotlib Backend

Agg

Python version

3.13.3

Jupyter version

none

Installation

pip

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions