diff --git a/lib/matplotlib/backends/backend_mixed.py b/lib/matplotlib/backends/backend_mixed.py index 4b1a8b95b08a..511304855514 100644 --- a/lib/matplotlib/backends/backend_mixed.py +++ b/lib/matplotlib/backends/backend_mixed.py @@ -48,6 +48,7 @@ def __init__(self, figure, width, height, dpi, vector_renderer, # the figure dpi before and after the rasterization. Although # this looks ugly, I couldn't find a better solution. -JJL self.figure=figure + self._figdpi = figure.get_dpi() self._bbox_inches_restore = bbox_inches_restore @@ -121,16 +122,19 @@ def stop_rasterizing(self): image.is_grayscale = False image.flipud_out() gc = self._renderer.new_gc() + # TODO: If the mixedmode resolution differs from the figure's + # dpi, the image must be scaled (dpi->_figdpi). Not all + # backends support this. self._renderer.draw_image( gc, - float(l)/self.dpi*72., - (float(height) - b - h)/self.dpi*72., + float(l) / self.dpi * self._figdpi, + (float(height)-b-h) / self.dpi * self._figdpi, image) self._raster_renderer = None self._rasterizing = False - # restore the figure dpi. - self.figure.set_dpi(72) + # restore the figure dpi. + self.figure.set_dpi(self._figdpi) if self._bbox_inches_restore: # when tight bbox is used r = process_figure_for_rasterizing(self.figure, diff --git a/lib/matplotlib/backends/backend_pgf.py b/lib/matplotlib/backends/backend_pgf.py index c9015d3a5237..63c48082a85f 100644 --- a/lib/matplotlib/backends/backend_pgf.py +++ b/lib/matplotlib/backends/backend_pgf.py @@ -13,6 +13,7 @@ import matplotlib as mpl from matplotlib.backend_bases import RendererBase, GraphicsContextBase,\ FigureManagerBase, FigureCanvasBase +from matplotlib.backends.backend_mixed import MixedModeRenderer from matplotlib.figure import Figure from matplotlib.text import Text from matplotlib.path import Path @@ -738,7 +739,7 @@ def __init__(self, *args): def get_default_filetype(self): return 'pdf' - def _print_pgf_to_fh(self, fh): + def _print_pgf_to_fh(self, fh, *args, **kwargs): header_text = r"""%% Creator: Matplotlib, PGF backend %% %% To include the figure in your LaTeX document, write @@ -767,6 +768,7 @@ def _print_pgf_to_fh(self, fh): # get figure size in inch w, h = self.figure.get_figwidth(), self.figure.get_figheight() + dpi = self.figure.get_dpi() # create pgfpicture environment and write the pgf code fh.write(header_text) @@ -777,7 +779,10 @@ def _print_pgf_to_fh(self, fh): writeln(fh, r"\begin{pgfpicture}") writeln(fh, r"\pgfpathrectangle{\pgfpointorigin}{\pgfqpoint{%fin}{%fin}}" % (w, h)) writeln(fh, r"\pgfusepath{use as bounding box}") - renderer = RendererPgf(self.figure, fh) + _bbox_inches_restore = kwargs.pop("bbox_inches_restore", None) + renderer = MixedModeRenderer(self.figure, w, h, dpi, + RendererPgf(self.figure, fh), + bbox_inches_restore=_bbox_inches_restore) self.figure.draw(renderer) # end the pgfpicture environment @@ -796,14 +801,14 @@ def print_pgf(self, fname_or_fh, *args, **kwargs): # figure out where the pgf is to be written to if is_string_like(fname_or_fh): with codecs.open(fname_or_fh, "w", encoding="utf-8") as fh: - self._print_pgf_to_fh(fh) + self._print_pgf_to_fh(fh, *args, **kwargs) elif is_writable_file_like(fname_or_fh): raise ValueError("saving pgf to a stream is not supported, " + "consider using the pdf option of the pgf-backend") else: raise ValueError("filename must be a path") - def _print_pdf_to_fh(self, fh): + def _print_pdf_to_fh(self, fh, *args, **kwargs): w, h = self.figure.get_figwidth(), self.figure.get_figheight() try: @@ -814,7 +819,7 @@ def _print_pdf_to_fh(self, fh): fname_pdf = os.path.join(tmpdir, "figure.pdf") # print figure to pgf and compile it with latex - self.print_pgf(fname_pgf) + self.print_pgf(fname_pgf, *args, **kwargs) latex_preamble = get_preamble() latex_fontspec = get_fontspec() @@ -856,13 +861,13 @@ def print_pdf(self, fname_or_fh, *args, **kwargs): # figure out where the pdf is to be written to if is_string_like(fname_or_fh): with open(fname_or_fh, "wb") as fh: - self._print_pdf_to_fh(fh) + self._print_pdf_to_fh(fh, *args, **kwargs) elif is_writable_file_like(fname_or_fh): - self._print_pdf_to_fh(fname_or_fh) + self._print_pdf_to_fh(fname_or_fh, *args, **kwargs) else: raise ValueError("filename must be a path or a file-like object") - def _print_png_to_fh(self, fh): + def _print_png_to_fh(self, fh, *args, **kwargs): converter = make_pdf_to_png_converter() try: @@ -871,7 +876,7 @@ def _print_png_to_fh(self, fh): fname_pdf = os.path.join(tmpdir, "figure.pdf") fname_png = os.path.join(tmpdir, "figure.png") # create pdf and try to convert it to png - self.print_pdf(fname_pdf) + self.print_pdf(fname_pdf, *args, **kwargs) converter(fname_pdf, fname_png, dpi=self.figure.dpi) # copy file contents to target with open(fname_png, "rb") as fh_src: @@ -888,9 +893,9 @@ def print_png(self, fname_or_fh, *args, **kwargs): """ if is_string_like(fname_or_fh): with open(fname_or_fh, "wb") as fh: - self._print_png_to_fh(fh) + self._print_png_to_fh(fh, *args, **kwargs) elif is_writable_file_like(fname_or_fh): - self._print_png_to_fh(fname_or_fh) + self._print_png_to_fh(fname_or_fh, *args, **kwargs) else: raise ValueError("filename must be a path or a file-like object") diff --git a/lib/matplotlib/tests/baseline_images/test_backend_pgf/pgf_mixedmode.pdf b/lib/matplotlib/tests/baseline_images/test_backend_pgf/pgf_mixedmode.pdf new file mode 100644 index 000000000000..86dfbbc527cf Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_backend_pgf/pgf_mixedmode.pdf differ diff --git a/lib/matplotlib/tests/test_backend_pgf.py b/lib/matplotlib/tests/test_backend_pgf.py index 8f922e7727f0..34c31ce9a604 100644 --- a/lib/matplotlib/tests/test_backend_pgf.py +++ b/lib/matplotlib/tests/test_backend_pgf.py @@ -145,6 +145,18 @@ def test_pathclip(): plt.savefig(os.path.join(result_dir, "pgf_pathclip.pdf")) +# test mixed mode rendering +@switch_backend('pgf') +def test_mixedmode(): + if not check_for('xelatex'): + raise SkipTest('xelatex + pgf is required') + + Y, X = np.ogrid[-1:1:40j, -1:1:40j] + plt.figure() + plt.pcolor(X**2 + Y**2).set_rasterized(True) + compare_figure('pgf_mixedmode.pdf') + + if __name__ == '__main__': import nose nose.runmodule(argv=['-s','--with-doctest'], exit=False)