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

Skip to content

Commit 43de13f

Browse files
committed
backend_ps cleanup.
Dedupe some code between backend_ps and backend_bases (the edgecolor and facecolor handling -- see changelog), as well as between the non-tex and tex cases (by formatting the header metadata ("dsc_comments") earlier). Also simplify a bit papersize handling in usetex case.
1 parent ac0bd8f commit 43de13f

File tree

2 files changed

+54
-104
lines changed

2 files changed

+54
-104
lines changed

doc/api/next_api_changes/behaviour.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,14 @@ multiple plot calls.
106106
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
107107
It previously raised `TypeError`, **except** when the input was of the form
108108
``b"C[number]"`` in which case it raised a ValueError.
109+
110+
`.FigureCanvasPS.print_ps` and `.FigureCanvasPS.print_eps` no longer apply edgecolor and facecolor
111+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
112+
113+
These methods now assume that the figure edge and facecolor have been correctly
114+
applied by `.FigureCanvasBase.print_figure`, as they are normally called
115+
through it.
116+
117+
This behavior is consistent with other figure saving methods
118+
(`.FigureCanvasAgg.print_png`, `.FigureCanvasPdf.print_pdf`,
119+
`.FigureCanvasSVG.print_svg`).

lib/matplotlib/backends/backend_ps.py

Lines changed: 43 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -764,10 +764,30 @@ def print_ps(self, outfile, *args, **kwargs):
764764
def print_eps(self, outfile, *args, **kwargs):
765765
return self._print_ps(outfile, 'eps', *args, **kwargs)
766766

