Skip to content

Commit 497738c

Browse files
committed
Fix baseline alignment when using usetex.
Previously we inferred the baseline of usetex strings with the baseline of the character with the lowest baseline, which is wrong in the presence of indices (see usetex_baseline_test.py). There was an option to use the "preview" latex package to fix that, but that was never made the default and likely cannot as the package is GPL. Instead I can infer the baseline position by "reverse-engineering" the starting instructions of the dvi stream (this was done without consulting the approach in "preview"). The results can be checked using usetex_baseline_test.py (preview=False now looks the same as preview=True; likewise, the output of test_usetex was changed. The text.latex.preview rc can now be deprecated (in a future PR). The test was also updated to include the strings of the usetex_baseline_test example (which may go away once text.latex.preview is removed).
1 parent 9fa950c commit 497738c

File tree

6 files changed

+34
-8
lines changed

6 files changed

+34
-8
lines changed

lib/matplotlib/backends/backend_ps.py

+1-2
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

+17
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ def _output(self):
267267
maxx = max(maxx, x + w)
268268
maxy = max(maxy, y + e)
269269
maxy_pure = max(maxy_pure, y)
270+
if self._baseline_v is not None:
271+
maxy_pure = self._baseline_v # This should normally be the case.
270272

271273
if self.dpi is None:
272274
# special case for ease of debugging: output raw dvi coordinates
@@ -294,9 +296,24 @@ def _read(self):
294296
Read one page from the file. Return True if successful,
295297
False if there were no more pages.
296298
"""
299+
# Pages appear to start with the sequence
300+
# bop (begin of page)
301+
# xxx comment
302+
# down
303+
# push
304+
# down, down
305+
# push
306+
# down (possibly multiple)
307+
# push <= here, v is the baseline position.
308+
# etc.
309+
# (dviasm is useful to explore this structure.)
310+
self._baseline_v = None
297311
while True:
298312
byte = self.file.read(1)[0]
299313
self._dtable[byte](self, byte)
314+
if (self._baseline_v is None
315+
and len(getattr(self, "stack", [])) == 3):
316+
self._baseline_v = self.v
300317
if byte == 140: # end of page
301318
return True
302319
if self.state is _dvistate.post_post: # end of file
Binary file not shown.

lib/matplotlib/tests/test_usetex.py

+15-5
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,30 @@
1414

1515
@image_comparison(baseline_images=['test_usetex'],
1616
extensions=['pdf', 'png'],
17-
tol={'aarch64': 2.868}.get(platform.machine(), 0.3))
17+
tol={'aarch64': 2.868}.get(platform.machine(), 0.3),
18+
style="mpl20")
1819
def test_usetex():
1920
mpl.rcParams['text.usetex'] = True
2021
fig = plt.figure()
2122
ax = fig.add_subplot(111)
22-
ax.text(0.1, 0.2,
23+
kwargs = {"verticalalignment": "baseline", "size": 24,
24+
"bbox": dict(pad=0, edgecolor="k", facecolor="none")}
25+
ax.text(0.2, 0.7,
2326
# the \LaTeX macro exercises character sizing and placement,
2427
# \left[ ... \right\} draw some variable-height characters,
2528
# \sqrt and \frac draw horizontal rules, \mathrm changes the font
2629
r'\LaTeX\ $\left[\int\limits_e^{2e}'
2730
r'\sqrt\frac{\log^3 x}{x}\,\mathrm{d}x \right\}$',
28-
fontsize=24)
29-
ax.set_xticks([])
30-
ax.set_yticks([])
31+
**kwargs)
32+
ax.text(0.2, 0.3, "lg", **kwargs)
33+
ax.text(0.4, 0.3, r"$\frac{1}{2}\pi$", **kwargs)
34+
ax.text(0.6, 0.3, "$p^{3^A}$", **kwargs)
35+
ax.text(0.8, 0.3, "$p_{3_2}$", **kwargs)
36+
for x in {t.get_position()[0] for t in ax.texts}:
37+
ax.axvline(x)
38+
for y in {t.get_position()[1] for t in ax.texts}:
39+
ax.axhline(y)
40+
ax.set_axis_off()
3141

3242

3343
@check_figures_equal()

lib/matplotlib/texmanager.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ def get_text_width_height_descent(self, tex, fontsize, renderer=None):
410410
return width, height + depth, depth
411411

412412
else:
413-
# use dviread. It sometimes returns a wrong descent.
413+
# use dviread.
414414
dvifile = self.make_dvi(tex, fontsize)
415415
with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
416416
page, = dvi

0 commit comments

Comments
 (0)