From 70f22969211eedc72170be882199c1746f8c8d11 Mon Sep 17 00:00:00 2001 From: pwuertz Date: Tue, 26 Mar 2013 22:27:42 +0100 Subject: [PATCH] backend_pgf: clip paths within the backend (fixes #1857) --- lib/matplotlib/backends/backend_pgf.py | 21 ++++++++++++++------- lib/matplotlib/compat/subprocess.py | 2 ++ lib/matplotlib/tests/test_backend_pgf.py | 15 +++++++++++++++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/matplotlib/backends/backend_pgf.py b/lib/matplotlib/backends/backend_pgf.py index 940f5a00861e..2a84c531d010 100644 --- a/lib/matplotlib/backends/backend_pgf.py +++ b/lib/matplotlib/backends/backend_pgf.py @@ -421,7 +421,7 @@ def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None) bl, tr = marker_path.get_extents(marker_trans).get_points() coords = bl[0] * f, bl[1] * f, tr[0] * f, tr[1] * f writeln(self.fh, r"\pgfsys@defobject{currentmarker}{\pgfqpoint{%fin}{%fin}}{\pgfqpoint{%fin}{%fin}}{" % coords) - self._print_pgf_path(marker_path, marker_trans) + self._print_pgf_path(None, marker_path, marker_trans) self._pgf_path_draw(stroke=gc.get_linewidth() != 0.0, fill=rgbFace is not None) writeln(self.fh, r"}") @@ -441,7 +441,7 @@ def draw_path(self, gc, path, transform, rgbFace=None): # draw the path self._print_pgf_clip(gc) self._print_pgf_path_styles(gc, rgbFace) - self._print_pgf_path(path, transform) + self._print_pgf_path(gc, path, transform) self._pgf_path_draw(stroke=gc.get_linewidth() != 0.0, fill=rgbFace is not None) writeln(self.fh, r"\end{pgfscope}") @@ -452,7 +452,7 @@ def draw_path(self, gc, path, transform, rgbFace=None): # combine clip and path for clipping self._print_pgf_clip(gc) - self._print_pgf_path(path, transform) + self._print_pgf_path(gc, path, transform) writeln(self.fh, r"\pgfusepath{clip}") # build pattern definition @@ -461,7 +461,7 @@ def draw_path(self, gc, path, transform, rgbFace=None): writeln(self.fh, r"\pgfpathrectangle{\pgfqpoint{0in}{0in}}{\pgfqpoint{1in}{1in}}") writeln(self.fh, r"\pgfusepath{clip}") scale = mpl.transforms.Affine2D().scale(self.dpi) - self._print_pgf_path(gc.get_hatch_path(), scale) + self._print_pgf_path(None, gc.get_hatch_path(), scale) self._pgf_path_draw(stroke=True) writeln(self.fh, r"\end{pgfscope}") writeln(self.fh, r"}") @@ -495,7 +495,7 @@ def _print_pgf_clip(self, gc): # check for clip path clippath, clippath_trans = gc.get_clip_path() if clippath is not None: - self._print_pgf_path(clippath, clippath_trans) + self._print_pgf_path(gc, clippath, clippath_trans) writeln(self.fh, r"\pgfusepath{clip}") def _print_pgf_path_styles(self, gc, rgbFace): @@ -543,10 +543,17 @@ def _print_pgf_path_styles(self, gc, rgbFace): dash_str += r"}{%fpt}" % dash_offset writeln(self.fh, dash_str) - def _print_pgf_path(self, path, transform): + def _print_pgf_path(self, gc, path, transform): f = 1. / self.dpi + # check for clip box + bbox = gc.get_clip_rectangle() if gc else None + if bbox: + p1, p2 = bbox.get_points() + clip = (p1[0], p1[1], p2[0], p2[1]) + else: + clip = None # build path - for points, code in path.iter_segments(transform): + for points, code in path.iter_segments(transform, clip=clip): if code == Path.MOVETO: x, y = tuple(points) writeln(self.fh, r"\pgfpathmoveto{\pgfqpoint{%fin}{%fin}}" % diff --git a/lib/matplotlib/compat/subprocess.py b/lib/matplotlib/compat/subprocess.py index 5f77c4f8ec0d..6918e7d78be0 100644 --- a/lib/matplotlib/compat/subprocess.py +++ b/lib/matplotlib/compat/subprocess.py @@ -75,3 +75,5 @@ def _check_output(*popenargs, **kwargs): check_output = subprocess.check_output else: check_output = _check_output + +CalledProcessError = subprocess.CalledProcessError diff --git a/lib/matplotlib/tests/test_backend_pgf.py b/lib/matplotlib/tests/test_backend_pgf.py index 73ecb26472e1..8f922e7727f0 100644 --- a/lib/matplotlib/tests/test_backend_pgf.py +++ b/lib/matplotlib/tests/test_backend_pgf.py @@ -130,6 +130,21 @@ def test_rcupdate(): create_figure() compare_figure('pgf_rcupdate%d.pdf' % (i+1)) + +# test backend-side clipping, since large numbers are not supported by TeX +@switch_backend('pgf') +def test_pathclip(): + if not check_for('xelatex'): + raise SkipTest('xelatex + pgf is required') + + plt.figure() + plt.plot([0., 1e100], [0., 1e100]) + plt.xlim(0, 1) + plt.ylim(0, 1) + # this test passes if compiling/saving to pdf works (no image comparison) + plt.savefig(os.path.join(result_dir, "pgf_pathclip.pdf")) + + if __name__ == '__main__': import nose nose.runmodule(argv=['-s','--with-doctest'], exit=False)