From e1916505eec44b6656c7ee13be0bcd842aaecc45 Mon Sep 17 00:00:00 2001 From: Pranav Date: Tue, 9 Apr 2024 12:02:21 +0530 Subject: [PATCH 01/16] Add hatch linewidth setter in Graphics Context Base --- lib/matplotlib/backend_bases.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 95ed49612b35..80e57311d6de 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -961,6 +961,10 @@ def get_hatch_linewidth(self): """Get the hatch linewidth.""" return self._hatch_linewidth + def set_hatch_linewidth(self, hatch_linewidth): + """Set the hatch linewidth.""" + self._hatch_linewidth = hatch_linewidth + def get_sketch_params(self): """ Return the sketch parameters for the artist. From 7faf10415276aabacba85a29388dc2a35de8637d Mon Sep 17 00:00:00 2001 From: Pranav Date: Tue, 9 Apr 2024 12:27:24 +0530 Subject: [PATCH 02/16] Add linewidth parameter to hatch style in PDF, PS and SVG backends --- lib/matplotlib/backends/backend_pdf.py | 51 ++++++++++++++------------ lib/matplotlib/backends/backend_ps.py | 3 +- lib/matplotlib/backends/backend_svg.py | 9 +++-- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/lib/matplotlib/backends/backend_pdf.py b/lib/matplotlib/backends/backend_pdf.py index 44b85cd3136d..07707710494c 100644 --- a/lib/matplotlib/backends/backend_pdf.py +++ b/lib/matplotlib/backends/backend_pdf.py @@ -732,7 +732,7 @@ def __init__(self, filename, metadata=None): self._soft_mask_states = {} self._soft_mask_seq = (Name(f'SM{i}') for i in itertools.count(1)) self._soft_mask_groups = [] - self.hatchPatterns = {} + self._hatch_patterns = {} self._hatch_pattern_seq = (Name(f'H{i}') for i in itertools.count(1)) self.gouraudTriangles = [] @@ -1536,25 +1536,29 @@ def _write_soft_mask_groups(self): def hatchPattern(self, hatch_style): # The colors may come in as numpy arrays, which aren't hashable if hatch_style is not None: - edge, face, hatch = hatch_style + edge, face, hatch, lw = hatch_style if edge is not None: edge = tuple(edge) if face is not None: face = tuple(face) - hatch_style = (edge, face, hatch) + hatch_style = (edge, face, hatch, lw) - pattern = self.hatchPatterns.get(hatch_style, None) + pattern = self._hatch_patterns.get(hatch_style, None) if pattern is not None: return pattern name = next(self._hatch_pattern_seq) - self.hatchPatterns[hatch_style] = name + self._hatch_patterns[hatch_style] = name return name + hatchPatterns = _api.deprecated("3.8")(property(lambda self: { + k: (e, f, h) for k, (e, f, h, l) in self._hatch_patterns.items() + })) + def writeHatches(self): hatchDict = dict() sidelen = 72.0 - for hatch_style, name in self.hatchPatterns.items(): + for hatch_style, name in self._hatch_patterns.items(): ob = self.reserveObject('hatch pattern') hatchDict[name] = ob res = {'Procsets': @@ -1569,7 +1573,7 @@ def writeHatches(self): # Change origin to match Agg at top-left. 'Matrix': [1, 0, 0, 1, 0, self.height * 72]}) - stroke_rgb, fill_rgb, hatch = hatch_style + stroke_rgb, fill_rgb, hatch, lw = hatch_style self.output(stroke_rgb[0], stroke_rgb[1], stroke_rgb[2], Op.setrgb_stroke) if fill_rgb is not None: @@ -1578,7 +1582,7 @@ def writeHatches(self): 0, 0, sidelen, sidelen, Op.rectangle, Op.fill) - self.output(mpl.rcParams['hatch.linewidth'], Op.setlinewidth) + self.output(lw, Op.setlinewidth) self.output(*self.pathOperations( Path.hatch(hatch), @@ -2461,7 +2465,7 @@ def stroke(self): """ # _linewidth > 0: in pdf a line of width 0 is drawn at minimum # possible device width, but e.g., agg doesn't draw at all - return (self._linewidth > 0 and self._alpha > 0 and + return (self.get_linewidth() > 0 and self._alpha > 0 and (len(self._rgb) <= 3 or self._rgb[3] != 0.0)) def fill(self, *args): @@ -2509,14 +2513,15 @@ def alpha_cmd(self, alpha, forced, effective_alphas): name = self.file.alphaState(effective_alphas) return [name, Op.setgstate] - def hatch_cmd(self, hatch, hatch_color): + def hatch_cmd(self, hatch, hatch_color, hatch_linewidth): if not hatch: if self._fillcolor is not None: return self.fillcolor_cmd(self._fillcolor) else: return [Name('DeviceRGB'), Op.setcolorspace_nonstroke] else: - hatch_style = (hatch_color, self._fillcolor, hatch) + hatch_style = (hatch_color, self._fillcolor, hatch, + hatch_linewidth) name = self.file.hatchPattern(hatch_style) return [Name('Pattern'), Op.setcolorspace_nonstroke, name, Op.setcolor_nonstroke] @@ -2572,17 +2577,17 @@ def clip_cmd(self, cliprect, clippath): commands = ( # must come first since may pop - (('_cliprect', '_clippath'), clip_cmd), - (('_alpha', '_forced_alpha', '_effective_alphas'), alpha_cmd), - (('_capstyle',), capstyle_cmd), - (('_fillcolor',), fillcolor_cmd), - (('_joinstyle',), joinstyle_cmd), - (('_linewidth',), linewidth_cmd), - (('_dashes',), dash_cmd), - (('_rgb',), rgb_cmd), + (("_cliprect", "_clippath"), clip_cmd), + (("_alpha", "_forced_alpha", "_effective_alphas"), alpha_cmd), + (("_capstyle",), capstyle_cmd), + (("_fillcolor",), fillcolor_cmd), + (("_joinstyle",), joinstyle_cmd), + (("_linewidth",), linewidth_cmd), + (("_dashes",), dash_cmd), + (("_rgb",), rgb_cmd), # must come after fillcolor and rgb - (('_hatch', '_hatch_color'), hatch_cmd), - ) + (("_hatch", "_hatch_color", "_hatch_linewidth"), hatch_cmd), + ) def delta(self, other): """ @@ -2610,11 +2615,11 @@ def delta(self, other): break # Need to update hatching if we also updated fillcolor - if params == ('_hatch', '_hatch_color') and fill_performed: + if cmd.__name__ == 'hatch_cmd' and fill_performed: different = True if different: - if params == ('_fillcolor',): + if cmd.__name__ == 'fillcolor_cmd': fill_performed = True theirs = [getattr(other, p) for p in params] cmds.extend(cmd(self, *theirs)) diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index 893c660c0b24..47ad194a9dfb 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -510,7 +510,7 @@ def create_hatch(self, hatch): if hatch in self._hatches: return self._hatches[hatch] name = 'H%d' % len(self._hatches) - linewidth = mpl.rcParams['hatch.linewidth'] + # linewidth = mpl.rcParams['hatch.linewidth'] pageheight = self.height * 72 self._pswriter.write(f"""\ << /PatternType 1 @@ -935,6 +935,7 @@ def _draw_ps(self, ps, gc, rgbFace, *, fill=True, stroke=True): if hatch: hatch_name = self.create_hatch(hatch) write("gsave\n") + write("%f setlinewidth" % gc.get_hatch_linewidth()) write(_nums_to_str(*gc.get_hatch_color()[:3])) write(f" {hatch_name} setpattern fill grestore\n") diff --git a/lib/matplotlib/backends/backend_svg.py b/lib/matplotlib/backends/backend_svg.py index dbf056613696..2f722cc8cb7f 100644 --- a/lib/matplotlib/backends/backend_svg.py +++ b/lib/matplotlib/backends/backend_svg.py @@ -500,11 +500,12 @@ def _get_hatch(self, gc, rgbFace): edge = gc.get_hatch_color() if edge is not None: edge = tuple(edge) - dictkey = (gc.get_hatch(), rgbFace, edge) + lw = gc._linewidth + dictkey = (gc.get_hatch(), rgbFace, edge, lw) oid = self._hatchd.get(dictkey) if oid is None: oid = self._make_id('h', dictkey) - self._hatchd[dictkey] = ((gc.get_hatch_path(), rgbFace, edge), oid) + self._hatchd[dictkey] = ((gc.get_hatch_path(), rgbFace, edge, lw), oid) else: _, oid = oid return oid @@ -515,7 +516,7 @@ def _write_hatches(self): HATCH_SIZE = 72 writer = self.writer writer.start('defs') - for (path, face, stroke), oid in self._hatchd.values(): + for (path, face, stroke, lw), oid in self._hatchd.values(): writer.start( 'pattern', id=oid, @@ -539,7 +540,7 @@ def _write_hatches(self): hatch_style = { 'fill': rgb2hex(stroke), 'stroke': rgb2hex(stroke), - 'stroke-width': str(mpl.rcParams['hatch.linewidth']), + 'stroke-width': str(lw), 'stroke-linecap': 'butt', 'stroke-linejoin': 'miter' } From e754c824ca0f0ae077e43bf48b6922af23304f72 Mon Sep 17 00:00:00 2001 From: Pranav Date: Tue, 9 Apr 2024 12:33:36 +0530 Subject: [PATCH 03/16] Add linewidht setter and getter methods to Collections --- lib/matplotlib/collections.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index e668308abc82..09bf3c0839f8 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -174,6 +174,7 @@ def __init__(self, *, self._edge_is_mapped = None self._mapped_colors = None # calculated in update_scalarmappable self._hatch_color = mcolors.to_rgba(mpl.rcParams['hatch.color']) + self._hatch_linewidth = mpl.rcParams['hatch.linewidth'] self.set_facecolor(facecolors) self.set_edgecolor(edgecolors) self.set_linewidth(linewidths) @@ -364,6 +365,9 @@ def draw(self, renderer): if self._hatch: gc.set_hatch(self._hatch) gc.set_hatch_color(self._hatch_color) + print(self._hatch_linewidth) + print(self.get_hatch_linewidth()) + mhatch._set_hatch_linewidth(gc, self.get_hatch_linewidth()) if self.get_sketch_params() is not None: gc.set_sketch_params(*self.get_sketch_params()) @@ -542,6 +546,14 @@ def get_hatch(self): """Return the current hatching pattern.""" return self._hatch + def set_hatch_linewidth(self, lw): + """Set the hatch linewidth""" + self._hatch_linewidth = lw + + def get_hatch_linewidth(self): + """Return the hatch linewidth""" + return self._hatch_linewidth + def set_offsets(self, offsets): """ Set the offsets for the collection. From 9976d31aa374c5f221e8747edeec529bba7533b1 Mon Sep 17 00:00:00 2001 From: Pranav Date: Tue, 9 Apr 2024 12:40:52 +0530 Subject: [PATCH 04/16] Deprecation warning for setting linewidths in non-PDF,PS,SVG backends --- lib/matplotlib/hatch.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/matplotlib/hatch.py b/lib/matplotlib/hatch.py index 0cbd042e1628..9438472167a5 100644 --- a/lib/matplotlib/hatch.py +++ b/lib/matplotlib/hatch.py @@ -223,3 +223,14 @@ def get_path(hatchpattern, density=6): cursor += pattern.num_vertices return Path(vertices, codes) + + +def _set_hatch_linewidth(gc, hatch_linewidth): + if hasattr(gc, "set_hatch_linewidth"): + gc.set_hatch_linewidth(hatch_linewidth) + else: + _api.warn_deprecated( + "3.8", message="The current backend does not define " + "GraphicsContextRenderer.set_hatch_linewidth; support for such " + "backends is deprecated since %(since)s and will be removed " + "%(removal)s.") From 30726ab2de6ef5dbe7a53506285f8071a3917a68 Mon Sep 17 00:00:00 2001 From: Pranav Date: Tue, 9 Apr 2024 12:44:46 +0530 Subject: [PATCH 05/16] Add setter and getter methods for hatch linewidth in Patch --- lib/matplotlib/patches.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index 2db678587ec7..cfffb64c429a 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -72,6 +72,7 @@ def __init__(self, *, joinstyle = JoinStyle.miter self._hatch_color = colors.to_rgba(mpl.rcParams['hatch.color']) + self._hatch_linewidth = mpl.rcParams['hatch.linewidth'] self._fill = bool(fill) # needed for set_facecolor call if color is not None: if edgecolor is not None or facecolor is not None: @@ -571,6 +572,14 @@ def get_hatch(self): """Return the hatching pattern.""" return self._hatch + def set_hatch_linewidth(self, hatch_linewidth): + """Set the hatch linewidth""" + self._hatch_linewidth = hatch_linewidth + + def get_hatch_linewidth(self): + """Return the hatch linewidth""" + return self._hatch_linewidth + def _draw_paths_with_artist_properties( self, renderer, draw_path_args_list): """ @@ -605,6 +614,7 @@ def _draw_paths_with_artist_properties( if self._hatch: gc.set_hatch(self._hatch) gc.set_hatch_color(self._hatch_color) + mhatch._set_hatch_linewidth(gc, self.get_hatch_linewidth()) if self.get_sketch_params() is not None: gc.set_sketch_params(*self.get_sketch_params()) From 9c385ff71c5feca688433bd87583aeec812823fc Mon Sep 17 00:00:00 2001 From: Pranav Date: Wed, 10 Apr 2024 07:31:17 +0530 Subject: [PATCH 06/16] Add test for patches setter and getter --- lib/matplotlib/collections.pyi | 2 ++ lib/matplotlib/tests/test_patches.py | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/matplotlib/collections.pyi b/lib/matplotlib/collections.pyi index 06d8676867ee..7237b5846d10 100644 --- a/lib/matplotlib/collections.pyi +++ b/lib/matplotlib/collections.pyi @@ -48,6 +48,8 @@ class Collection(artist.Artist, cm.ScalarMappable): def get_urls(self) -> Sequence[str | None]: ... def set_hatch(self, hatch: str) -> None: ... def get_hatch(self) -> str: ... + def set_hatch_linewidth(self, lw: float) -> None: ... + def get_hatch_linewidth(self) -> float: ... def set_offsets(self, offsets: ArrayLike) -> None: ... def get_offsets(self) -> ArrayLike: ... def set_linewidth(self, lw: float | Sequence[float]) -> None: ... diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index 3544ce8cb10c..71ca81539844 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -960,3 +960,20 @@ def test_arrow_set_data(): ) arrow.set_data(x=.5, dx=3, dy=8, width=1.2) assert np.allclose(expected2, np.round(arrow.get_verts(), 2)) + + +@check_figures_equal(extensions=["png", "pdf", "svg", "eps"]) +def test_set_and_get_hatch_linewidth(fig_test, fig_ref): + ax_test = fig_test.add_subplot() + ax_ref = fig_ref.add_subplot() + + lw = 2.0 + + with plt.rc_context({"hatch.linewidth": lw}): + ax_ref.add_patch(mpatches.Rectangle((0, 0), 1, 1, hatch="x")) + + ax_test.add_patch(mpatches.Rectangle((0, 0), 1, 1, hatch="x")) + ax_test.patches[0].set_hatch_linewidth(lw) + + assert (ax_ref.patches[0].get_hatch_linewidth() == lw) + assert (ax_test.patches[0].get_hatch_linewidth() == lw) From 6938fbe7af449dc511ce52bd9f748c164275d23a Mon Sep 17 00:00:00 2001 From: Pranav Date: Wed, 10 Apr 2024 07:47:51 +0530 Subject: [PATCH 07/16] Add test for collections setter and getter --- lib/matplotlib/tests/test_collections.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/matplotlib/tests/test_collections.py b/lib/matplotlib/tests/test_collections.py index 19af38f3b522..41cec64f054a 100644 --- a/lib/matplotlib/tests/test_collections.py +++ b/lib/matplotlib/tests/test_collections.py @@ -1361,3 +1361,24 @@ def test_striped_lines(fig_test, fig_ref, gapcolor): for x, gcol, ls in zip(x, itertools.cycle(gapcolor), itertools.cycle(linestyles)): ax_ref.axvline(x, 0, 1, linewidth=20, linestyle=ls, gapcolor=gcol, alpha=0.5) + + +@check_figures_equal(extensions=['png', 'pdf', 'svg', 'eps']) +def test_hatch_linewidth(fig_test, fig_ref): + ax_test = fig_test.add_subplot() + ax_ref = fig_ref.add_subplot() + + lw = 2.0 + + ref = mcollections.CircleCollection(sizes=[1, 2, 3, 4, 5], hatch='x') + ref.set_linewidth(2) + + with mpl.rc_context({'hatch.linewidth': lw}): + test = mcollections.CircleCollection(sizes=[1, 2, 3, 4, 5], hatch='x') + test.set_linewidth(2) + + # Add the collection to the axes + ax_ref.add_collection(ref) + ax_test.add_collection(test) + + assert ((test.get_linewidth() == lw) and (ref.get_linewidth() == lw)) From 05300fe36eb4b4a1114cc2693276a35bc52b926a Mon Sep 17 00:00:00 2001 From: Pranav Date: Thu, 11 Apr 2024 17:06:31 +0530 Subject: [PATCH 08/16] Moved _set_hatch_linewidth to backend_bases --- lib/matplotlib/backend_bases.py | 10 ++++++++++ lib/matplotlib/backend_bases.pyi | 1 + lib/matplotlib/collections.py | 4 +--- lib/matplotlib/patches.py | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 80e57311d6de..a4e74b8bf9ed 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -965,6 +965,16 @@ def set_hatch_linewidth(self, hatch_linewidth): """Set the hatch linewidth.""" self._hatch_linewidth = hatch_linewidth + def _set_hatch_linewidth(self, hatch_linewidth): + if hasattr(self, "set_hatch_linewidth"): + self.set_hatch_linewidth(hatch_linewidth) + else: + _api.warn_deprecated( + "3.8", message="The current backend does not define " + "GraphicsContextRenderer.set_hatch_linewidth; support for such " + "backends is deprecated since %(since)s and will be removed " + "%(removal)s.") + def get_sketch_params(self): """ Return the sketch parameters for the artist. diff --git a/lib/matplotlib/backend_bases.pyi b/lib/matplotlib/backend_bases.pyi index 70be504666fc..12b4d06aa68c 100644 --- a/lib/matplotlib/backend_bases.pyi +++ b/lib/matplotlib/backend_bases.pyi @@ -167,6 +167,7 @@ class GraphicsContextBase: def get_hatch_color(self) -> ColorType: ... def set_hatch_color(self, hatch_color: ColorType) -> None: ... def get_hatch_linewidth(self) -> float: ... + def set_hatch_linewidth(self, hatch_linewidth: float) -> None: ... def get_sketch_params(self) -> tuple[float, float, float] | None: ... def set_sketch_params( self, diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index 09bf3c0839f8..8f1133d11f2a 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -365,9 +365,7 @@ def draw(self, renderer): if self._hatch: gc.set_hatch(self._hatch) gc.set_hatch_color(self._hatch_color) - print(self._hatch_linewidth) - print(self.get_hatch_linewidth()) - mhatch._set_hatch_linewidth(gc, self.get_hatch_linewidth()) + gc._set_hatch_linewidth(self._hatch_linewidth) if self.get_sketch_params() is not None: gc.set_sketch_params(*self.get_sketch_params()) diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index cfffb64c429a..d4a3f1a8926f 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -614,7 +614,7 @@ def _draw_paths_with_artist_properties( if self._hatch: gc.set_hatch(self._hatch) gc.set_hatch_color(self._hatch_color) - mhatch._set_hatch_linewidth(gc, self.get_hatch_linewidth()) + gc._set_hatch_linewidth(self._hatch_linewidth) if self.get_sketch_params() is not None: gc.set_sketch_params(*self.get_sketch_params()) From 21cd38d3716b4d0edbd2db4d2c874c5a673c3b6f Mon Sep 17 00:00:00 2001 From: Pranav Date: Mon, 13 May 2024 01:00:43 +0530 Subject: [PATCH 09/16] Added API change note --- doc/api/next_api_changes/deprecations/28048-PR.rst | 6 ++++++ lib/matplotlib/backends/backend_pdf.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 doc/api/next_api_changes/deprecations/28048-PR.rst diff --git a/doc/api/next_api_changes/deprecations/28048-PR.rst b/doc/api/next_api_changes/deprecations/28048-PR.rst new file mode 100644 index 000000000000..4c5e9554b1cc --- /dev/null +++ b/doc/api/next_api_changes/deprecations/28048-PR.rst @@ -0,0 +1,6 @@ +``PdfFile.hatchPatterns`` +~~~~~~~~~~~~~~~~~~~~~~~~~ + +... is deprecated and replaced by an internal helper called ``PdfFile._hatch_patterns`` instead. + +- The attribute ``PdfFile._hatch_patterns`` now stores hatch linewidths as well. diff --git a/lib/matplotlib/backends/backend_pdf.py b/lib/matplotlib/backends/backend_pdf.py index 07707710494c..7ebe6c1a0279 100644 --- a/lib/matplotlib/backends/backend_pdf.py +++ b/lib/matplotlib/backends/backend_pdf.py @@ -1551,7 +1551,7 @@ def hatchPattern(self, hatch_style): self._hatch_patterns[hatch_style] = name return name - hatchPatterns = _api.deprecated("3.8")(property(lambda self: { + hatchPatterns = _api.deprecated("3.10")(property(lambda self: { k: (e, f, h) for k, (e, f, h, l) in self._hatch_patterns.items() })) From 1a41d77aa291f6eb50b86e515fbe2c5b48755236 Mon Sep 17 00:00:00 2001 From: Pranav Date: Tue, 22 Oct 2024 15:47:09 +0530 Subject: [PATCH 10/16] Made suggested changes --- doc/api/next_api_changes/deprecations/28048-PR.rst | 4 +--- lib/matplotlib/backends/backend_pdf.py | 2 +- lib/matplotlib/collections.py | 4 ++-- lib/matplotlib/patches.py | 8 ++++---- lib/matplotlib/patches.pyi | 2 ++ lib/matplotlib/tests/test_collections.py | 7 +++---- lib/matplotlib/tests/test_patches.py | 4 ++-- 7 files changed, 15 insertions(+), 16 deletions(-) diff --git a/doc/api/next_api_changes/deprecations/28048-PR.rst b/doc/api/next_api_changes/deprecations/28048-PR.rst index 4c5e9554b1cc..4e90a3aced19 100644 --- a/doc/api/next_api_changes/deprecations/28048-PR.rst +++ b/doc/api/next_api_changes/deprecations/28048-PR.rst @@ -1,6 +1,4 @@ ``PdfFile.hatchPatterns`` ~~~~~~~~~~~~~~~~~~~~~~~~~ -... is deprecated and replaced by an internal helper called ``PdfFile._hatch_patterns`` instead. - -- The attribute ``PdfFile._hatch_patterns`` now stores hatch linewidths as well. +... is deprecated. diff --git a/lib/matplotlib/backends/backend_pdf.py b/lib/matplotlib/backends/backend_pdf.py index 7ebe6c1a0279..05636836cc5c 100644 --- a/lib/matplotlib/backends/backend_pdf.py +++ b/lib/matplotlib/backends/backend_pdf.py @@ -2465,7 +2465,7 @@ def stroke(self): """ # _linewidth > 0: in pdf a line of width 0 is drawn at minimum # possible device width, but e.g., agg doesn't draw at all - return (self.get_linewidth() > 0 and self._alpha > 0 and + return (self._linewidth > 0 and self._alpha > 0 and (len(self._rgb) <= 3 or self._rgb[3] != 0.0)) def fill(self, *args): diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index 8f1133d11f2a..1f8caa641f4b 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -545,11 +545,11 @@ def get_hatch(self): return self._hatch def set_hatch_linewidth(self, lw): - """Set the hatch linewidth""" + """Set the hatch linewidth.""" self._hatch_linewidth = lw def get_hatch_linewidth(self): - """Return the hatch linewidth""" + """Return the hatch linewidth.""" return self._hatch_linewidth def set_offsets(self, offsets): diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index d4a3f1a8926f..40fa88073338 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -572,12 +572,12 @@ def get_hatch(self): """Return the hatching pattern.""" return self._hatch - def set_hatch_linewidth(self, hatch_linewidth): - """Set the hatch linewidth""" - self._hatch_linewidth = hatch_linewidth + def set_hatch_linewidth(self, lw): + """Set the hatch linewidth.""" + self._hatch_linewidth = lw def get_hatch_linewidth(self): - """Return the hatch linewidth""" + """Return the hatch linewidth.""" return self._hatch_linewidth def _draw_paths_with_artist_properties( diff --git a/lib/matplotlib/patches.pyi b/lib/matplotlib/patches.pyi index f6c9ddf75839..0645479ee5e7 100644 --- a/lib/matplotlib/patches.pyi +++ b/lib/matplotlib/patches.pyi @@ -59,6 +59,8 @@ class Patch(artist.Artist): def set_joinstyle(self, s: JoinStyleType) -> None: ... def get_joinstyle(self) -> Literal["miter", "round", "bevel"]: ... def set_hatch(self, hatch: str) -> None: ... + def set_hatch_linewidth(self, lw: float) -> None: ... + def get_hatch_linewidth(self) -> float: ... def get_hatch(self) -> str: ... def get_path(self) -> Path: ... diff --git a/lib/matplotlib/tests/test_collections.py b/lib/matplotlib/tests/test_collections.py index 41cec64f054a..4a834161acfb 100644 --- a/lib/matplotlib/tests/test_collections.py +++ b/lib/matplotlib/tests/test_collections.py @@ -1373,12 +1373,11 @@ def test_hatch_linewidth(fig_test, fig_ref): ref = mcollections.CircleCollection(sizes=[1, 2, 3, 4, 5], hatch='x') ref.set_linewidth(2) - with mpl.rc_context({'hatch.linewidth': lw}): - test = mcollections.CircleCollection(sizes=[1, 2, 3, 4, 5], hatch='x') - test.set_linewidth(2) + with mpl.rc_context({"hatch.linewidth": lw}): + test = PolyCollection(polygons, hatch="x") # Add the collection to the axes ax_ref.add_collection(ref) ax_test.add_collection(test) - assert ((test.get_linewidth() == lw) and (ref.get_linewidth() == lw)) + assert test.get_hatch_linewidth() == ref.get_hatch_linewidth() == lw diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index 71ca81539844..edbafa074de5 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -975,5 +975,5 @@ def test_set_and_get_hatch_linewidth(fig_test, fig_ref): ax_test.add_patch(mpatches.Rectangle((0, 0), 1, 1, hatch="x")) ax_test.patches[0].set_hatch_linewidth(lw) - assert (ax_ref.patches[0].get_hatch_linewidth() == lw) - assert (ax_test.patches[0].get_hatch_linewidth() == lw) + assert ax_ref.patches[0].get_hatch_linewidth() == lw + assert ax_test.patches[0].get_hatch_linewidth() == lw From 36d132f00308504aa8f9185f498815d02b391ce5 Mon Sep 17 00:00:00 2001 From: Pranav Date: Tue, 22 Oct 2024 16:40:14 +0530 Subject: [PATCH 11/16] Resolved merge problems --- lib/matplotlib/backends/backend_pdf.py | 16 +++++++--------- lib/matplotlib/backends/backend_ps.py | 6 +++--- lib/matplotlib/collections.py | 2 +- lib/matplotlib/patches.py | 2 +- lib/matplotlib/tests/test_collections.py | 9 ++++++--- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/matplotlib/backends/backend_pdf.py b/lib/matplotlib/backends/backend_pdf.py index 05636836cc5c..4c3c222ac72f 100644 --- a/lib/matplotlib/backends/backend_pdf.py +++ b/lib/matplotlib/backends/backend_pdf.py @@ -1535,13 +1535,12 @@ def _write_soft_mask_groups(self): def hatchPattern(self, hatch_style): # The colors may come in as numpy arrays, which aren't hashable - if hatch_style is not None: - edge, face, hatch, lw = hatch_style - if edge is not None: - edge = tuple(edge) - if face is not None: - face = tuple(face) - hatch_style = (edge, face, hatch, lw) + edge, face, hatch, lw = hatch_style + if edge is not None: + edge = tuple(edge) + if face is not None: + face = tuple(face) + hatch_style = (edge, face, hatch, lw) pattern = self._hatch_patterns.get(hatch_style, None) if pattern is not None: @@ -2520,8 +2519,7 @@ def hatch_cmd(self, hatch, hatch_color, hatch_linewidth): else: return [Name('DeviceRGB'), Op.setcolorspace_nonstroke] else: - hatch_style = (hatch_color, self._fillcolor, hatch, - hatch_linewidth) + hatch_style = (hatch_color, self._fillcolor, hatch, hatch_linewidth) name = self.file.hatchPattern(hatch_style) return [Name('Pattern'), Op.setcolorspace_nonstroke, name, Op.setcolor_nonstroke] diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index 47ad194a9dfb..f490f88698b4 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -505,12 +505,12 @@ def set_font(self, fontname, fontsize, store=True): self.fontname = fontname self.fontsize = fontsize - def create_hatch(self, hatch): + def create_hatch(self, hatch, gc=None): sidelen = 72 if hatch in self._hatches: return self._hatches[hatch] name = 'H%d' % len(self._hatches) - # linewidth = mpl.rcParams['hatch.linewidth'] + linewidth = gc.get_hatch_linewidth() pageheight = self.height * 72 self._pswriter.write(f"""\ << /PatternType 1 @@ -933,7 +933,7 @@ def _draw_ps(self, ps, gc, rgbFace, *, fill=True, stroke=True): write("grestore\n") if hatch: - hatch_name = self.create_hatch(hatch) + hatch_name = self.create_hatch(hatch, gc) write("gsave\n") write("%f setlinewidth" % gc.get_hatch_linewidth()) write(_nums_to_str(*gc.get_hatch_color()[:3])) diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index 1f8caa641f4b..94aa6b315141 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -365,7 +365,7 @@ def draw(self, renderer): if self._hatch: gc.set_hatch(self._hatch) gc.set_hatch_color(self._hatch_color) - gc._set_hatch_linewidth(self._hatch_linewidth) + gc.set_hatch_linewidth(self._hatch_linewidth) if self.get_sketch_params() is not None: gc.set_sketch_params(*self.get_sketch_params()) diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index 40fa88073338..e7e56c853849 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -614,7 +614,7 @@ def _draw_paths_with_artist_properties( if self._hatch: gc.set_hatch(self._hatch) gc.set_hatch_color(self._hatch_color) - gc._set_hatch_linewidth(self._hatch_linewidth) + gc.set_hatch_linewidth(self._hatch_linewidth) if self.get_sketch_params() is not None: gc.set_sketch_params(*self.get_sketch_params()) diff --git a/lib/matplotlib/tests/test_collections.py b/lib/matplotlib/tests/test_collections.py index 4a834161acfb..11934cfca2c3 100644 --- a/lib/matplotlib/tests/test_collections.py +++ b/lib/matplotlib/tests/test_collections.py @@ -1370,13 +1370,16 @@ def test_hatch_linewidth(fig_test, fig_ref): lw = 2.0 - ref = mcollections.CircleCollection(sizes=[1, 2, 3, 4, 5], hatch='x') - ref.set_linewidth(2) + polygons = [ + [(0.1, 0.1), (0.1, 0.4), (0.4, 0.4), (0.4, 0.1)], + [(0.6, 0.6), (0.6, 0.9), (0.9, 0.9), (0.9, 0.6)], + ] + ref = PolyCollection(polygons, hatch="x") + ref.set_hatch_linewidth(lw) with mpl.rc_context({"hatch.linewidth": lw}): test = PolyCollection(polygons, hatch="x") - # Add the collection to the axes ax_ref.add_collection(ref) ax_test.add_collection(test) From 7d94d86b382e30b313899de98d62cc83a305ffd4 Mon Sep 17 00:00:00 2001 From: Pranav Date: Tue, 22 Oct 2024 16:49:00 +0530 Subject: [PATCH 12/16] Rollback unwanted changes --- lib/matplotlib/backends/backend_pdf.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/matplotlib/backends/backend_pdf.py b/lib/matplotlib/backends/backend_pdf.py index 4c3c222ac72f..86cbbe4d9a41 100644 --- a/lib/matplotlib/backends/backend_pdf.py +++ b/lib/matplotlib/backends/backend_pdf.py @@ -2575,16 +2575,16 @@ def clip_cmd(self, cliprect, clippath): commands = ( # must come first since may pop - (("_cliprect", "_clippath"), clip_cmd), - (("_alpha", "_forced_alpha", "_effective_alphas"), alpha_cmd), - (("_capstyle",), capstyle_cmd), - (("_fillcolor",), fillcolor_cmd), - (("_joinstyle",), joinstyle_cmd), - (("_linewidth",), linewidth_cmd), - (("_dashes",), dash_cmd), - (("_rgb",), rgb_cmd), + (('_cliprect', '_clippath'), clip_cmd), + (('_alpha', '_forced_alpha', '_effective_alphas'), alpha_cmd), + (('_capstyle',), capstyle_cmd), + (('_fillcolor',), fillcolor_cmd), + (('_joinstyle',), joinstyle_cmd), + (('_linewidth',), linewidth_cmd), + (('_dashes',), dash_cmd), + (('_rgb',), rgb_cmd), # must come after fillcolor and rgb - (("_hatch", "_hatch_color", "_hatch_linewidth"), hatch_cmd), + (('_hatch', '_hatch_color', '_hatch_linewidth'), hatch_cmd), ) def delta(self, other): From 65b5c32293400e4ceb88b1be40fdb38ebb2439d6 Mon Sep 17 00:00:00 2001 From: Pranav Date: Tue, 22 Oct 2024 20:48:08 +0530 Subject: [PATCH 13/16] Minor Fixes --- lib/matplotlib/backend_bases.py | 10 ---------- lib/matplotlib/backends/backend_ps.py | 1 - lib/matplotlib/hatch.py | 11 ----------- 3 files changed, 22 deletions(-) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index a4e74b8bf9ed..80e57311d6de 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -965,16 +965,6 @@ def set_hatch_linewidth(self, hatch_linewidth): """Set the hatch linewidth.""" self._hatch_linewidth = hatch_linewidth - def _set_hatch_linewidth(self, hatch_linewidth): - if hasattr(self, "set_hatch_linewidth"): - self.set_hatch_linewidth(hatch_linewidth) - else: - _api.warn_deprecated( - "3.8", message="The current backend does not define " - "GraphicsContextRenderer.set_hatch_linewidth; support for such " - "backends is deprecated since %(since)s and will be removed " - "%(removal)s.") - def get_sketch_params(self): """ Return the sketch parameters for the artist. diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index f490f88698b4..bfe3ad59702e 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -935,7 +935,6 @@ def _draw_ps(self, ps, gc, rgbFace, *, fill=True, stroke=True): if hatch: hatch_name = self.create_hatch(hatch, gc) write("gsave\n") - write("%f setlinewidth" % gc.get_hatch_linewidth()) write(_nums_to_str(*gc.get_hatch_color()[:3])) write(f" {hatch_name} setpattern fill grestore\n") diff --git a/lib/matplotlib/hatch.py b/lib/matplotlib/hatch.py index 9438472167a5..0cbd042e1628 100644 --- a/lib/matplotlib/hatch.py +++ b/lib/matplotlib/hatch.py @@ -223,14 +223,3 @@ def get_path(hatchpattern, density=6): cursor += pattern.num_vertices return Path(vertices, codes) - - -def _set_hatch_linewidth(gc, hatch_linewidth): - if hasattr(gc, "set_hatch_linewidth"): - gc.set_hatch_linewidth(hatch_linewidth) - else: - _api.warn_deprecated( - "3.8", message="The current backend does not define " - "GraphicsContextRenderer.set_hatch_linewidth; support for such " - "backends is deprecated since %(since)s and will be removed " - "%(removal)s.") From 3cad9a1ab8cedd12d61ece7f47cbe604ce67ef5c Mon Sep 17 00:00:00 2001 From: Pranav Date: Wed, 23 Oct 2024 13:18:29 +0530 Subject: [PATCH 14/16] Fixed wrong linewidth get --- lib/matplotlib/backends/backend_svg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/backends/backend_svg.py b/lib/matplotlib/backends/backend_svg.py index 2f722cc8cb7f..2193dc6b6cdc 100644 --- a/lib/matplotlib/backends/backend_svg.py +++ b/lib/matplotlib/backends/backend_svg.py @@ -500,7 +500,7 @@ def _get_hatch(self, gc, rgbFace): edge = gc.get_hatch_color() if edge is not None: edge = tuple(edge) - lw = gc._linewidth + lw = gc.get_hatch_linewidth() dictkey = (gc.get_hatch(), rgbFace, edge, lw) oid = self._hatchd.get(dictkey) if oid is None: From 4eb5b87038927c58eb6624085fce44ed65e92134 Mon Sep 17 00:00:00 2001 From: Pranav Date: Thu, 31 Oct 2024 07:59:43 +0530 Subject: [PATCH 15/16] Passed linewidth instead of gc while creating hatches --- lib/matplotlib/backends/backend_ps.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index bfe3ad59702e..a58be976117b 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -505,12 +505,12 @@ def set_font(self, fontname, fontsize, store=True): self.fontname = fontname self.fontsize = fontsize - def create_hatch(self, hatch, gc=None): + def create_hatch(self, hatch, lw): sidelen = 72 if hatch in self._hatches: return self._hatches[hatch] name = 'H%d' % len(self._hatches) - linewidth = gc.get_hatch_linewidth() + linewidth = lw pageheight = self.height * 72 self._pswriter.write(f"""\ << /PatternType 1 @@ -933,7 +933,7 @@ def _draw_ps(self, ps, gc, rgbFace, *, fill=True, stroke=True): write("grestore\n") if hatch: - hatch_name = self.create_hatch(hatch, gc) + hatch_name = self.create_hatch(hatch, gc.get_hatch_linewidth()) write("gsave\n") write(_nums_to_str(*gc.get_hatch_color()[:3])) write(f" {hatch_name} setpattern fill grestore\n") From b67df775aa4ad0d32ad69749ec8374aad109a027 Mon Sep 17 00:00:00 2001 From: Pranav Date: Thu, 31 Oct 2024 08:46:00 +0530 Subject: [PATCH 16/16] Dropped recurring linewidth parameter --- lib/matplotlib/backends/backend_ps.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index a58be976117b..78473afa0f06 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -505,12 +505,11 @@ def set_font(self, fontname, fontsize, store=True): self.fontname = fontname self.fontsize = fontsize - def create_hatch(self, hatch, lw): + def create_hatch(self, hatch, linewidth): sidelen = 72 if hatch in self._hatches: return self._hatches[hatch] name = 'H%d' % len(self._hatches) - linewidth = lw pageheight = self.height * 72 self._pswriter.write(f"""\ << /PatternType 1