Skip to content

Commit a46dd3b

Browse files
committed
Replace sole use of maxdict by lru_cache.
... and expand the cache size, while we're at it.
1 parent 9844e9f commit a46dd3b

File tree

2 files changed

+28
-22
lines changed

2 files changed

+28
-22
lines changed

lib/matplotlib/tests/test_text.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,8 @@ def test_pdf_chars_beyond_bmp():
768768

769769
@needs_usetex
770770
def test_metrics_cache():
771+
mpl.text._get_text_metrics_with_cache_impl.cache_clear()
772+
771773
fig = plt.figure()
772774
fig.text(.3, .5, "foo\nbar")
773775
fig.text(.3, .5, "foo\nbar", usetex=True)
@@ -788,3 +790,8 @@ def call(*args, **kwargs):
788790
# collision with the non-TeX string (drawn first here) whose metrics would
789791
# get incorrectly reused by the first TeX string.
790792
assert len(ys["foo"]) == len(ys["bar"]) == 1
793+
794+
info = mpl.text._get_text_metrics_with_cache_impl.cache_info()
795+
# Every string gets a miss for the first layouting (extents), then a hit
796+
# when drawing, but "foo\nbar" gets two hits as it's drawn twice.
797+
assert info.hits > info.misses

lib/matplotlib/text.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Classes for including text in a figure.
33
"""
44

5+
import functools
56
import logging
67
import math
78
import numbers
@@ -89,6 +90,21 @@ def _get_textbox(text, renderer):
8990
return x_box, y_box, w_box, h_box
9091

9192

93+
def _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi):
94+
"""Call ``renderer.get_text_width_height_descent``, caching the results."""
95+
# Cached based on a copy of fontprop so that later in-place mutations of
96+
# the passed-in argument do not mess up the cache.
97+
return _get_text_metrics_with_cache_impl(
98+
weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)
99+
100+
101+
@functools.lru_cache(4096)
102+
def _get_text_metrics_with_cache_impl(
103+
renderer_ref, text, fontprop, ismath, dpi):
104+
# dpi is unused, but participates in cache invalidation (via the renderer).
105+
return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)
106+
107+
92108
@docstring.interpd
93109
@cbook._define_aliases({
94110
"color": ["c"],
@@ -108,7 +124,6 @@ class Text(Artist):
108124
"""Handle storing and drawing of text in window or data coordinates."""
109125

110126
zorder = 3
111-
_cached = cbook.maxdict(50)
112127

113128
def __repr__(self):
114129
return "Text(%s, %s, %s)" % (self._x, self._y, repr(self._text))
@@ -273,23 +288,6 @@ def update_from(self, other):
273288
self._linespacing = other._linespacing
274289
self.stale = True
275290

276-
def _get_text_metrics_with_cache(
277-
self, renderer, text, fontproperties, ismath):
278-
"""
279-
Call ``renderer.get_text_width_height_descent``, caching the results.
280-
"""
281-
cache_key = (
282-
weakref.ref(renderer),
283-
text,
284-
hash(fontproperties),
285-
ismath,
286-
self.figure.dpi,
287-
)
288-
if cache_key not in self._cached:
289-
self._cached[cache_key] = renderer.get_text_width_height_descent(
290-
text, fontproperties, ismath)
291-
return self._cached[cache_key]
292-
293291
def _get_layout(self, renderer):
294292
"""
295293
Return the extent (bbox) of the text together with
@@ -305,16 +303,17 @@ def _get_layout(self, renderer):
305303
ys = []
306304

307305
# Full vertical extent of font, including ascenders and descenders:
308-
_, lp_h, lp_d = self._get_text_metrics_with_cache(
306+
_, lp_h, lp_d = _get_text_metrics_with_cache(
309307
renderer, "lp", self._fontproperties,
310-
ismath="TeX" if self.get_usetex() else False)
308+
ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
311309
min_dy = (lp_h - lp_d) * self._linespacing
312310

313311
for i, line in enumerate(lines):
314312
clean_line, ismath = self._preprocess_math(line)
315313
if clean_line:
316-
w, h, d = self._get_text_metrics_with_cache(
317-
renderer, clean_line, self._fontproperties, ismath)
314+
w, h, d = _get_text_metrics_with_cache(
315+
renderer, clean_line, self._fontproperties,
316+
ismath=ismath, dpi=self.figure.dpi)
318317
else:
319318
w = h = d = 0
320319

0 commit comments

Comments
 (0)