diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py index 0cfda07dd627..9ce2228b5954 100644 --- a/lib/matplotlib/lines.py +++ b/lib/matplotlib/lines.py @@ -798,8 +798,11 @@ def draw(self, renderer): if self.get_sketch_params() is not None: gc.set_sketch_params(*self.get_sketch_params()) - # We first draw a path within the gaps if needed. - if self.is_dashed() and self._gapcolor is not None: + # We first draw a path within the gaps if needed, but only for + # visible dashed lines; zero-width lines would otherwise yield + # all-zero dashes. + if (self._linewidth > 0 and self.is_dashed() + and self._gapcolor is not None): lc_rgba = mcolors.to_rgba(self._gapcolor, self._alpha) gc.set_foreground(lc_rgba, isRGBA=True) @@ -812,7 +815,10 @@ def draw(self, renderer): lc_rgba = mcolors.to_rgba(self._color, self._alpha) gc.set_foreground(lc_rgba, isRGBA=True) - gc.set_dashes(*self._dash_pattern) + if self._linewidth > 0: + gc.set_dashes(*self._dash_pattern) + else: + gc.set_dashes(0, None) renderer.draw_path(gc, tpath, affine.frozen()) gc.restore() diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index 4a4bd698db04..8dabb548642d 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -709,8 +709,9 @@ def _draw_paths_with_artist_properties( from matplotlib.patheffects import PathEffectRenderer renderer = PathEffectRenderer(self.get_path_effects(), renderer) - # Draw the gaps first if gapcolor is set - if self._has_dashed_edge() and self._gapcolor is not None: + # We first draw a path within the gaps if needed, but only for visible + # dashed edges; zero-width edges would otherwise yield all-zero dashes. + if lw > 0 and self._has_dashed_edge() and self._gapcolor is not None: gc.set_foreground(self._gapcolor, isRGBA=True) offset_gaps, gaps = mlines._get_inverse_dash_pattern( *self._dash_pattern) @@ -720,7 +721,10 @@ def _draw_paths_with_artist_properties( # Draw the main edge gc.set_foreground(self._edgecolor, isRGBA=True) - gc.set_dashes(*self._dash_pattern) + if lw > 0: + gc.set_dashes(*self._dash_pattern) + else: + gc.set_dashes(0, None) for draw_path_args in draw_path_args_list: renderer.draw_path(gc, *draw_path_args) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 45e9cc75fec0..3cf2c4dfd1c7 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -8081,9 +8081,13 @@ def test_twinning_default_axes_class(): assert type(twiny) is Axes -def test_zero_linewidth(): - # Check that setting a zero linewidth doesn't error - plt.plot([0, 1], [0, 1], ls='--', lw=0) +@mpl.style.context('mpl20') +@check_figures_equal() +def test_stairs_fill_zero_linewidth(fig_test, fig_ref): + fig_test.subplots().stairs( + [1, 2, 3, 4], [1, 2, 3, 4, 5], fill=True, ls='--') + fig_ref.subplots().stairs( + [1, 2, 3, 4], [1, 2, 3, 4, 5], fill=True, ls='-') def test_empty_errorbar_legend(): diff --git a/lib/matplotlib/tests/test_lines.py b/lib/matplotlib/tests/test_lines.py index a5b42d5de874..e2a63bbf962b 100644 --- a/lib/matplotlib/tests/test_lines.py +++ b/lib/matplotlib/tests/test_lines.py @@ -92,6 +92,13 @@ def test_valid_linestyles(): line.set_linestyle('aardvark') +@mpl.style.context('mpl20') +def test_zero_linewidth_dashed_uses_solid_gc_dashes(): + fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1], ls='--', lw=0) + fig.draw_without_rendering() + + @image_comparison(['drawstyle_variants.png'], remove_text=True, tol=0 if platform.machine() == 'x86_64' else 0.03) def test_drawstyle_variants(): diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index 51144a7652f3..80dcc43894c4 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -907,6 +907,14 @@ def test_default_linestyle(): assert patch.get_linestyle() == 'solid' +@mpl.style.context('mpl20') +def test_patch_zero_linewidth_dashed_uses_solid_gc_dashes(): + fig, ax = plt.subplots() + ax.add_patch(Rectangle( + (0, 0), 1, 1, fill=False, linewidth=0, linestyle='--')) + fig.draw_without_rendering() + + def test_default_capstyle(): patch = Patch() assert patch.get_capstyle() == 'butt'