8000 Merge pull request #16476 from anntzer/fix-usetex-baseline · matplotlib/matplotlib@b44ecb6 · GitHub
[go: up one dir, main page]

Skip to content

Commit b44ecb6

Browse files
authored
Merge pull request #16476 from anntzer/fix-usetex-baseline
Fix baseline alignment when using usetex.
2 parents 44aa425 + 8472fbb commit b44ecb6

File tree

6 files changed

+58
-18
lines changed

6 files changed

+58
-18
lines changed

lib/matplotlib/backends/backend_ps.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,7 @@ def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None):
484484
r'\psfrag{%s}[Bl][Bl][1][%f]{\fontsize{%f}{%f}%s}' % (
485485
thetext, angle, fontsize, fontsize*1.25, tex))
486486
else:
487-
# Stick to the bottom alignment, but this may give incorrect
488-
# baseline some times.
487+
# Stick to the bottom alignment.
489488
pos = _nums_to_str(x-corr, y-bl)
490489
self.psfrag.append(
491490
r'\psfrag{%s}[bl][bl][1][%f]{\fontsize{%f}{%f}%s}' % (

lib/matplotlib/dviread.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,12 @@ def _output(self):
274274
maxx = max(maxx, x + w)
275275
maxy = max(maxy, y + e)
276276
maxy_pure = max(maxy_pure, y)
277+
if self._baseline_v is not None:
278+
maxy_pure = self._baseline_v # This should normally be the case.
279+
self._baseline_v = None
280+
281+
if not self.text and not self.boxes: # Avoid infs/nans from inf+/-inf.
282+
return Page(text=[], boxes=[], width=0, height=0, descent=0)
277283

278284
if self.dpi is None:
279285
# special case for ease of debugging: output raw dvi coordinates
@@ -301,9 +307,24 @@ def _read(self):
301307
Read one page from the file. Return True if successful,
302308
False if there were no more pages.
303309
"""
310+
# Pages appear to start with the sequence
311+
# bop (begin of page)
312+
# xxx comment
313+
# down
314+
# push
315+
# down, down
316+
# push
317+
# down (possibly multiple)
318+
# push <= here, v is the baseline position.
319+
# etc.
320+
# (dviasm is useful to explore this structure.)
321+
self._baseline_v = None
304322
while True:
305323
byte = self.file.read(1)[0]
306324
self._dtable[byte](self, byte)
325+
if (self._baseline_v is None
326+
and len(getattr(self, "stack", [])) == 3):
327+
self._baseline_v = self.v
307328
if byte == 140: # end of page
308329
return True
309330
if self.state is _dvistate.post_post: # end of file
Binary file not shown.
Loading

lib/matplotlib/tests/test_usetex.py

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import platform
2-
31
import numpy as np
42
import pytest
53

@@ -12,24 +10,38 @@
1210
pytestmark = pytest.mark.skip('Missing TeX of Ghostscript or dvipng')
1311

1412

15-
@image_comparison(baseline_images=['test_usetex'],
16-
extensions=['pdf', 'png'],
17-
tol={'aarch64': 2.868, 'x86_64': 2.868}.get(
18-
platform.machine(), 0.3
19-
))
13+
@image_comparison(
14+
baseline_images=['test_usetex'],
15+
extensions=['pdf', 'png'],
16+
style="mpl20")
2017
def test_usetex():
2118
mpl.rcParams['text.usetex'] = True
2219
fig = plt.figure()
2320
ax = fig.add_subplot(111)
24-
ax.text(0.1, 0.2,
21+
kwargs = {"verticalalignment": "baseline", "size": 24,
22+
"bbox": dict(pad=0, edgecolor="k", facecolor="none")}
23+
ax.text(0.2, 0.7,
2524
# the \LaTeX macro exercises character sizing and placement,
2625
# \left[ ... \right\} draw some variable-height characters,
2726
# \sqrt and \frac draw horizontal rules, \mathrm changes the font
2827
r'\LaTeX\ $\left[\int\limits_e^{2e}'
2928
r'\sqrt\frac{\log^3 x}{x}\,\mathrm{d}x \right\}$',
30-
fontsize=24)
31-
ax.set_xticks([])
32-
ax.set_yticks([])
29+
**kwargs)
30+
ax.text(0.2, 0.3, "lg", **kwargs)
31+
ax.text(0.4, 0.3, r"$\frac{1}{2}\pi$", **kwargs)
32+
ax.text(0.6, 0.3, "$p^{3^A}$", **kwargs)
33+
ax.text(0.8, 0.3, "$p_{3_2}$", **kwargs)
34+
for x in {t.get_position()[0] for t in ax.texts}:
35+
ax.axvline(x)
36+
for y in {t.get_position()[1] for t in ax.texts}:
37+
ax.axhline(y)
38+
ax.set_axis_off()
39+
40+
41+
@check_figures_equal()
42+
def test_empty(fig_test, fig_ref):
43+
mpl.rcParams['text.usetex'] = True
44+
fig_test.text(.5, .5, "% a comment")
3345

3446

3547
@check_figures_equal()

lib/matplotlib/texmanager.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ def make_tex(self, tex, fontsize):
207207
\usepackage[papersize={72in,72in},body={70in,70in},margin={1in,1in}]{geometry}
208208
\pagestyle{empty}
209209
\begin{document}
210-
\fontsize{%f}{%f}%s
210+
%% The empty hbox ensures that a page is printed even for empty inputs.
211+
\fontsize{%f}{%f}\hbox{}%s
211212
\end{document}
212213
""" % (self._get_preamble(), fontsize, fontsize * 1.25, fontcmd % tex),
213214
encoding='utf-8')
@@ -350,9 +351,16 @@ def make_png(self, tex, fontsize, dpi):
350351
# see get_rgba for a discussion of the background
351352
if not os.path.exists(pngfile):
352353
dvifile = self.make_dvi(tex, fontsize)
353-
self._run_checked_subprocess(
354-
["dvipng", "-bg", "Transparent", "-D", str(dpi),
355-
"-T", "tight", "-o", pngfile, dvifile], tex)
354+
cmd = ["dvipng", "-bg", "Transparent", "-D", str(dpi),
355+
"-T", "tight", "-o", pngfile, dvifile]
356+
# When testing, disable FreeType rendering for reproducibility; but
357+
# dvipng 1.16 has a bug (fixed in f3ff241) that breaks --freetype0
358+
# mode, so for it we keep FreeType enabled; the image will be
359+
# slightly off.
360+
if (getattr(mpl, "_called_from_pytest", False)
361+
and mpl._get_executable_info("dvipng").version != "1.16"):
362+
cmd.insert(1, "--freetype0")
363+
self._run_checked_subprocess(cmd, tex)
356364
return pngfile
357365

358366
def get_grey(self, tex, fontsize=None, dpi=None):
@@ -403,7 +411,7 @@ def get_text_width_height_descent(self, tex, fontsize, renderer=None):
403411
return width, height + depth, depth
404412

405413
else:
406-
# use dviread. It sometimes returns a wrong descent.
414+
# use dviread.
407415
dvifile = self.make_dvi(tex, fontsize)
408416
with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
409417
page, = dvi

0 commit comments

Comments
 (0)
0