diff --git a/lib/matplotlib/tests/test_usetex.py b/lib/matplotlib/tests/test_usetex.py index 6dd3d08f4291..1b7b76bfc0f2 100644 --- a/lib/matplotlib/tests/test_usetex.py +++ b/lib/matplotlib/tests/test_usetex.py @@ -6,17 +6,15 @@ import matplotlib.pyplot as plt -@pytest.fixture(autouse=True) # All tests in this module use usetex. -def usetex(): - if not mpl.checkdep_usetex(True): - pytest.skip('Missing TeX of Ghostscript or dvipng') - mpl.rcParams['text.usetex'] = True +if not mpl.checkdep_usetex(True): + pytestmark = pytest.mark.skip('Missing TeX of Ghostscript or dvipng') @image_comparison(baseline_images=['test_usetex'], extensions=['pdf', 'png'], tol={'aarch64': 2.868}.get(platform.machine(), 0.3)) def test_usetex(): + mpl.rcParams['text.usetex'] = True fig = plt.figure() ax = fig.add_subplot(111) ax.text(0.1, 0.2, @@ -32,5 +30,16 @@ def test_usetex(): @check_figures_equal() def test_unicode_minus(fig_test, fig_ref): + mpl.rcParams['text.usetex'] = True fig_test.text(.5, .5, "$-$") fig_ref.text(.5, .5, "\N{MINUS SIGN}") + + +def test_mathdefault(): + plt.rcParams["axes.formatter.use_mathtext"] = True + fig = plt.figure() + fig.add_subplot().set_xlim(-1, 1) + # Check that \mathdefault commands generated by tickers don't cause + # problems when later switching usetex on. + mpl.rcParams['text.usetex'] = True + fig.canvas.draw() diff --git a/lib/matplotlib/texmanager.py b/lib/matplotlib/texmanager.py index 3847a1a09358..bdbb38d711d9 100644 --- a/lib/matplotlib/texmanager.py +++ b/lib/matplotlib/texmanager.py @@ -192,6 +192,22 @@ def get_custom_preamble(self): """Return a string containing user additions to the tex preamble.""" return rcParams['text.latex.preamble'] + def _get_preamble(self): + unicode_preamble = "\n".join([ + r"\usepackage[utf8]{inputenc}", + r"\DeclareUnicodeCharacter{2212}{\ensuremath{-}}", + ]) if rcParams["text.latex.unicode"] else "" + return "\n".join([ + r"\documentclass{article}", + # Pass-through \mathdefault, which is used in non-usetex mode to + # use the default text font but was historically suppressed in + # usetex mode. + r"\newcommand{\mathdefault}[1]{#1}", + self._font_preamble, + unicode_preamble, + self.get_custom_preamble(), + ]) + def make_tex(self, tex, fontsize): """ Generate a tex file to render the tex string at a specific font size. @@ -200,29 +216,19 @@ def make_tex(self, tex, fontsize): """ basefile = self.get_basefile(tex, fontsize) texfile = '%s.tex' % basefile - custom_preamble = self.get_custom_preamble() fontcmd = {'sans-serif': r'{\sffamily %s}', 'monospace': r'{\ttfamily %s}'}.get(self.font_family, r'{\rmfamily %s}') tex = fontcmd % tex - unicode_preamble = "\n".join([ - r"\usepackage[utf8]{inputenc}", - r"\DeclareUnicodeCharacter{2212}{\ensuremath{-}}", - ]) if rcParams["text.latex.unicode"] else "" - s = r""" -\documentclass{article} -%s -%s %s \usepackage[papersize={72in,72in},body={70in,70in},margin={1in,1in}]{geometry} \pagestyle{empty} \begin{document} \fontsize{%f}{%f}%s \end{document} -""" % (self._font_preamble, unicode_preamble, custom_preamble, - fontsize, fontsize * 1.25, tex) +""" % (self._get_preamble(), fontsize, fontsize * 1.25, tex) with open(texfile, 'wb') as fh: if rcParams['text.latex.unicode']: fh.write(s.encode('utf8')) @@ -250,24 +256,15 @@ def make_tex_preview(self, tex, fontsize): """ basefile = self.get_basefile(tex, fontsize) texfile = '%s.tex' % basefile - custom_preamble = self.get_custom_preamble() fontcmd = {'sans-serif': r'{\sffamily %s}', 'monospace': r'{\ttfamily %s}'}.get(self.font_family, r'{\rmfamily %s}') tex = fontcmd % tex - unicode_preamble = "\n".join([ - r"\usepackage[utf8]{inputenc}", - r"\DeclareUnicodeCharacter{2212}{\ensuremath{-}}", - ]) if rcParams["text.latex.unicode"] else "" - # newbox, setbox, immediate, etc. are used to find the box # extent of the rendered text. s = r""" -\documentclass{article} -%s -%s %s \usepackage[active,showbox,tightpage]{preview} \usepackage[papersize={72in,72in},body={70in,70in},margin={1in,1in}]{geometry} @@ -282,8 +279,7 @@ def make_tex_preview(self, tex, fontsize): {\fontsize{%f}{%f}%s} \end{preview} \end{document} -""" % (self._font_preamble, unicode_preamble, custom_preamble, - fontsize, fontsize * 1.25, tex) +""" % (self._get_preamble(), fontsize, fontsize * 1.25, tex) with open(texfile, 'wb') as fh: if rcParams['text.latex.unicode']: fh.write(s.encode('utf8')) diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py index f30335e8a387..842f506eb55d 100644 --- a/lib/matplotlib/ticker.py +++ b/lib/matplotlib/ticker.py @@ -188,10 +188,6 @@ 'SymmetricalLogLocator', 'LogitLocator', 'OldAutoLocator') -def _mathdefault(s): - return '\\mathdefault{%s}' % s - - class _DummyAxis: def __init__(self, minpos=0): self.dataLim = mtransforms.Bbox.unit() @@ -654,14 +650,10 @@ def get_offset(self): sciNotStr = self.format_data(10 ** self.orderOfMagnitude) else: sciNotStr = '1e%d' % self.orderOfMagnitude - if self._useMathText: - if sciNotStr != '': - sciNotStr = r'\times%s' % _mathdefault(sciNotStr) - s = ''.join(('$', sciNotStr, _mathdefault(offsetStr), '$')) - elif self._usetex: + if self._useMathText or self._usetex: if sciNotStr != '': - sciNotStr = r'\times%s' % sciNotStr - s = ''.join(('$', sciNotStr, offsetStr, '$')) + sciNotStr = r'\times\mathdefault{%s}' % sciNotStr + s = r'$%s\mathdefault{%s}$' % (sciNotStr, offsetStr) else: s = ''.join((sciNotStr, offsetStr)) @@ -784,10 +776,8 @@ def _set_format(self): break sigfigs += 1 self.format = '%1.' + str(sigfigs) + 'f' - if self._usetex: - self.format = '$%s$' % self.format - elif self._useMathText: - self.format = '$%s$' % _mathdefault(self.format) + if self._usetex or self._useMathText: + self.format = r'$\mathdefault{%s}$' % self.format @cbook.deprecated("3.1") def pprint_val(self, x): @@ -1079,11 +1069,7 @@ class LogFormatterMathtext(LogFormatter): def _non_decade_format(self, sign_string, base, fx, usetex): 'Return string for non-decade locations' - if usetex: - return (r'$%s%s^{%.2f}$') % (sign_string, base, fx) - else: - return ('$%s$' % _mathdefault('%s%s^{%.2f}' % - (sign_string, base, fx))) + return r'$\mathdefault{%s%s^{%.2f}}$' % (sign_string, base, fx) def __call__(self, x, pos=None): """ @@ -1095,10 +1081,7 @@ def __call__(self, x, pos=None): min_exp = rcParams['axes.formatter.min_exponent'] if x == 0: # Symlog - if usetex: - return '$0$' - else: - return '$%s$' % _mathdefault('0') + return r'$\mathdefault{0}$' sign_string = '-' if x < 0 else '' x = abs(x) @@ -1124,17 +1107,11 @@ def __call__(self, x, pos=None): base = '%s' % b if abs(fx) < min_exp: - if usetex: - return r'${0}{1:g}$'.format(sign_string, x) - else: - return '${0}$'.format(_mathdefault( - '{0}{1:g}'.format(sign_string, x))) + return r'$\mathdefault{%s%g}$' % (sign_string, x) elif not is_x_decade: return self._non_decade_format(sign_string, base, fx, usetex) - elif usetex: - return r'$%s%s^{%d}$' % (sign_string, base, fx) else: - return '$%s$' % _mathdefault('%s%s^{%d}' % (sign_string, base, fx)) + return r'$\mathdefault{%s%s^{%d}}$' % (sign_string, base, fx) class LogFormatterSciNotation(LogFormatterMathtext): @@ -1149,12 +1126,8 @@ def _non_decade_format(self, sign_string, base, fx, usetex): coeff = b ** fx / b ** exponent if is_close_to_int(coeff): coeff = round(coeff) - if usetex: - return (r'$%s%g\times%s^{%d}$') % \ - (sign_string, coeff, base, exponent) - else: - return ('$%s$' % _mathdefault(r'%s%g\times%s^{%d}' % - (sign_string, coeff, base, exponent))) + return r'$\mathdefault{%s%g\times%s^{%d}}$' \ + % (sign_string, coeff, base, exponent) class LogitFormatter(Formatter): @@ -1326,8 +1299,6 @@ def __call__(self, x, pos=None): return "" if x <= 0 or x >= 1: return "" - usetex = rcParams["text.usetex"] - if is_close_to_int(2 * x) and round(2 * x) == 1: s = self._one_half elif x < 0.5 and is_decade(x, rtol=1e-7): @@ -1342,9 +1313,7 @@ def __call__(self, x, pos=None): s = self._one_minus(self._format_value(1-x, 1-self.locs)) else: s = self._format_value(x, self.locs, sci_notation=False) - if usetex: - return "$%s$" % s - return "$%s$" % _mathdefault(s) + return r"$\mathdefault{%s}$" % s def format_data_short(self, value): """