def print_svg(self, filename, *args, **kwargs): with cbook.open_file_cm(filename, "w", encoding="utf-8") as fh: filename = getattr(fh, 'name', '') if not isinstance(filename, six.string_types): filename = '' if cbook.file_requires_unicode(fh): detach = False else: if six.PY3: fh = io.TextIOWrapper(fh, 'utf-8') else: fh = codecs.getwriter('utf-8')(fh) detach = True result = self._print_svg(filename, fh, **kwargs) # Detach underlying stream from wrapper so that it remains open in # the caller. if detach: if six.PY3: fh.detach() else: fh.reset() fh.stream = io.BytesIO() return result
def print_pdf_tex(self, filename, *args, **kwargs): _dpi = 72 rcParams.update({"svg.fonttype": 'none'}) with cbook.open_file_cm(filename, "w", encoding="utf-8") as fh: filename = getattr(fh, 'name', '') if not isinstance(filename, str): filename = '' if cbook.file_requires_unicode(fh): detach = False else: fh = TextIOWrapper(fh, 'utf-8') detach = True _dpi = self._print_pdftex(filename, fh, **kwargs) # Detach underlying stream from wrapper so that it remains open in # the caller. if detach: fh.detach() subprocess.run([ "inkscape", "--export-filename={}.pdf".format('.'.join( filename.split('.')[:-1])), filename, "--export-dpi={}".format(int(_dpi)), "--export-latex" ])
def _for_fmt_output(cls, fmt, stream, width, height, dpi): if stream is not None and cbook.file_requires_unicode(stream): if fmt in [_StreamSurfaceType.PS, _StreamSurfaceType.EPS]: # PS is (typically) ASCII -- Language Reference, section 3.2. stream = _BytesWritingWrapper(stream, "ascii") elif fmt is _StreamSurfaceType.SVG: # cairo outputs SVG with encoding="UTF-8". stream = _BytesWritingWrapper(stream, "utf-8") # (No default encoding for pdf, which is a binary format.) args = fmt, stream, width, height, dpi cairo_debug_pdf = os.environ.get("CAIRO_DEBUG_PDF") if mpl.rcParams["pdf.compression"]: os.environ.setdefault("CAIRO_DEBUG_PDF", "1") try: obj = _mplcairo.GraphicsContextRendererCairo.__new__(cls, *args) _mplcairo.GraphicsContextRendererCairo.__init__(obj, *args) finally: if cairo_debug_pdf is None: os.environ.pop("CAIRO_DEBUG_PDF", None) else: os.environ["CAIRO_DEBUG_PDF"] = cairo_debug_pdf try: name = os.fsdecode(stream.name) except (AttributeError, TypeError): pass # In particular, stream.name is an int for TemporaryFile. else: obj._set_path(name) RendererBase.__init__(obj) return obj
def print_pgf(self, fname_or_fh, *args, **kwargs): """ Output pgf macros for drawing the figure so it can be included and rendered in latex documents. """ with cbook.open_file_cm(fname_or_fh, "w", encoding="utf-8") as file: if not cbook.file_requires_unicode(file): file = codecs.getwriter("utf-8")(file) self._print_pgf_to_fh(file, *args, **kwargs)
def print_pgf(self, fname_or_fh, *args, **kwargs): """ Output pgf commands for drawing the figure so it can be included and rendered in latex documents. """ if kwargs.get("dryrun", False): self._print_pgf_to_fh(None, *args, **kwargs) return with cbook.open_file_cm(fname_or_fh, "w", encoding="utf-8") as file: if not cbook.file_requires_unicode(file): file = codecs.getwriter("utf-8")(file) self._print_pgf_to_fh(file, *args, **kwargs)
def _move_path_to_path_or_stream(src, dst): """ Move the contents of file at *src* to path-or-filelike *dst*. If *dst* is a path, the metadata of *src* are *not* copied. """ if is_writable_file_like(dst): fh = (open(src, 'r', encoding='latin-1') if file_requires_unicode(dst) else open(src, 'rb')) with fh: shutil.copyfileobj(fh, dst) else: shutil.move(src, dst, copy_function=shutil.copyfile)
def _print_ps_impl(self, is_eps, path_or_stream, *, metadata=None, orientation="portrait", papertype=None, **kwargs): if papertype is None: papertype = mpl.rcParams["ps.papersize"] if orientation == "portrait": if papertype == "auto": width, height = self.figure.get_size_inches() papertype = backend_ps._get_papertype(height, width) elif orientation == "landscape": if papertype == "auto": width, height = self.figure.get_size_inches() papertype = backend_ps._get_papertype(width, height) else: raise ValueError(f"Invalid orientation ({orientation!r})") metadata = {**metadata} if metadata is not None else {} dsc_comments = metadata["_dsc_comments"] = [ f"%%Orientation: {orientation}" ] if "Title" in metadata: dsc_comments.append("%%Title: {}".format(metadata.pop("Title"))) if not is_eps: dsc_comments.append(f"%%DocumentPaperSizes: {papertype}") print_method = partial( self._print_method, GraphicsContextRendererCairo._for_eps_output if is_eps else GraphicsContextRendererCairo._for_ps_output) if mpl.rcParams["ps.usedistiller"]: with TemporaryDirectory() as tmp_dirname: tmp_name = Path(tmp_dirname, "tmp") print_method(tmp_name, metadata=metadata, **kwargs) # Assume we can get away without passing the bbox. { "ghostscript": backend_ps.gs_distill, "xpdf": backend_ps.xpdf_distill }[mpl.rcParams["ps.usedistiller"]](str(tmp_name), False, ptype=papertype) # If path_or_stream is *already* a text-mode stream then # tmp_name needs to be opened in text-mode too. with cbook.open_file_cm(path_or_stream, "wb") as stream, \ tmp_name.open("r" if cbook.file_requires_unicode(stream) else "rb") as tmp_file: shutil.copyfileobj(tmp_file, stream) else: print_method(path_or_stream, metadata=metadata, **kwargs)
def print_svg(self, filename, *args, **kwargs): """ Parameters ---------- filename : str or path-like or file-like Output target; if a string, a file will be opened for writing. metadata : Dict[str, Any], optional Metadata in the SVG file defined as key-value pairs of strings, datetimes, or lists of strings, e.g., ``{'Creator': 'My software', 'Contributor': ['Me', 'My Friend'], 'Title': 'Awesome'}``. The standard keys and their value types are: * *str*: ``'Coverage'``, ``'Description'``, ``'Format'``, ``'Identifier'``, ``'Language'``, ``'Relation'``, ``'Source'``, ``'Title'``, and ``'Type'``. * *str* or *list of str*: ``'Contributor'``, ``'Creator'``, ``'Keywords'``, ``'Publisher'``, and ``'Rights'``. * *str*, *date*, *datetime*, or *tuple* of same: ``'Date'``. If a non-*str*, then it will be formatted as ISO 8601. Values have been predefined for ``'Creator'``, ``'Date'``, ``'Format'``, and ``'Type'``. They can be removed by setting them to `None`. Information is encoded as `Dublin Core Metadata`__. .. _DC: https://www.dublincore.org/specifications/dublin-core/ __ DC_ """ with cbook.open_file_cm(filename, "w", encoding="utf-8") as fh: filename = getattr(fh, 'name', '') if not isinstance(filename, str): filename = '' if cbook.file_requires_unicode(fh): detach = False else: fh = TextIOWrapper(fh, 'utf-8') detach = True self._print_svg(filename, fh, **kwargs) # Detach underlying stream from wrapper so that it remains open in # the caller. if detach: fh.detach()
def print_svg(self, filename, *args, **kwargs): with cbook.open_file_cm(filename, "w", encoding="utf-8") as fh: filename = getattr(fh, 'name', '') if not isinstance(filename, str): filename = '' if cbook.file_requires_unicode(fh): detach = False else: fh = TextIOWrapper(fh, 'utf-8') detach = True self._print_svg(filename, fh, **kwargs) # Detach underlying stream from wrapper so that it remains open in # the caller. if detach: fh.detach()
def _for_fmt_output(cls, fmt, stream, width, height, dpi): if cbook.file_requires_unicode(stream): if fmt in [_StreamSurfaceType.PS, _StreamSurfaceType.EPS]: # PS is (typically) ASCII -- Language Reference, section 3.2. stream = _BytesWritingWrapper(stream, "ascii") elif fmt is _StreamSurfaceType.SVG: # cairo outputs SVG with encoding="UTF-8". stream = _BytesWritingWrapper(stream, "utf-8") # (No default encoding for pdf, which is a binary format.) args = fmt, stream, width, height, dpi obj = _mplcairo.GraphicsContextRendererCairo.__new__(cls, *args) _mplcairo.GraphicsContextRendererCairo.__init__(obj, *args) try: name = os.fsdecode(stream.name) except (AttributeError, TypeError): pass # In particular, stream.name is an int for TemporaryFile. else: obj._set_path(name) RendererBase.__init__(obj) return obj
def _print_figure( self, outfile, format, *, dpi, dsc_comments, orientation, papertype, dryrun=False, bbox_inches_restore=None): """ Render the figure to a filesystem path or a file-like object. Parameters are as for `.print_figure`, except that *dsc_comments* is a all string containing Document Structuring Convention comments, generated from the *metadata* parameter to `.print_figure`. """ is_eps = format == 'eps' if isinstance(outfile, (str, os.PathLike)): outfile = os.fspath(outfile) passed_in_file_object = False elif is_writable_file_like(outfile): passed_in_file_object = True else: raise ValueError("outfile must be a path or a file-like object") # find the appropriate papertype width, height = self.figure.get_size_inches() if papertype == 'auto': papertype = _get_papertype( *orientation.swap_if_landscape((width, height))) paper_width, paper_height = orientation.swap_if_landscape( papersize[papertype]) if mpl.rcParams['ps.usedistiller']: # distillers improperly clip eps files if pagesize is too small if width > paper_width or height > paper_height: papertype = _get_papertype( *orientation.swap_if_landscape(width, height)) paper_width, paper_height = orientation.swap_if_landscape( papersize[papertype]) # center the figure on the paper xo = 72 * 0.5 * (paper_width - width) yo = 72 * 0.5 * (paper_height - height) llx = xo lly = yo urx = llx + self.figure.bbox.width ury = lly + self.figure.bbox.height rotation = 0 if orientation is _Orientation.landscape: llx, lly, urx, ury = lly, llx, ury, urx xo, yo = 72 * paper_height - yo, xo rotation = 90 bbox = (llx, lly, urx, ury) if dryrun: class NullWriter: def write(self, *args, **kwargs): pass self._pswriter = NullWriter() else: self._pswriter = StringIO() # mixed mode rendering ps_renderer = RendererPS(width, height, self._pswriter, imagedpi=dpi) renderer = MixedModeRenderer( self.figure, width, height, dpi, ps_renderer, bbox_inches_restore=bbox_inches_restore) self.figure.draw(renderer) if dryrun: # return immediately if dryrun (tightbbox=True) return def print_figure_impl(fh): # write the PostScript headers if is_eps: print("%!PS-Adobe-3.0 EPSF-3.0", file=fh) else: print(f"%!PS-Adobe-3.0\n" f"%%DocumentPaperSizes: {papertype}\n" f"%%Pages: 1\n", end="", file=fh) print(f"{dsc_comments}\n" f"%%Orientation: {orientation.name}\n" f"%%BoundingBox: {bbox[0]} {bbox[1]} {bbox[2]} {bbox[3]}\n" f"%%EndComments\n", end="", file=fh) Ndict = len(psDefs) print("%%BeginProlog", file=fh) if not mpl.rcParams['ps.useafm']: Ndict += len(ps_renderer._character_tracker.used) print("/mpldict %d dict def" % Ndict, file=fh) print("mpldict begin", file=fh) print("\n".join(psDefs), file=fh) if not mpl.rcParams['ps.useafm']: for font_path, chars \ in ps_renderer._character_tracker.used.items(): if not chars: continue font = get_font(font_path) glyph_ids = [font.get_char_index(c) for c in chars] fonttype = mpl.rcParams['ps.fonttype'] # Can't use more than 255 chars from a single Type 3 font. if len(glyph_ids) > 255: fonttype = 42 # The ttf to ps (subsetting) support doesn't work for # OpenType fonts that are Postscript inside (like the STIX # fonts). This will simply turn that off to avoid errors. if is_opentype_cff_font(font_path): raise RuntimeError( "OpenType CFF fonts can not be saved using " "the internal Postscript backend at this " "time; consider using the Cairo backend") fh.flush() try: convert_ttf_to_ps(os.fsencode(font_path), fh, fonttype, glyph_ids) except RuntimeError: _log.warning("The PostScript backend does not " "currently support the selected font.") raise print("end", file=fh) print("%%EndProlog", file=fh) if not is_eps: print("%%Page: 1 1", file=fh) print("mpldict begin", file=fh) print("%s translate" % _nums_to_str(xo, yo), file=fh) if rotation: print("%d rotate" % rotation, file=fh) print("%s clipbox" % _nums_to_str(width*72, height*72, 0, 0), file=fh) # write the figure print(self._pswriter.getvalue(), file=fh) # write the trailer print("end", file=fh) print("showpage", file=fh) if not is_eps: print("%%EOF", file=fh) fh.flush() if mpl.rcParams['ps.usedistiller']: # We are going to use an external program to process the output. # Write to a temporary file. with TemporaryDirectory() as tmpdir: tmpfile = os.path.join(tmpdir, "tmp.ps") with open(tmpfile, 'w', encoding='latin-1') as fh: print_figure_impl(fh) if mpl.rcParams['ps.usedistiller'] == 'ghostscript': _try_distill(gs_distill, tmpfile, is_eps, ptype=papertype, bbox=bbox) elif mpl.rcParams['ps.usedistiller'] == 'xpdf': _try_distill(xpdf_distill, tmpfile, is_eps, ptype=papertype, bbox=bbox) _move_path_to_path_or_stream(tmpfile, outfile) else: # Write directly to outfile. if passed_in_file_object: requires_unicode = file_requires_unicode(outfile) if not requires_unicode: fh = TextIOWrapper(outfile, encoding="latin-1") # Prevent the TextIOWrapper from closing the underlying # file. fh.close = lambda: None else: fh = outfile print_figure_impl(fh) else: with open(outfile, 'w', encoding='latin-1') as fh: print_figure_impl(fh)
def _print_figure(self, fmt, outfile, *, dpi, dsc_comments, orientation, papertype, bbox_inches_restore=None): """ Render the figure to a filesystem path or a file-like object. Parameters are as for `.print_figure`, except that *dsc_comments* is a all string containing Document Structuring Convention comments, generated from the *metadata* parameter to `.print_figure`. """ is_eps = fmt == 'eps' if not (isinstance(outfile, (str, os.PathLike)) or is_writable_file_like(outfile)): raise ValueError("outfile must be a path or a file-like object") # find the appropriate papertype width, height = self.figure.get_size_inches() if papertype == 'auto': papertype = _get_papertype( *orientation.swap_if_landscape((width, height))) paper_width, paper_height = orientation.swap_if_landscape( papersize[papertype]) if mpl.rcParams['ps.usedistiller']: # distillers improperly clip eps files if pagesize is too small if width > paper_width or height > paper_height: papertype = _get_papertype( *orientation.swap_if_landscape((width, height))) paper_width, paper_height = orientation.swap_if_landscape( papersize[papertype]) # center the figure on the paper xo = 72 * 0.5 * (paper_width - width) yo = 72 * 0.5 * (paper_height - height) llx = xo lly = yo urx = llx + self.figure.bbox.width ury = lly + self.figure.bbox.height rotation = 0 if orientation is _Orientation.landscape: llx, lly, urx, ury = lly, llx, ury, urx xo, yo = 72 * paper_height - yo, xo rotation = 90 bbox = (llx, lly, urx, ury) self._pswriter = StringIO() # mixed mode rendering ps_renderer = RendererPS(width, height, self._pswriter, imagedpi=dpi) renderer = MixedModeRenderer(self.figure, width, height, dpi, ps_renderer, bbox_inches_restore=bbox_inches_restore) self.figure.draw(renderer) def print_figure_impl(fh): # write the PostScript headers if is_eps: print("%!PS-Adobe-3.0 EPSF-3.0", file=fh) else: print( f"%!PS-Adobe-3.0\n" f"%%DocumentPaperSizes: {papertype}\n" f"%%Pages: 1\n", end="", file=fh) print( f"{dsc_comments}\n" f"%%Orientation: {orientation.name}\n" f"{get_bbox_header(bbox)[0]}\n" f"%%EndComments\n", end="", file=fh) Ndict = len(psDefs) print("%%BeginProlog", file=fh) if not mpl.rcParams['ps.useafm']: Ndict += len(ps_renderer._character_tracker.used) print("/mpldict %d dict def" % Ndict, file=fh) print("mpldict begin", file=fh) print("\n".join(psDefs), file=fh) if not mpl.rcParams['ps.useafm']: for font_path, chars \ in ps_renderer._character_tracker.used.items(): if not chars: continue fonttype = mpl.rcParams['ps.fonttype'] # Can't use more than 255 chars from a single Type 3 font. if len(chars) > 255: fonttype = 42 fh.flush() if fonttype == 3: fh.write(_font_to_ps_type3(font_path, chars)) else: # Type 42 only. _font_to_ps_type42(font_path, chars, fh) print("end", file=fh) print("%%EndProlog", file=fh) if not is_eps: print("%%Page: 1 1", file=fh) print("mpldict begin", file=fh) print("%s translate" % _nums_to_str(xo, yo), file=fh) if rotation: print("%d rotate" % rotation, file=fh) print("%s clipbox" % _nums_to_str(width * 72, height * 72, 0, 0), file=fh) # write the figure print(self._pswriter.getvalue(), file=fh) # write the trailer print("end", file=fh) print("showpage", file=fh) if not is_eps: print("%%EOF", file=fh) fh.flush() if mpl.rcParams['ps.usedistiller']: # We are going to use an external program to process the output. # Write to a temporary file. with TemporaryDirectory() as tmpdir: tmpfile = os.path.join(tmpdir, "tmp.ps") with open(tmpfile, 'w', encoding='latin-1') as fh: print_figure_impl(fh) if mpl.rcParams['ps.usedistiller'] == 'ghostscript': _try_distill(gs_distill, tmpfile, is_eps, ptype=papertype, bbox=bbox) elif mpl.rcParams['ps.usedistiller'] == 'xpdf': _try_distill(xpdf_distill, tmpfile, is_eps, ptype=papertype, bbox=bbox) _move_path_to_path_or_stream(tmpfile, outfile) else: # Write directly to outfile. with cbook.open_file_cm(outfile, "w", encoding="latin-1") as file: if not file_requires_unicode(file): file = codecs.getwriter("latin-1")(file) print_figure_impl(file)
def _print_figure(self, outfile, format, dpi, facecolor, edgecolor, orientation, papertype, *, metadata=None, dryrun=False, bbox_inches_restore=None, **kwargs): """ Render the figure to hardcopy. Set the figure patch face and edge colors. This is useful because some of the GUIs have a gray figure face color background and you'll probably want to override this on hardcopy If outfile is a string, it is interpreted as a file name. If the extension matches .ep* write encapsulated postscript, otherwise write a stand-alone PostScript file. If outfile is a file object, a stand-alone PostScript file is written into this file object. metadata must be a dictionary. Currently, only the value for the key 'Creator' is used. """ is_eps = format == 'eps' if isinstance(outfile, (str, os.PathLike)): outfile = title = os.fspath(outfile) title = title.encode("ascii", "replace").decode("ascii") passed_in_file_object = False elif is_writable_file_like(outfile): title = None passed_in_file_object = True else: raise ValueError("outfile must be a path or a file-like object") # find the appropriate papertype width, height = self.figure.get_size_inches() if papertype == 'auto': papertype = _get_papertype( *orientation.swap_if_landscape((width, height))) paper_width, paper_height = orientation.swap_if_landscape( papersize[papertype]) if mpl.rcParams['ps.usedistiller']: # distillers improperly clip eps files if pagesize is too small if width > paper_width or height > paper_height: papertype = _get_papertype( *orientation.swap_if_landscape(width, height)) paper_width, paper_height = orientation.swap_if_landscape( papersize[papertype]) # center the figure on the paper xo = 72 * 0.5 * (paper_width - width) yo = 72 * 0.5 * (paper_height - height) l, b, w, h = self.figure.bbox.bounds llx = xo lly = yo urx = llx + w ury = lly + h rotation = 0 if orientation is _Orientation.landscape: llx, lly, urx, ury = lly, llx, ury, urx xo, yo = 72 * paper_height - yo, xo rotation = 90 bbox = (llx, lly, urx, ury) # generate PostScript code for the figure and store it in a string origfacecolor = self.figure.get_facecolor() origedgecolor = self.figure.get_edgecolor() self.figure.set_facecolor(facecolor) self.figure.set_edgecolor(edgecolor) if dryrun: class NullWriter: def write(self, *args, **kwargs): pass self._pswriter = NullWriter() else: self._pswriter = StringIO() # mixed mode rendering ps_renderer = RendererPS(width, height, self._pswriter, imagedpi=dpi) renderer = MixedModeRenderer(self.figure, width, height, dpi, ps_renderer, bbox_inches_restore=bbox_inches_restore) self.figure.draw(renderer) if dryrun: # return immediately if dryrun (tightbbox=True) return self.figure.set_facecolor(origfacecolor) self.figure.set_edgecolor(origedgecolor) # check for custom metadata if metadata is not None and 'Creator' in metadata: creator_str = metadata['Creator'] else: creator_str = \ f"matplotlib version {mpl.__version__}, http://matplotlib.org/" def print_figure_impl(fh): # write the PostScript headers if is_eps: print("%!PS-Adobe-3.0 EPSF-3.0", file=fh) else: print( f"%!PS-Adobe-3.0\n" f"%%DocumentPaperSizes: {papertype}\n" f"%%Pages: 1\n", end="", file=fh) if title: print("%%Title: " + title, file=fh) # get source date from SOURCE_DATE_EPOCH, if set # See https://reproducible-builds.org/specs/source-date-epoch/ source_date_epoch = os.getenv("SOURCE_DATE_EPOCH") if source_date_epoch: source_date = datetime.datetime.utcfromtimestamp( int(source_date_epoch)).strftime("%a %b %d %H:%M:%S %Y") else: source_date = time.ctime() print( f"%%Creator: {creator_str}\n" f"%%CreationDate: {source_date}\n" f"%%Orientation: {orientation.name}\n" f"%%BoundingBox: {bbox[0]} {bbox[1]} {bbox[2]} {bbox[3]}\n" f"%%EndComments\n", end="", file=fh) Ndict = len(psDefs) print("%%BeginProlog", file=fh) if not mpl.rcParams['ps.useafm']: Ndict += len(ps_renderer._character_tracker.used) print("/mpldict %d dict def" % Ndict, file=fh) print("mpldict begin", file=fh) for d in psDefs: d = d.strip() for l in d.split('\n'): print(l.strip(), file=fh) if not mpl.rcParams['ps.useafm']: for font_path, chars \ in ps_renderer._character_tracker.used.items(): if not chars: continue font = get_font(font_path) glyph_ids = [font.get_char_index(c) for c in chars] fonttype = mpl.rcParams['ps.fonttype'] # Can't use more than 255 chars from a single Type 3 font. if len(glyph_ids) > 255: fonttype = 42 # The ttf to ps (subsetting) support doesn't work for # OpenType fonts that are Postscript inside (like the STIX # fonts). This will simply turn that off to avoid errors. if is_opentype_cff_font(font_path): raise RuntimeError( "OpenType CFF fonts can not be saved using " "the internal Postscript backend at this " "time; consider using the Cairo backend") fh.flush() try: convert_ttf_to_ps(os.fsencode(font_path), fh, fonttype, glyph_ids) except RuntimeError: _log.warning("The PostScript backend does not " "currently support the selected font.") raise print("end", file=fh) print("%%EndProlog", file=fh) if not is_eps: print("%%Page: 1 1", file=fh) print("mpldict begin", file=fh) print("%s translate" % _nums_to_str(xo, yo), file=fh) if rotation: print("%d rotate" % rotation, file=fh) print("%s clipbox" % _nums_to_str(width * 72, height * 72, 0, 0), file=fh) # write the figure content = self._pswriter.getvalue() if not isinstance(content, str): content = content.decode('ascii') print(content, file=fh) # write the trailer print("end", file=fh) print("showpage", file=fh) if not is_eps: print("%%EOF", file=fh) fh.flush() if mpl.rcParams['ps.usedistiller']: # We are going to use an external program to process the output. # Write to a temporary file. with TemporaryDirectory() as tmpdir: tmpfile = os.path.join(tmpdir, "tmp.ps") with open(tmpfile, 'w', encoding='latin-1') as fh: print_figure_impl(fh) if mpl.rcParams['ps.usedistiller'] == 'ghostscript': gs_distill(tmpfile, is_eps, ptype=papertype, bbox=bbox) elif mpl.rcParams['ps.usedistiller'] == 'xpdf': xpdf_distill(tmpfile, is_eps, ptype=papertype, bbox=bbox) _move_path_to_path_or_stream(tmpfile, outfile) else: # Write directly to outfile. if passed_in_file_object: requires_unicode = file_requires_unicode(outfile) if not requires_unicode: fh = TextIOWrapper(outfile, encoding="latin-1") # Prevent the TextIOWrapper from closing the underlying # file. fh.close = lambda: None else: fh = outfile print_figure_impl(fh) else: with open(outfile, 'w', encoding='latin-1') as fh: print_figure_impl(fh)