Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

backend_pgf: clip paths within the backend (fixes #1857) #1858

Merged
merged 1 commit into from

4 participants

@pwuertz
Collaborator

Because LaTeX doesn't handle very large numbers (#1857), this PR moves some of the clipping operations from the pgf-code into backend_pgf.

@pwuertz
Collaborator

Weird, python 2.6 and 3.x tests are passing on Travis, 2.7 is not (although it passes on my machine with 2.7). It also won't show me the log-file to see what's wrong :/

@mdboom
Owner

It looks like the Travis failure was a networking error when trying to install PIL, so in other words a false result. Looks like a reasonable fix to me.

Should this perhaps go on 1.2.x since it's a bugfix? Also, it could use a test -- I don't know if it needs to be an image comparison test, but something to just make sure the really large number doesn't show up in the output should be sufficient.

@pwuertz
Collaborator

I just added a test that triggers #1857 and now passes with clipping added to draw_path.

Also, apparently some restructuring has been applied to master and a failed LaTeX call now results in an error looking up subprocess.CalledProcessError. I forwarded the missing Exception in matplotlib.compat.subprocess.

If this is fine with you we can apply this to master and I'll prepare another PR for 1.2 without the subprocess fix.

@pelson pelson merged commit 6e94330 into matplotlib:master
@daradib

I think this breaks #1825 because the subprocess module is empty on Google App Engine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 31, 2013
  1. @pwuertz
This page is out of date. Refresh to see the latest.
View
21 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}}" %
View
2  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
View
15 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)
Something went wrong with that request. Please try again.