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
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
Actual outcome
On 3.11.2 (3.10.9 gives the same):
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_cachekeys its cache on the renderer, the text, a copy of the font properties,ismath, anddpi. Forismath="TeX"the metrics also depend ontext.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. OtherrcParamsTexManagerreads, such asfont.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 exampletext.latex.preambleand the font settingsTexManagerreads.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