767-
def _print_ps(self, outfile, format, *args,
768-
papertype=None, dpi=72, facecolor='w', edgecolor='w',
769-
orientation='portrait',
770-
**kwargs):
767+
def _print_ps(
768+
self, outfile, format, *args,
769+
dpi=72, metadata=None, papertype=None, orientation='portrait',
770+
**kwargs):
771+
772+
self.figure.set_dpi(72) # Override the dpi kwarg
773+
774+
dsc_comments = {}
775+
if isinstance(outfile, (str, os.PathLike)):
776+
dsc_comments["Title"] = \
777+
os.fspath(outfile).encode("ascii", "replace").decode("ascii")
778+
dsc_comments["Creator"] = (metadata or {}).get(
779+
"Creator",
780+
f"matplotlib version {mpl.__version__}, http://matplotlib.org/")
781+
# See https://reproducible-builds.org/specs/source-date-epoch/
782+
source_date_epoch = os.getenv("SOURCE_DATE_EPOCH")
783+
dsc_comments["CreationDate"] = (
784+
datetime.datetime.utcfromtimestamp(
785+
int(source_date_epoch)).strftime("%a %b %d %H:%M:%S %Y")
786+
if source_date_epoch
787+
else time.ctime())
788+
dsc_comments = "\n".join(
789+
f"%%{k}: {v}" for k, v in dsc_comments.items())
790+
771791
if papertype is None:
772792
papertype = mpl.rcParams['ps.papersize']
773793
papertype = papertype.lower()
@@ -776,42 +796,29 @@ def _print_ps(self, outfile, format, *args,
776796
orientation = cbook._check_getitem(
777797
_Orientation, orientation=orientation.lower())
778798

779-
self.figure.set_dpi(72) # Override the dpi kwarg
780-
781799
printer = (self._print_figure_tex
782800
if mpl.rcParams['text.usetex'] else
783801
self._print_figure)
784-
printer(outfile, format, dpi, facecolor, edgecolor,
785-
orientation, papertype, **kwargs)
802+
printer(outfile, format, dpi=dpi, dsc_comments=dsc_comments,
803+
orientation=orientation, papertype=papertype, **kwargs)
786804

787805
@cbook._delete_parameter("3.2", "dryrun")
788806
def _print_figure(
789-
self, outfile, format, dpi, facecolor, edgecolor,
790-
orientation, papertype, *,
791-
metadata=None, dryrun=False, bbox_inches_restore=None, **kwargs):
807+
self, outfile, format, *,
808+
dpi, dsc_comments, orientation, papertype,
809+
dryrun=False, bbox_inches_restore=None, **kwargs):
792810
"""
793-
Render the figure to hardcopy. Set the figure patch face and
794-
edge colors. This is useful because some of the GUIs have a
795-
gray figure face color background and you'll probably want to
796-
override this on hardcopy
797-
798-
If outfile is a string, it is interpreted as a file name.
799-
If the extension matches .ep* write encapsulated postscript,
800-
otherwise write a stand-alone PostScript file.
801-
802-
If outfile is a file object, a stand-alone PostScript file is
803-
written into this file object.
811+
Render the figure to a filesystem path or a file-like object.
804812
805-
metadata must be a dictionary. Currently, only the value for
806-
the key 'Creator' is used.
813+
Parameters are as for `.print_figure`, except that *dsc_comments* is a
814+
all string containing Document Structuring Convention comments,
815+
generated from the *metadata* parameter to `.print_figure`.
807816
"""
808817
is_eps = format == 'eps'
809818
if isinstance(outfile, (str, os.PathLike)):
810-
outfile = title = os.fspath(outfile)
811-
title = title.encode("ascii", "replace").decode("ascii")
819+
outfile = os.fspath(outfile)
812820
passed_in_file_object = False
813821
elif is_writable_file_like(outfile):
814-
title = None
815822
passed_in_file_object = True
816823
else:
817824
raise ValueError("outfile must be a path or a file-like object")
@@ -848,12 +855,6 @@ def _print_figure(
848855
rotation = 90
849856
bbox = (llx, lly, urx, ury)
850857

851-
# generate PostScript code for the figure and store it in a string
852-
origfacecolor = self.figure.get_facecolor()
853-
origedgecolor = self.figure.get_edgecolor()
854-
self.figure.set_facecolor(facecolor)
855-
self.figure.set_edgecolor(edgecolor)
856-
857858
if dryrun:
858859
class NullWriter:
859860
def write(self, *args, **kwargs):
@@ -874,16 +875,6 @@ def write(self, *args, **kwargs):
874875
if dryrun: # return immediately if dryrun (tightbbox=True)
875876
return
876877

877-
self.figure.set_facecolor(origfacecolor)
878-
self.figure.set_edgecolor(origedgecolor)
879-
880-
# check for custom metadata
881-
if metadata is not None and 'Creator' in metadata:
882-
creator_str = metadata['Creator']
883-
else:
884-
creator_str = \
885-
f"matplotlib version {mpl.__version__}, http://matplotlib.org/"
886-
887878
def print_figure_impl(fh):
888879
# write the PostScript headers
889880
if is_eps:
@@ -893,18 +884,7 @@ def print_figure_impl(fh):
893884
f"%%DocumentPaperSizes: {papertype}\n"
894885
f"%%Pages: 1\n",
895886
end="", file=fh)
896-
if title:
897-
print("%%Title: " + title, file=fh)
898-
# get source date from SOURCE_DATE_EPOCH, if set
899-
# See https://reproducible-builds.org/specs/source-date-epoch/
900-
source_date_epoch = os.getenv("SOURCE_DATE_EPOCH")
901-
if source_date_epoch:
902-
source_date = datetime.datetime.utcfromtimestamp(
903-
int(source_date_epoch)).strftime("%a %b %d %H:%M:%S %Y")
904-
else:
905-
source_date = time.ctime()
906-
print(f"%%Creator: {creator_str}\n"
907-
f"%%CreationDate: {source_date}\n"
887+
print(f"{dsc_comments}\n"
908888
f"%%Orientation: {orientation.name}\n"
909889
f"%%BoundingBox: {bbox[0]} {bbox[1]} {bbox[2]} {bbox[3]}\n"
910890
f"%%EndComments\n",
@@ -1008,28 +988,18 @@ def print_figure_impl(fh):
1008988

1009989
@cbook._delete_parameter("3.2", "dryrun")
1010990
def _print_figure_tex(
1011-
self, outfile, format, dpi, facecolor, edgecolor,
1012-
orientation, papertype, *,
1013-
metadata=None, dryrun=False, bbox_inches_restore=None, **kwargs):
991+
self, outfile, format, *,
992+
dpi, dsc_comments, orientation, papertype,
993+
dryrun=False, bbox_inches_restore=None, **kwargs):
1014994
"""
1015-
If text.usetex is True in rc, a temporary pair of tex/eps files
995+
If :rc:`text.usetex` is True, a temporary pair of tex/eps files
1016996
are created to allow tex to manage the text layout via the PSFrags
1017997
package. These files are processed to yield the final ps or eps file.
1018998
1019-
metadata must be a dictionary. Currently, only the value for
1020-
the key 'Creator' is used.
999+
The rest of the behavior is as for `._print_figure`.
10211000
"""
10221001
is_eps = format == 'eps'
1023-
if is_writable_file_like(outfile):
1024-
title = None
1025-
else:
1026-
try:
1027-
title = os.fspath(outfile)
1028-
except TypeError as err:
1029-
raise ValueError(
1030-
"outfile must be a path or a file-like object") from err
10311002

1032-
self.figure.dpi = 72 # ignore the dpi kwarg
10331003
width, height = self.figure.get_size_inches()
10341004
xo = 0
10351005
yo = 0
@@ -1041,12 +1011,6 @@ def _print_figure_tex(
10411011
ury = lly + h
10421012
bbox = (llx, lly, urx, ury)
10431013

1044-
# generate PostScript code for the figure and store it in a string
1045-
origfacecolor = self.figure.get_facecolor()
1046-
origedgecolor = self.figure.get_edgecolor()
1047-
self.figure.set_facecolor(facecolor)
1048-
self.figure.set_edgecolor(edgecolor)
1049-
10501014
if dryrun:
10511015
class NullWriter:
10521016
def write(self, *args, **kwargs):
@@ -1067,35 +1031,13 @@ def write(self, *args, **kwargs):
10671031
if dryrun: # return immediately if dryrun (tightbbox=True)
10681032
return
10691033

1070-
self.figure.set_facecolor(origfacecolor)
1071-
self.figure.set_edgecolor(origedgecolor)
1072-
1073-
# check for custom metadata
1074-
if metadata is not None and 'Creator' in metadata:
1075-
creator_str = metadata['Creator']
1076-
else:
1077-
creator_str = \
1078-
f"matplotlib version {mpl.__version__}, http://matplotlib.org/"
1079-
10801034
# write to a temp file, we'll move it to outfile when done
1081-
10821035
with TemporaryDirectory() as tmpdir:
10831036
tmpfile = os.path.join(tmpdir, "tmp.ps")
1084-
# get source date from SOURCE_DATE_EPOCH, if set
1085-
# See https://reproducible-builds.org/specs/source-date-epoch/
1086-
source_date_epoch = os.getenv("SOURCE_DATE_EPOCH")
1087-
if source_date_epoch:
1088-
source_date = datetime.datetime.utcfromtimestamp(
1089-
int(source_date_epoch)).strftime("%a %b %d %H:%M:%S %Y")
1090-
else:
1091-
source_date = time.ctime()
10921037
pathlib.Path(tmpfile).write_text(
10931038
f"""\
10941039
%!PS-Adobe-3.0 EPSF-3.0
1095-
{f'''%%Title: {title}
1096-
''' if title else ""}\
1097-
%%Creator: {creator_str}
1098-
%%CreationDate: {source_date}
1040+
{dsc_comments}
10991041
%%BoundingBox: {bbox[0]} {bbox[1]} {bbox[2]} {bbox[3]}
11001042
%%EndComments
11011043
%%BeginProlog
@@ -1124,12 +1066,9 @@ def write(self, *args, **kwargs):
11241066
paper_width, paper_height = orientation.swap_if_landscape(
11251067
self.figure.get_size_inches())
11261068
else:
1127-
temp_papertype = _get_papertype(width, height)
11281069
if papertype == 'auto':
1129-
papertype = temp_papertype
1130-
paper_width, paper_height = papersize[temp_papertype]
1131-
else:
1132-
paper_width, paper_height = papersize[papertype]
1070+
papertype = _get_papertype(width, height)
1071+
paper_width, paper_height = papersize[papertype]
11331072

11341073
texmanager = ps_renderer.get_texmanager()
11351074
font_preamble = texmanager.get_font_preamble()

0 commit comments

Comments
 (0)