8000 Fix baseline alignment when using usetex. · matplotlib/matplotlib@ce91174 · GitHub
[go: up one dir, main page]

Skip to content

Commit ce91174

Browse files
anntzerQuLogic
authored andcommitted
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 7d5bca4 commit ce91174

File tree

6 files changed

+41
-12
lines changed

6 files changed

+41
-12
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 not self.text and not self.boxes: # Avoid infs/nans from inf+/-inf.
279285
return Page(text=[], boxes=[], width=0, height=0, descent=0)
@@ -304,9 +310,24 @@ def _read(self):
304310
Read one page from the file. Return True if successful,
305311
False if there were no more pages.
306312
"""
313+
# Pages appear to start with the sequence
314+
# bop (begin of page)
315+
# xxx comment
316+
# down
317+
# push
318+
# down, down
319+
# push
320+
# down (possibly multiple)
321+
# push <= here, v is the baseline position.
322+
# etc.
323+
# (dviasm is useful to explore this structure.)
324+
self._baseline_v = None
307325
while True:
308326
byte = self.file.read(1)[0]
309327
self._dtable[byte](self, byte)
328+
if (self._baseline_v is None
329+
and len(getattr(self, "stack", [])) == 3):
330+
self._baseline_v = self.v
310331
if byte == 140: # end of page
311332
return True
312333
if self.state is _dvistate.post_post: # end of file
Binary file not shown.
Loading

lib/matplotlib/tests/test_usetex.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,33 @@
1212
pytestmark = pytest.mark.skip('Missing TeX of Ghostscript or dvipng')
1313

1414

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-
))
15+
@image_comparison(
16+
baseline_images=['test_usetex'],
17+
extensions=['pdf', 'png'],
18+
tol={'aarch64': 2.868, 'x86_64': 2.868}.get(platform.machine(), 0.3),
19+
style="mpl20")
2020
def test_usetex():
2121
mpl.rcParams['text.usetex'] = True
2222
fig = plt.figure()
2323
ax = fig.add_subplot(111)
24-
ax.text(0.1, 0.2,
24+
kwargs = {"verticalalignment": "baseline", "size": 24,
25+
"bbox": dict(pad=0, edgecolor="k", facecolor="none")}
26+
ax.text(0.2, 0.7,
2527
# the \LaTeX macro exercises character sizing and placement,
2628
# \left[ ... \right\} draw some variable-height characters,
2729
# \sqrt and \frac draw horizontal rules, \mathrm changes the font
2830
r'\LaTeX\ $\left[\int\limits_e^{2e}'
2931
r'\sqrt\frac{\log^3 x}{x}\,\mathrm{d}x \right\}$',
30-
fontsize=24)
31-
ax.set_xticks([])
32-
ax.set_yticks([])
32+
**kwargs)
33+
ax.text(0.2, 0.3, "lg", **kwargs)
34+
ax.text(0.4, 0.3, r"$\frac{1}{2}\pi$", **kwargs)
35+
ax.text(0.6, 0.3, "$p^{3^A}$", **kwargs)
36+
ax.text(0.8, 0.3, "$p_{3_2}$", **kwargs)
37+
for x in {t.get_position()[0] for t in ax.texts}:
38+
ax.axvline(x)
39+
for y in {t.get_position()[1] for t in ax.texts}:
40+
ax.axhline(y)
41+
ax.set_axis_off()
3342

3443

3544
@check_figures_equal()

lib/matplotlib/texmanager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ def get_text_width_height_descent(self, tex, fontsize, renderer=None):
404404
return width, height + depth, depth
405405

406406
else:
407-
# use dviread. It sometimes returns a wrong descent.
407+
# use dviread.
408408
dvifile = self.make_dvi(tex, fontsize)
409409
with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
410410
page, = dvi

0 commit comments

Comments
 (0)
0