Skip to content

Commit da709cf

Browse files
committed
Remove font preamble caching in TexManager.
TexManager has a complex caching machinery (... among other caching layers) to map font-related rcParams to a tex preamble (see `_rc_cache`, `_rc_cache_keys`, `_reinit`) but that's just a matter of a few dict lookups which are negligible compared to invoking the subprocess; so just strip out that caching and always regenerate the font-related preamble. That caching also set some attributes (`texmanager.serif`, etc.) as a side-effect via `setattr`/`getattr`, which are used nowhere else (and it's hard to know they even exist other than figuring out the relevant `setattr` calls); just deprecate them.
1 parent 4ef1da9 commit da709cf

File tree

2 files changed

+44
-45
lines changed

2 files changed

+44
-45
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Deprecations
2+
````````````
3+
4+
The ``TexManager.serif``, ``TexManager.sans_serif``, ``TexManager.cursive`` and
5+
``TexManager.monospace`` attributes are deprecated.

lib/matplotlib/texmanager.py

Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,6 @@ class TexManager:
6666
rgba_arrayd = {}
6767
grey_arrayd = {}
6868

69-
serif = ('cmr', '')
70-
sans_serif = ('cmss', '')
71-
monospace = ('cmtt', '')
72-
cursive = ('pzc', r'\usepackage{chancery}')
7369
font_family = 'serif'
7470
font_families = ('serif', 'sans-serif', 'cursive', 'monospace')
7571

@@ -92,25 +88,40 @@ class TexManager:
9288
'monospace': ('cmtt', r'\usepackage{type1ec}'),
9389
'computer modern roman': ('cmr', r'\usepackage{type1ec}'),
9490
'computer modern sans serif': ('cmss', r'\usepackage{type1ec}'),
95-
'computer modern typewriter': ('cmtt', r'\usepackage{type1ec}')}
96-
97-
_rc_cache = None
98-
_rc_cache_keys = (
99-
('text.latex.preamble', 'text.latex.unicode', 'text.latex.preview',
100-
'font.family') + tuple('font.' + n for n in font_families))
91+
'computer modern typewriter': ('cmtt', r'\usepackage{type1ec}'),
92+
}
10193

10294
@functools.lru_cache() # Always return the same instance.
10395
def __new__(cls):
104-
self = object.__new__(cls)
105-
self._reinit()
106-
return self
107-
108-
def _reinit(self):
109-
if self.texcache is None:
96+
if cls.texcache is None:
11097
raise RuntimeError('Cannot create TexManager, as there is no '
11198
'cache directory available')
99+
Path(cls.texcache).mkdir(parents=True, exist_ok=True)
100+
return object.__new__(cls)
101+
102+
_fonts = {} # Only for deprecation period.
103+
104+
@cbook.deprecated("3.3")
105+
@property
106+
def serif(self):
107+
return self._fonts.get("serif", ('cmr', ''))
108+
109+
@cbook.deprecated("3.3")
110+
@property
111+
def sans_serif(self):
112+
return self._fonts.get("sans-serif", ('cmss', ''))
113+
114+
@cbook.deprecated("3.3")
115+
@property
116+
def cursive(self):
117+
return self._fonts.get("cursive", ('pzc', r'\usepackage{chancery}'))
112118

113-
Path(self.texcache).mkdir(parents=True, exist_ok=True)
119+
@cbook.deprecated("3.3")
120+
@property
121+
def monospace(self):
122+
return self._fonts.get("monospace", ('cmtt', ''))
123+
124+
def get_font_config(self):
114125
ff = rcParams['font.family']
115126
if len(ff) == 1 and ff[0].lower() in self.font_families:
116127
self.font_family = ff[0].lower()
@@ -124,11 +135,9 @@ def _reinit(self):
124135

125136
fontconfig = [self.font_family]
126137
for font_family in self.font_families:
127-
font_family_attr = font_family.replace('-', '_')
128138
for font in rcParams['font.' + font_family]:
129139
if font.lower() in self.font_info:
130-
setattr(self, font_family_attr,
131-
self.font_info[font.lower()])
140+
self._fonts[font_family] = self.font_info[font.lower()]
132141
_log.debug('family: %s, font: %s, info: %s',
133142
font_family, font, self.font_info[font.lower()])
134143
break
@@ -138,22 +147,25 @@ def _reinit(self):
138147
else:
139148
_log.info('No LaTeX-compatible font found for the %s font '
140149
'family in rcParams. Using default.', font_family)
141-
setattr(self, font_family_attr, self.font_info[font_family])
142-
fontconfig.append(getattr(self, font_family_attr)[0])
143-
# Add a hash of the latex preamble to self._fontconfig so that the
150+
self._fonts[font_family] = self.font_info[font_family]
151+
fontconfig.append(self._fonts[font_family][0])
152+
# Add a hash of the latex preamble to fontconfig so that the
144153
# correct png is selected for strings rendered with same font and dpi
145154
# even if the latex preamble changes within the session
146155
preamble_bytes = self.get_custom_preamble().encode('utf-8')
147156
fontconfig.append(hashlib.md5(preamble_bytes).hexdigest())
148-
self._fontconfig = ''.join(fontconfig)
149157

150158
# The following packages and commands need to be included in the latex
151159
# file's preamble:
152-
cmd = [self.serif[1], self.sans_serif[1], self.monospace[1]]
160+
cmd = [self._fonts['serif'][1],
161+
self._fonts['sans-serif'][1],
162+
self._fonts['monospace'][1]]
153163
if self.font_family == 'cursive':
154-
cmd.append(self.cursive[1])
164+
cmd.append(self._fonts['cursive'][1])
155165
self._font_preamble = '\n'.join(
156-
[r'\usepackage{type1cm}'] + cmd + [r'\usepackage{textcomp}'])
166+
[r'\usepackage{type1cm}', *cmd, r'\usepackage{textcomp}'])
167+
168+
return ''.join(fontconfig)
157169

158170
def get_basefile(self, tex, fontsize, dpi=None):
159171
"""
@@ -164,24 +176,6 @@ def get_basefile(self, tex, fontsize, dpi=None):
164176
return os.path.join(
165177
self.texcache, hashlib.md5(s.encode('utf-8')).hexdigest())
166178

167-
def get_font_config(self):
168-
"""Reinitializes self if relevant rcParams on have changed."""
169-
if self._rc_cache is None:
170-
self._rc_cache = dict.fromkeys(self._rc_cache_keys)
171-
changed = [par for par in self._rc_cache_keys
172-
if rcParams[par] != self._rc_cache[par]]
173-
if changed:
174-
_log.debug('following keys changed: %s', changed)
175-
for k in changed:
176-
_log.debug('%-20s: %-10s -> %-10s',
177-
k, self._rc_cache[k], rcParams[k])
178-
# deepcopy may not be necessary, but feels more future-proof
179-
self._rc_cache[k] = copy.deepcopy(rcParams[k])
180-
_log.debug('RE-INIT\nold fontconfig: %s', self._fontconfig)
181-
self._reinit()
182-
_log.debug('fontconfig: %s', self._fontconfig)
183-
return self._fontconfig
184-
185179
def get_font_preamble(self):
186180
"""
187181
Return a string containing font configuration for the tex preamble.

0 commit comments

Comments
 (0)