Skip to content

Commit

Permalink
Merge pull request #17163 from QuLogic/pdf-marker-clip
Browse files Browse the repository at this point in the history
Fix clipping of markers in PDF backend.
  • Loading branch information
QuLogic committed Jun 10, 2020
2 parents 76e9e26 + d131534 commit 21c3acb
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 1 deletion.
9 changes: 8 additions & 1 deletion lib/matplotlib/backends/backend_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1618,7 +1618,14 @@ def markerObject(self, path, trans, fill, stroke, lw, joinstyle,
def writeMarkers(self):
for ((pathops, fill, stroke, joinstyle, capstyle),
(name, ob, bbox, lw)) in self.markers.items():
bbox = bbox.padded(lw * 0.5)
# bbox wraps the exact limits of the control points, so half a line
# will appear outside it. If the join style is miter and the line
# is not parallel to the edge, then the line will extend even
# further. From the PDF specification, Section 8.4.3.5, the miter
# limit is miterLength / lineWidth and from Table 52, the default
# is 10. With half the miter length outside, that works out to the
# following padding:
bbox = bbox.padded(lw * 5)
self.beginStream(
ob.id, None,
{'Type': Name('XObject'), 'Subtype': Name('Form'),
Expand Down
41 changes: 41 additions & 0 deletions lib/matplotlib/tests/test_marker.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,44 @@ def draw_ref_marker(y, style, size):

ax_test.set(xlim=(-0.5, 1.5), ylim=(-0.5, 1.5))
ax_ref.set(xlim=(-0.5, 1.5), ylim=(-0.5, 1.5))


@check_figures_equal()
def test_marker_clipping(fig_ref, fig_test):
# Plotting multiple markers can trigger different optimized paths in
# backends, so compare single markers vs multiple to ensure they are
# clipped correctly.
marker_count = len(markers.MarkerStyle.markers)
marker_size = 50
ncol = 7
nrow = marker_count // ncol + 1

width = 2 * marker_size * ncol
height = 2 * marker_size * nrow * 2
fig_ref.set_size_inches((width / fig_ref.dpi, height / fig_ref.dpi))
ax_ref = fig_ref.add_axes([0, 0, 1, 1])
fig_test.set_size_inches((width / fig_test.dpi, height / fig_ref.dpi))
ax_test = fig_test.add_axes([0, 0, 1, 1])

for i, marker in enumerate(markers.MarkerStyle.markers):
x = i % ncol
y = i // ncol * 2

# Singular markers per call.
ax_ref.plot([x, x], [y, y + 1], c='k', linestyle='-', lw=3)
ax_ref.plot(x, y, c='k',
marker=marker, markersize=marker_size, markeredgewidth=10,
fillstyle='full', markerfacecolor='white')
ax_ref.plot(x, y + 1, c='k',
marker=marker, markersize=marker_size, markeredgewidth=10,
fillstyle='full', markerfacecolor='white')

# Multiple markers in a single call.
ax_test.plot([x, x], [y, y + 1], c='k', linestyle='-', lw=3,
marker=marker, markersize=marker_size, markeredgewidth=10,
fillstyle='full', markerfacecolor='white')

ax_ref.set(xlim=(-0.5, ncol), ylim=(-0.5, 2 * nrow))
ax_test.set(xlim=(-0.5, ncol), ylim=(-0.5, 2 * nrow))
ax_ref.axis('off')
ax_test.axis('off')

0 comments on commit 21c3acb

Please sign in to comment.