Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2f4a3e3

Browse files
authored
Merge pull request #17257 from tacaswell/backport_eps_work
Backport eps work
2 parents 687531d + 746c691 commit 2f4a3e3

File tree

7 files changed

+122
-97
lines changed

7 files changed

+122
-97
lines changed

lib/matplotlib/backends/backend_ps.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -543,8 +543,7 @@ def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None):
543543
r'\psfrag{%s}[Bl][Bl][1][%f]{\fontsize{%f}{%f}%s}' % (
544544
thetext, angle, fontsize, fontsize*1.25, tex))
545545
else:
546-
# Stick to the bottom alignment, but this may give incorrect
547-
# baseline some times.
546+
# Stick to the bottom alignment.
548547
pos = _nums_to_str(x-corr, y-bl)
549548
self.psfrag.append(
550549
r'\psfrag{%s}[bl][bl][1][%f]{\fontsize{%f}{%f}%s}' % (
@@ -1234,19 +1233,21 @@ def convert_psfrags(tmpfile, psfrags, font_preamble, custom_preamble,
12341233
"""
12351234
with mpl.rc_context({
12361235
"text.latex.preamble":
1237-
rcParams["text.latex.preamble"] +
1238-
r"\usepackage{psfrag,color}"
1239-
r"\usepackage[dvips]{graphicx}"
1240-
r"\PassOptionsToPackage{dvips}{geometry}"}):
1236+
mpl.rcParams["text.latex.preamble"] +
1237+
r"\usepackage{psfrag,color}""\n"
1238+
r"\usepackage[dvips]{graphicx}""\n"
1239+
r"\geometry{papersize={%(width)sin,%(height)sin},"
1240+
r"body={%(width)sin,%(height)sin},margin=0in}"
1241+
% {"width": paper_width, "height": paper_height}
1242+
}):
12411243
dvifile = TexManager().make_dvi(
1242-
r"\newgeometry{papersize={%(width)sin,%(height)sin},"
1243-
r"body={%(width)sin,%(height)sin}, margin={0in,0in}}""\n"
1244-
r"\begin{figure}"
1245-
r"\centering\leavevmode%(psfrags)s"
1246-
r"\includegraphics*[angle=%(angle)s]{%(epsfile)s}"
1244+
"\n"
1245+
r"\begin{figure}""\n"
1246+
r" \centering\leavevmode""\n"
1247+
r" %(psfrags)s""\n"
1248+
r" \includegraphics*[angle=%(angle)s]{%(epsfile)s}""\n"
12471249
r"\end{figure}"
12481250
% {
1249-
"width": paper_width, "height": paper_height,
12501251
"psfrags": "\n".join(psfrags),
12511252
"angle": 90 if orientation == 'landscape' else 0,
12521253
"epsfile": pathlib.Path(tmpfile).resolve().as_posix(),

lib/matplotlib/dviread.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,12 @@ def _output(self):
269269
maxx = max(maxx, x + w)
270270
maxy = max(maxy, y + e)
271271
maxy_pure = max(maxy_pure, y)
272+
if self._baseline_v is not None:
273+
maxy_pure = self._baseline_v # This should normally be the case.
274+
self._baseline_v = None
275+
276+
if not self.text and not self.boxes: # Avoid infs/nans from inf+/-inf.
277+
return Page(text=[], boxes=[], width=0, height=0, descent=0)
272278

273279
if self.dpi is None:
274280
# special case for ease of debugging: output raw dvi coordinates
@@ -296,9 +302,24 @@ def _read(self):
296302
Read one page from the file. Return True if successful,
297303
False if there were no more pages.
298304
"""
305+
# Pages appear to start with the sequence
306+
# bop (begin of page)
307+
# xxx comment
308+
# down
309+
# push
310+
# down, down
311+
# push
312+
# down (possibly multiple)
313+
# push <= here, v is the baseline position.
314+
# etc.
315+
# (dviasm is useful to explore this structure.)
316+
self._baseline_v = None
299317
while True:
300318
byte = self.file.read(1)[0]
301319
self._dtable[byte](self, byte)
320+
if (self._baseline_v is None
321+
and len(getattr(self, "stack", [])) == 3):
322+
self._baseline_v = self.v
302323
if byte == 140: # end of page
303324
return True
304325
if self.state is _dvistate.post_post: # end of file
Binary file not shown.

lib/matplotlib/tests/test_usetex.py

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import numpy as np
12
import pytest
23
import platform
34

@@ -7,31 +8,56 @@
78
from matplotlib.ticker import EngFormatter
89

910

10-
@pytest.fixture(autouse=True) # All tests in this module use usetex.
11-
def usetex():
12-
if not mpl.checkdep_usetex(True):
13-
pytest.skip('Missing TeX of Ghostscript or dvipng')
14-
mpl.rcParams['text.usetex'] = True
11+
if not mpl.checkdep_usetex(True):
12+
pytestmark = pytest.mark.skip('Missing TeX of Ghostscript or dvipng')
1513

1614

17-
@image_comparison(baseline_images=['test_usetex'],
18-
extensions=['pdf', 'png'],
19-
tol={'aarch64': 2.868}.get(platform.machine(), 0.3))
15+
@image_comparison(
16+
baseline_images=['test_usetex'],
17+
extensions=['pdf', 'png'],
18+
style="mpl20")
2019
def test_usetex():
20+
mpl.rcParams['text.usetex'] = True
2121
fig = plt.figure()
2222
ax = fig.add_subplot(111)
23-
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,
2426
# the \LaTeX macro exercises character sizing and placement,
2527
# \left[ ... \right\} draw some variable-height characters,
2628
# \sqrt and \frac draw horizontal rules, \mathrm changes the font
2729
r'\LaTeX\ $\left[\int\limits_e^{2e}'
2830
r'\sqrt\frac{\log^3 x}{x}\,\mathrm{d}x \right\}$',
29-
fontsize=24)
30-
ax.set_xticks([])
31-
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()
41+
42+
43+
@check_figures_equal()
44+
def test_empty(fig_test, fig_ref):
45+
mpl.rcParams['text.usetex'] = True
46+
fig_test.text(.5, .5, "% a comment")
3247

3348

3449
@check_figures_equal()
3550
def test_unicode_minus(fig_test, fig_ref):
51+
mpl.rcParams['text.usetex'] = True
3652
fig_test.text(.5, .5, "$-$")
3753
fig_ref.text(.5, .5, "\N{MINUS SIGN}")
54+
55+
56+
def test_mathdefault():
57+
plt.rcParams["axes.formatter.use_mathtext"] = True
58+
fig = plt.figure()
59+
fig.add_subplot().set_xlim(-1, 1)
60+
# Check that \mathdefault commands generated by tickers don't cause
61+
# problems when later switching usetex on.
62+
mpl.rcParams['text.usetex'] = True
63+
fig.canvas.draw()

lib/matplotlib/texmanager.py

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,25 @@ def get_custom_preamble(self):
192192
"""Return a string containing user additions to the tex preamble."""
193193
return rcParams['text.latex.preamble']
194194

195+
def _get_preamble(self):
196+
unicode_preamble = "\n".join([
197+
r"\usepackage[utf8]{inputenc}",
198+
r"\DeclareUnicodeCharacter{2212}{\ensuremath{-}}",
199+
]) if rcParams["text.latex.unicode"] else ""
200+
return "\n".join([
201+
r"\documentclass{article}",
202+
# Pass-through \mathdefault, which is used in non-usetex mode to
203+
# use the default text font but was historically suppressed in
204+
# usetex mode.
205+
r"\newcommand{\mathdefault}[1]{#1}",
206+
self._font_preamble,
207+
unicode_preamble,
208+
# Needs to come early so that the custom preamble can change the
209+
# geometry, e.g. in convert_psfrags.
210+
r"\usepackage[papersize=72in,body=70in,margin=1in]{geometry}",
211+
self.get_custom_preamble(),
212+
])
213+
195214
def make_tex(self, tex, fontsize):
196215
"""
197216
Generate a tex file to render the tex string at a specific font size.
@@ -200,29 +219,22 @@ def make_tex(self, tex, fontsize):
200219
"""
201220
basefile = self.get_basefile(tex, fontsize)
202221
texfile = '%s.tex' % basefile
203-
custom_preamble = self.get_custom_preamble()
204222
fontcmd = {'sans-serif': r'{\sffamily %s}',
205223
'monospace': r'{\ttfamily %s}'}.get(self.font_family,
206224
r'{\rmfamily %s}')
207225
tex = fontcmd % tex
208226

209-
unicode_preamble = "\n".join([
210-
r"\usepackage[utf8]{inputenc}",
211-
r"\DeclareUnicodeCharacter{2212}{\ensuremath{-}}",
212-
]) if rcParams["text.latex.unicode"] else ""
213-
214227
s = r"""
215-
\documentclass{article}
216228
%s
217-
%s
218-
%s
219-
\usepackage[papersize={72in,72in},body={70in,70in},margin={1in,1in}]{geometry}
220229
\pagestyle{empty}
221230
\begin{document}
222-
\fontsize{%f}{%f}%s
231+
%% The empty hbox ensures that a page is printed even for empty inputs, except
232+
%% when using psfrag which gets confused by it.
233+
\fontsize{%f}{%f}%%
234+
\ifdefined\psfrag\else\hbox{}\fi%%
235+
%s
223236
\end{document}
224-
""" % (self._font_preamble, unicode_preamble, custom_preamble,
225-
fontsize, fontsize * 1.25, tex)
237+
""" % (self._get_preamble(), fontsize, fontsize * 1.25, tex)
226238
with open(texfile, 'wb') as fh:
227239
if rcParams['text.latex.unicode']:
228240
fh.write(s.encode('utf8'))
@@ -250,27 +262,17 @@ def make_tex_preview(self, tex, fontsize):
250262
"""
251263
basefile = self.get_basefile(tex, fontsize)
252264
texfile = '%s.tex' % basefile
253-
custom_preamble = self.get_custom_preamble()
254265
fontcmd = {'sans-serif': r'{\sffamily %s}',
255266
'monospace': r'{\ttfamily %s}'}.get(self.font_family,
256267
r'{\rmfamily %s}')
257268
tex = fontcmd % tex
258269

259-
unicode_preamble = "\n".join([
260-
r"\usepackage[utf8]{inputenc}",
261-
r"\DeclareUnicodeCharacter{2212}{\ensuremath{-}}",
262-
]) if rcParams["text.latex.unicode"] else ""
263-
264270
# newbox, setbox, immediate, etc. are used to find the box
265271
# extent of the rendered text.
266272

267273
s = r"""
268-
\documentclass{article}
269-
%s
270-
%s
271274
%s
272275
\usepackage[active,showbox,tightpage]{preview}
273-
\usepackage[papersize={72in,72in},body={70in,70in},margin={1in,1in}]{geometry}
274276
275277
%% we override the default showbox as it is treated as an error and makes
276278
%% the exit status not zero
@@ -282,8 +284,7 @@ def make_tex_preview(self, tex, fontsize):
282284
{\fontsize{%f}{%f}%s}
283285
\end{preview}
284286
\end{document}
285-
""" % (self._font_preamble, unicode_preamble, custom_preamble,
286-
fontsize, fontsize * 1.25, tex)
287+
""" % (self._get_preamble(), fontsize, fontsize * 1.25, tex)
287288
with open(texfile, 'wb') as fh:
288289
if rcParams['text.latex.unicode']:
289290
fh.write(s.encode('utf8'))
@@ -391,9 +392,16 @@ def make_png(self, tex, fontsize, dpi):
391392
# see get_rgba for a discussion of the background
392393
if not os.path.exists(pngfile):
393394
dvifile = self.make_dvi(tex, fontsize)
394-
self._run_checked_subprocess(
395-
["dvipng", "-bg", "Transparent", "-D", str(dpi),
396-
"-T", "tight", "-o", pngfile, dvifile], tex)
395+
cmd = ["dvipng", "-bg", "Transparent", "-D", str(dpi),
396+
"-T", "tight", "-o", pngfile, dvifile]
397+
# When testing, disable FreeType rendering for reproducibility; but
398+
# dvipng 1.16 has a bug (fixed in f3ff241) that breaks --freetype0
399+
# mode, so for it we keep FreeType enabled; the image will be
400+
# slightly off.
401+
if (getattr(mpl, "_called_from_pytest", False)
402+
and mpl._get_executable_info("dvipng").version != "1.16"):
403+
cmd.insert(1, "--freetype0")
404+
self._run_checked_subprocess(cmd, tex)
397405
return pngfile
398406

399407
def get_grey(self, tex, fontsize=None, dpi=None):
@@ -446,7 +454,7 @@ def get_text_width_height_descent(self, tex, fontsize, renderer=None):
446454
return width, height + depth, depth
447455

448456
else:
449-
# use dviread. It sometimes returns a wrong descent.
457+
# use dviread.
450458
dvifile = self.make_dvi(tex, fontsize)
451459
with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
452460
page, = dvi

0 commit comments

Comments
 (0)