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 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()
def _print_figure(self, outfile, format, dpi=72, facecolor='w', edgecolor='w', orientation='portrait', isLandscape=False, papertype=None): """ 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. """ isEPSF = format == 'eps' passed_in_file_object = False if is_string_like(outfile): title = outfile tmpfile = os.path.join(gettempdir(), md5(outfile).hexdigest()) elif is_writable_file_like(outfile): title = None tmpfile = os.path.join(gettempdir(), md5(str(hash(outfile))).hexdigest()) passed_in_file_object = True else: raise ValueError("outfile must be a path or a file-like object") fh = file(tmpfile, 'w') # find the appropriate papertype width, height = self.figure.get_size_inches() if papertype == 'auto': if isLandscape: papertype = _get_papertype(height, width) else: papertype = _get_papertype(width, height) if isLandscape: paperHeight, paperWidth = papersize[papertype] else: paperWidth, paperHeight = papersize[papertype] if rcParams['ps.usedistiller'] and not papertype == 'auto': # distillers will improperly clip eps files if the pagesize is # too small if width>paperWidth or height>paperHeight: if isLandscape: papertype = _get_papertype(height, width) paperHeight, paperWidth = papersize[papertype] else: papertype = _get_papertype(width, height) paperWidth, paperHeight = papersize[papertype] # center the figure on the paper xo = 72*0.5*(paperWidth - width) yo = 72*0.5*(paperHeight - height) l, b, w, h = self.figure.bbox.bounds llx = xo lly = yo urx = llx + w ury = lly + h rotation = 0 if isLandscape: llx, lly, urx, ury = lly, llx, ury, urx xo, yo = 72*paperHeight - 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) self._pswriter = StringIO() renderer = RendererPS(width, height, self._pswriter, imagedpi=dpi) self.figure.draw(renderer) self.figure.set_facecolor(origfacecolor) self.figure.set_edgecolor(origedgecolor) # write the PostScript headers if isEPSF: print >>fh, "%!PS-Adobe-3.0 EPSF-3.0" else: print >>fh, "%!PS-Adobe-3.0" if title: print >>fh, "%%Title: "+title print >>fh, ("%%Creator: matplotlib version " +__version__+", http://matplotlib.sourceforge.net/") print >>fh, "%%CreationDate: "+time.ctime(time.time()) print >>fh, "%%Orientation: " + orientation if not isEPSF: print >>fh, "%%DocumentPaperSizes: "+papertype print >>fh, "%%%%BoundingBox: %d %d %d %d" % bbox if not isEPSF: print >>fh, "%%Pages: 1" print >>fh, "%%EndComments" Ndict = len(psDefs) print >>fh, "%%BeginProlog" if not rcParams['ps.useafm']: Ndict += len(renderer.used_characters) print >>fh, "/mpldict %d dict def"%Ndict print >>fh, "mpldict begin" for d in psDefs: d=d.strip() for l in d.split('\n'): print >>fh, l.strip() if not rcParams['ps.useafm']: for font_filename, chars in renderer.used_characters.values(): if len(chars): font = FT2Font(font_filename) cmap = font.get_charmap() glyph_ids = [] for c in chars: gind = cmap.get(c) or 0 glyph_ids.append(gind) # 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_filename): raise RuntimeError("OpenType CFF fonts can not be saved using the internal Postscript backend at this time.\nConsider using the Cairo backend.") else: fonttype = rcParams['ps.fonttype'] convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids) print >>fh, "end" print >>fh, "%%EndProlog" if not isEPSF: print >>fh, "%%Page: 1 1" print >>fh, "mpldict begin" #print >>fh, "gsave" print >>fh, "%s translate"%_nums_to_str(xo, yo) if rotation: print >>fh, "%d rotate"%rotation print >>fh, "%s clipbox"%_nums_to_str(width*72, height*72, 0, 0) # write the figure print >>fh, self._pswriter.getvalue() # write the trailer #print >>fh, "grestore" print >>fh, "end" print >>fh, "showpage" if not isEPSF: print >>fh, "%%EOF" fh.close() if rcParams['ps.usedistiller'] == 'ghostscript': gs_distill(tmpfile, isEPSF, ptype=papertype, bbox=bbox) elif rcParams['ps.usedistiller'] == 'xpdf': xpdf_distill(tmpfile, isEPSF, ptype=papertype, bbox=bbox) if passed_in_file_object: fh = file(tmpfile) print >>outfile, fh.read() else: shutil.move(tmpfile, outfile)
def _print_figure(self, outfile, format, dpi=72, facecolor='w', edgecolor='w', orientation='portrait', isLandscape=False, papertype=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. """ isEPSF = format == 'eps' passed_in_file_object = False fd, tmpfile = mkstemp() if is_string_like(outfile): title = outfile 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") os.close(fd) fh = file(tmpfile, 'w') width, height = self.figure.get_size_inches() if papertype == 'auto': if isLandscape: papertype = _get_papertype(height, width) else: papertype = _get_papertype(width, height) if isLandscape: paperHeight, paperWidth = papersize[papertype] else: paperWidth, paperHeight = papersize[papertype] if rcParams['ps.usedistiller'] and not papertype == 'auto': if width>paperWidth or height>paperHeight: if isLandscape: papertype = _get_papertype(height, width) paperHeight, paperWidth = papersize[papertype] else: papertype = _get_papertype(width, height) paperWidth, paperHeight = papersize[papertype] xo = 72*0.5*(paperWidth - width) yo = 72*0.5*(paperHeight - height) l, b, w, h = self.figure.bbox.bounds llx = xo lly = yo urx = llx + w ury = lly + h rotation = 0 if isLandscape: llx, lly, urx, ury = lly, llx, ury, urx xo, yo = 72*paperHeight - yo, xo rotation = 90 bbox = (llx, lly, urx, ury) origfacecolor = self.figure.get_facecolor() origedgecolor = self.figure.get_edgecolor() self.figure.set_facecolor(facecolor) self.figure.set_edgecolor(edgecolor) dryrun = kwargs.get("dryrun", False) if dryrun: class NullWriter(object): def write(self, *kl, **kwargs): pass self._pswriter = NullWriter() else: self._pswriter = StringIO() _bbox_inches_restore = kwargs.pop("bbox_inches_restore", None) 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) if isEPSF: print >>fh, "%!PS-Adobe-3.0 EPSF-3.0" else: print >>fh, "%!PS-Adobe-3.0" if title: print >>fh, "%%Title: "+title print >>fh, ("%%Creator: matplotlib version " +__version__+", http://matplotlib.sourceforge.net/") print >>fh, "%%CreationDate: "+time.ctime(time.time()) print >>fh, "%%Orientation: " + orientation if not isEPSF: print >>fh, "%%DocumentPaperSizes: "+papertype print >>fh, "%%%%BoundingBox: %d %d %d %d" % bbox if not isEPSF: print >>fh, "%%Pages: 1" print >>fh, "%%EndComments" Ndict = len(psDefs) print >>fh, "%%BeginProlog" if not rcParams['ps.useafm']: Ndict += len(ps_renderer.used_characters) print >>fh, "/mpldict %d dict def"%Ndict print >>fh, "mpldict begin" for d in psDefs: d=d.strip() for l in d.split('\n'): print >>fh, l.strip() if not rcParams['ps.useafm']: for font_filename, chars in ps_renderer.used_characters.values(): if len(chars): font = FT2Font(font_filename) cmap = font.get_charmap() glyph_ids = [] for c in chars: gind = cmap.get(c) or 0 glyph_ids.append(gind) if is_opentype_cff_font(font_filename): raise RuntimeError("OpenType CFF fonts can not be saved using the internal Postscript backend at this time.\nConsider using the Cairo backend.") else: fonttype = rcParams['ps.fonttype'] convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids) print >>fh, "end" print >>fh, "%%EndProlog" if not isEPSF: print >>fh, "%%Page: 1 1" print >>fh, "mpldict begin" print >>fh, "%s translate"%_nums_to_str(xo, yo) if rotation: print >>fh, "%d rotate"%rotation print >>fh, "%s clipbox"%_nums_to_str(width*72, height*72, 0, 0) print >>fh, self._pswriter.getvalue() print >>fh, "end" print >>fh, "showpage" if not isEPSF: print >>fh, "%%EOF" fh.close() if rcParams['ps.usedistiller'] == 'ghostscript': gs_distill(tmpfile, isEPSF, ptype=papertype, bbox=bbox) elif rcParams['ps.usedistiller'] == 'xpdf': xpdf_distill(tmpfile, isEPSF, ptype=papertype, bbox=bbox) if passed_in_file_object: fh = file(tmpfile) print >>outfile, fh.read() else: shutil.move(tmpfile, outfile)
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()
def _print_figure(self, outfile, format, dpi=72, facecolor='w', edgecolor='w', orientation='portrait', isLandscape=False, papertype=None): """ 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. """ isEPSF = format == 'eps' passed_in_file_object = False if is_string_like(outfile): title = outfile tmpfile = os.path.join(gettempdir(), md5(outfile).hexdigest()) elif is_writable_file_like(outfile): title = None tmpfile = os.path.join(gettempdir(), md5(str(hash(outfile))).hexdigest()) passed_in_file_object = True else: raise ValueError("outfile must be a path or a file-like object") fh = file(tmpfile, 'w') # find the appropriate papertype width, height = self.figure.get_size_inches() if papertype == 'auto': if isLandscape: papertype = _get_papertype(height, width) else: papertype = _get_papertype(width, height) if isLandscape: paperHeight, paperWidth = papersize[papertype] else: paperWidth, paperHeight = papersize[papertype] if rcParams['ps.usedistiller'] and not papertype == 'auto': # distillers will improperly clip eps files if the pagesize is # too small if width > paperWidth or height > paperHeight: if isLandscape: papertype = _get_papertype(height, width) paperHeight, paperWidth = papersize[papertype] else: papertype = _get_papertype(width, height) paperWidth, paperHeight = papersize[papertype] # center the figure on the paper xo = 72 * 0.5 * (paperWidth - width) yo = 72 * 0.5 * (paperHeight - height) l, b, w, h = self.figure.bbox.bounds llx = xo lly = yo urx = llx + w ury = lly + h rotation = 0 if isLandscape: llx, lly, urx, ury = lly, llx, ury, urx xo, yo = 72 * paperHeight - 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) self._pswriter = StringIO() renderer = RendererPS(width, height, self._pswriter, imagedpi=dpi) self.figure.draw(renderer) self.figure.set_facecolor(origfacecolor) self.figure.set_edgecolor(origedgecolor) # write the PostScript headers if isEPSF: print >> fh, "%!PS-Adobe-3.0 EPSF-3.0" else: print >> fh, "%!PS-Adobe-3.0" if title: print >> fh, "%%Title: " + title print >> fh, ("%%Creator: matplotlib version " + __version__ + ", http://matplotlib.sourceforge.net/") print >> fh, "%%CreationDate: " + time.ctime(time.time()) print >> fh, "%%Orientation: " + orientation if not isEPSF: print >> fh, "%%DocumentPaperSizes: " + papertype print >> fh, "%%%%BoundingBox: %d %d %d %d" % bbox if not isEPSF: print >> fh, "%%Pages: 1" print >> fh, "%%EndComments" Ndict = len(psDefs) print >> fh, "%%BeginProlog" if not rcParams['ps.useafm']: Ndict += len(renderer.used_characters) print >> fh, "/mpldict %d dict def" % Ndict print >> fh, "mpldict begin" for d in psDefs: d = d.strip() for l in d.split('\n'): print >> fh, l.strip() if not rcParams['ps.useafm']: for font_filename, chars in renderer.used_characters.values(): if len(chars): font = FT2Font(font_filename) cmap = font.get_charmap() glyph_ids = [] for c in chars: gind = cmap.get(c) or 0 glyph_ids.append(gind) # 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_filename): raise RuntimeError( "OpenType CFF fonts can not be saved using the internal Postscript backend at this time.\nConsider using the Cairo backend." ) else: fonttype = rcParams['ps.fonttype'] convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids) print >> fh, "end" print >> fh, "%%EndProlog" if not isEPSF: print >> fh, "%%Page: 1 1" print >> fh, "mpldict begin" #print >>fh, "gsave" print >> fh, "%s translate" % _nums_to_str(xo, yo) if rotation: print >> fh, "%d rotate" % rotation print >> fh, "%s clipbox" % _nums_to_str(width * 72, height * 72, 0, 0) # write the figure print >> fh, self._pswriter.getvalue() # write the trailer #print >>fh, "grestore" print >> fh, "end" print >> fh, "showpage" if not isEPSF: print >> fh, "%%EOF" fh.close() if rcParams['ps.usedistiller'] == 'ghostscript': gs_distill(tmpfile, isEPSF, ptype=papertype, bbox=bbox) elif rcParams['ps.usedistiller'] == 'xpdf': xpdf_distill(tmpfile, isEPSF, ptype=papertype, bbox=bbox) if passed_in_file_object: fh = file(tmpfile) print >> outfile, fh.read() else: shutil.move(tmpfile, outfile)