@@ -122,8 +122,11 @@ def writeln(fh, line):
122122fh .write ("%\n " )
123123
124124
125- def _font_properties_str (prop ):
126- # translate font properties to latex commands, return as string
125+ def _escape_and_apply_props (s ,prop ):
126+ """
127+ Generate a TeX string that renders string *s* with font properties *prop*,
128+ also applying any required escapes to *s*.
129+ """
127130commands = []
128131
129132families = {"serif" :r"\rmfamily" ,"sans" :r"\sffamily" ,
@@ -149,7 +152,7 @@ def _font_properties_str(prop):
149152commands .append (r"\bfseries" )
150153
151154commands .append (r"\selectfont" )
152- return "" .join (commands )
155+ return "" .join (commands )+ " " + common_texification ( s )
153156
154157
155158def _metadata_to_str (key ,value ):
@@ -296,7 +299,10 @@ def __init__(self):
296299"or error in preamble." ,stdout )
297300
298301self .latex = None # Will be set up on first use.
299- self .str_cache = {}# cache for strings already processed
302+ # Per-instance cache.
303+ self ._get_box_metrics = functools .lru_cache ()(self ._get_box_metrics )
304+
305+ str_cache = _api .deprecated ("3.5" )(property (lambda self : {}))
300306
301307def _setup_latex_process (self ):
302308# Open LaTeX process for real work; register it for deletion. On
@@ -322,46 +328,34 @@ def finalize_latex(latex):
322328
323329def get_width_height_descent (self ,text ,prop ):
324330"""
325- Get the width, total height and descentfor a text typeset by the
326- current LaTeX environment.
331+ Get the width, total height, and descent(in TeX points) for a text
332+ typeset by the current LaTeX environment.
327333 """
334+ return self ._get_box_metrics (_escape_and_apply_props (text ,prop ))
328335
329- # apply font properties and define textbox
330- prop_cmds = _font_properties_str (prop )
331- textbox = "\\ sbox0{%s %s}" % (prop_cmds ,text )
332-
333- # check cache
334- if textbox in self .str_cache :
335- return self .str_cache [textbox ]
336-
337- # send textbox to LaTeX and wait for prompt
338- self ._stdin_writeln (textbox )
339- try :
340- self ._expect_prompt ()
341- except LatexError as e :
342- raise ValueError ("Error processing '{}'\n LaTeX Output:\n {}"
343- .format (text ,e .latex_output ))from e
344-
345- # typeout width, height and text offset of the last textbox
346- self ._stdin_writeln (r"\typeout{\the\wd0,\the\ht0,\the\dp0}" )
347- # read answer from latex and advance to the next prompt
336+ def _get_box_metrics (self ,tex ):
337+ """
338+ Get the width, total height and descent (in TeX points) for a TeX
339+ command's output in the current LaTeX environment.
340+ """
341+ # This method gets wrapped in __init__ for per-instance caching.
342+ self ._stdin_writeln (# Send textbox to TeX & request metrics typeout.
343+ r"\sbox0{%s}\typeout{\the\wd0,\the\ht0,\the\dp0}" % tex )
348344try :
349345answer = self ._expect_prompt ()
350- except LatexError as e :
351- raise ValueError ("Error processing '{}'\n LaTeX Output:\n {}"
352- .format (text ,e .latex_output ))from e
353-
354- # parse metrics from the answer string
346+ except LatexError as err :
347+ raise ValueError ("Error measuring {!r}\n LaTeX Output:\n {}"
348+ .format (tex ,err .latex_output ))from err
355349try :
356- width ,height ,offset = answer .splitlines ()[0 ].split ("," )
350+ # Parse metrics from the answer string. Last line is prompt, and
351+ # next-to-last-line is blank line from \typeout.
352+ width ,height ,offset = answer .splitlines ()[- 3 ].split ("," )
357353except Exception as err :
358- raise ValueError ("Errorprocessing '{}' \n LaTeX Output:\n {}"
359- .format (text ,answer ))from err
354+ raise ValueError ("Errormeasuring {!r} \n LaTeX Output:\n {}"
355+ .format (tex ,answer ))from err
360356w ,h ,o = float (width [:- 2 ]),float (height [:- 2 ]),float (offset [:- 2 ])
361-
362- # the height returned from LaTeX goes from base to top.
363- # the height matplotlib expects goes from bottom to top.
364- self .str_cache [textbox ]= (w ,h + o ,o )
357+ # The height returned from LaTeX goes from base to top;
358+ # the height Matplotlib expects goes from bottom to top.
365359return w ,h + o ,o
366360
367361
@@ -671,9 +665,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
671665# docstring inherited
672666
673667# prepare string for tex
674- s = common_texification (s )
675- prop_cmds = _font_properties_str (prop )
676- s = r"%s %s" % (prop_cmds ,s )
668+ s = _escape_and_apply_props (s ,prop )
677669
678670writeln (self .fh ,r"\begin{pgfscope}" )
679671
@@ -718,10 +710,6 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
718710
719711def get_text_width_height_descent (self ,s ,prop ,ismath ):
720712# docstring inherited
721-
722- # check if the math is supposed to be displaystyled
723- s = common_texification (s )
724-
725713# get text metrics in units of latex pt, convert to display units
726714w ,h ,d = (LatexManager ._get_cached_or_new ()
727715 .get_width_height_descent (s ,prop ))