8000 Enables setting hatch linewidth in Patches and Collections, also fixe… · matplotlib/matplotlib@c52cb41 · GitHub
[go: up one dir, main page]

Skip to content

Commit c52cb41

Browse files
authored
Enables setting hatch linewidth in Patches and Collections, also fixes setting hatch linewidth by rcParams (#28048)
1 parent e8654e1 commit c52cb41

File tree

12 files changed

+103
-27
lines changed

12 files changed

+103
-27
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``PdfFile.hatchPatterns``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
... is deprecated.

lib/matplotlib/backend_bases.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,10 @@ def get_hatch_linewidth(self):
961961
"""Get the hatch linewidth."""
962962
return self._hatch_linewidth
963963

964+
def set_hatch_linewidth(self, hatch_linewidth):
965+
"""Set the hatch linewidth."""
966+
self._hatch_linewidth = hatch_linewidth
967+
964968
def get_sketch_params(self):
965969
"""
966970
Return the sketch parameters for the artist.

lib/matplotlib/backend_bases.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ class GraphicsContextBase:
167167
def get_hatc 6D40 h_color(self) -> ColorType: ...
168168
def set_hatch_color(self, hatch_color: ColorType) -> None: ...
169169
def get_hatch_linewidth(self) -> float: ...
170+
def set_hatch_linewidth(self, hatch_linewidth: float) -> None: ...
170171
def get_sketch_params(self) -> tuple[float, float, float] | None: ...
171172
def set_sketch_params(
172173
self,

lib/matplotlib/backends/backend_pdf.py

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ def __init__(self, filename, metadata=None):
731731
self._soft_mask_states = {}
732732
self._soft_mask_seq = (Name(f'SM{i}') for i in itertools.count(1))
733733
self._soft_mask_groups = []
734-
self.hatchPatterns = {}
734+
self._hatch_patterns = {}
735735
self._hatch_pattern_seq = (Name(f'H{i}') for i in itertools.count(1))
736736
self.gouraudTriangles = []
737737

@@ -1534,26 +1534,29 @@ def _write_soft_mask_groups(self):
15341534

15351535
def hatchPattern(self, hatch_style):
15361536
# The colors may come in as numpy arrays, which aren't hashable
1537-
if hatch_style is not None:
1538-
edge, face, hatch = hatch_style
1539-
if edge is not None:
1540-
edge = tuple(edge)
1541-
if face is not None:
1542-
face = tuple(face)
1543-
hatch_style = (edge, face, hatch)
1544-
1545-
pattern = self.hatchPatterns.get(hatch_style, None)
1537+
edge, face, hatch, lw = hatch_style
1538+
if edge is not None:
1539+
edge = tuple(edge)
1540+
if face is not None:
1541+
face = tuple(face)
1542+
hatch_style = (edge, face, hatch, lw)
1543+
1544+
pattern = self._hatch_patterns.get(hatch_style, None)
15461545
if pattern is not None:
15471546
return pattern
15481547

15491548
name = next(self._hatch_pattern_seq)
1550-
self.hatchPatterns[hatch_style] = name
1549+
self._hatch_patterns[hatch_style] = name
15511550
return name
15521551

1552+
hatchPatterns = _api.deprecated("3.10")(property(lambda self: {
1553+
k: (e, f, h) for k, (e, f, h, l) in self._hatch_patterns.items()
1554+
}))
1555+
15531556
def writeHatches(self):
15541557
hatchDict = dict()
15551558
sidelen = 72.0
1556-
for hatch_style, name in self.hatchPatterns.items():
1559+
for hatch_style, name in self._hatch_patterns.items():
15571560
ob = self.reserveObject('hatch pattern')
15581561
hatchDict[name] = ob
15591562
res = {'Procsets':
@@ -1568,7 +1571,7 @@ def writeHatches(self):
15681571
# Change origin to match Agg at top-left.
15691572
'Matrix': [1, 0, 0, 1, 0, self.height * 72]})
15701573

1571-
stroke_rgb, fill_rgb, hatch = hatch_style
1574+
stroke_rgb, fill_rgb, hatch, lw = hatch_style
15721575
self.output(stroke_rgb[0], stroke_rgb[1], stroke_rgb[2],
15731576
Op.setrgb_stroke)
15741577
if fill_rgb is not None:
@@ -1577,7 +1580,7 @@ def writeHatches(self):
15771580
0, 0, sidelen, sidelen, Op.rectangle,
15781581
Op.fill)
15791582

1580-
self.output(mpl.rcParams['hatch.linewidth'], Op.setlinewidth)
1583+
self.output(lw, Op.setlinewidth)
15811584

15821585
self.output(*self.pathOperations(
15831586
Path.hatch(hatch),
@@ -2508,14 +2511,14 @@ def alpha_cmd(self, alpha, forced, effective_alphas):
25082511
name = self.file.alphaState(effective_alphas)
25092512
return [name, Op.setgstate]
25102513

2511-
def hatch_cmd(self, hatch, hatch_color):
2514+
def hatch_cmd(self, hatch, hatch_color, hatch_linewidth):
25122515
if not hatch:
25132516
if self._fillcolor is not None:
25142517
return self.fillcolor_cmd(self._fillcolor)
25152518
else:
25162519
return [Name('DeviceRGB'), Op.setcolorspace_nonstroke]
25172520
else:
2518-
hatch_style = (hatch_color, self._fillcolor, hatch)
2521+
hatch_style = (hatch_color, self._fillcolor, hatch, hatch_linewidth)
25192522
name = self.file.hatchPattern(hatch_style)
25202523
return [Name('Pattern'), Op.setcolorspace_nonstroke,
25212524
name, Op.setcolor_nonstroke]
@@ -2580,8 +2583,8 @@ def clip_cmd(self, cliprect, clippath):
25802583
(('_dashes',), dash_cmd),
25812584
(('_rgb',), rgb_cmd),
25822585
# must come after fillcolor and rgb
2583-
(('_hatch', '_hatch_color'), hatch_cmd),
2584-
)
2586+
(('_hatch', '_hatch_color', '_hatch_linewidth'), hatch_cmd),
2587+
)
25852588

25862589
def delta(self, other):
25872590
"""
@@ -2609,11 +2612,11 @@ def delta(self, other):
26092612
break
26102613

26112614
# Need to update hatching if we also updated fillcolor
2612-
if params == ('_hatch', '_hatch_color') and fill_performed:
2615+
if cmd.__name__ == 'hatch_cmd' and fill_performed:
26132616
different = True
26142617

26152618
if different:
2616-
if params == ('_fillcolor',):
2619+
if cmd.__name__ == 'fillcolor_cmd':
26172620
fill_performed = True
26182621
theirs = [getattr(other, p) for p in params]
26192622
cmds.extend(cmd(self, *theirs))

lib/matplotlib/backends/backend_ps.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -505,12 +505,11 @@ def set_font(self, fontname, fontsize, store=True):
505505
self.fontname = fontname
506506
self.fontsize = fontsize
507507

508-
def create_hatch(self, hatch):
508+
def create_hatch(self, hatch, linewidth):
509509
sidelen = 72
510510
if hatch in self._hatches:
511511
return self._hatches[hatch]
512512
name = 'H%d' % len(self._hatches)
513-
linewidth = mpl.rcParams['hatch.linewidth']
514513
pageheight = self.height * 72
515514
self._pswriter.write(f"""\
516515
<< /PatternType 1
@@ -933,7 +932,7 @@ def _draw_ps(self, ps, gc, rgbFace, *, fill=True, stroke=True):
933932
write("grestore\n")
934933

935934
if hatch:
936-
hatch_name = self.create_hatch(hatch)
935+
hatch_name = self.create_hatch(hatch, gc.get_hatch_linewidth())
937936
write("gsave\n")
938937
write(_nums_to_str(*gc.get_hatch_color()[:3]))
939938
write(f" {hatch_name} setpattern fill grestore\n")

lib/matplotlib/backends/backend_svg.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -500,11 +500,12 @@ def _get_hatch(self, gc, rgbFace):
500500
edge = gc.get_hatch_color()
501501
if edge is not None:
502502
edge = tuple(edge)
503-
dictkey = (gc.get_hatch(), rgbFace, edge)
503+
lw = gc.get_hatch_linewidth()
504+
dictkey = (gc.get_hatch(), rgbFace, edge, lw)
504505
oid = self._hatchd.get(dictkey)
505506
if oid is None:
506507
oid = self._make_id('h', dictkey)
507-
self._hatchd[dictkey] = ((gc.get_hatch_path(), rgbFace, edge), oid)
508+
self._hatchd[dictkey] = ((gc.get_hatch_path(), rgbFace, edge, lw), oid)
508509
else:
509510
_, oid = oid
510511
return oid
@@ -515,7 +516,7 @@ def _write_hatches(self):
515516
HATCH_SIZE = 72
516517
writer = self.writer
517518
writer.start('defs')
518-
for (path, face, stroke), oid in self._hatchd.values():
519+
for (path, face, stroke, lw), oid in self._hatchd.values():
519520
writer.start(
520521
'pattern',
521522
id=oid,
@@ -539,7 +540,7 @@ def _write_hatches(self):
539540
hatch_style = {
540541
'fill': rgb2hex(stroke),
541542
'stroke': rgb2hex(stroke),
542-
'stroke-width': str(mpl.rcParams['hatch.linewidth']),
543+
'stroke-width': str(lw),
543544
'stroke-linecap': 'butt',
544545
'stroke-linejoin': 'miter'
545546
}

lib/matplotlib/collections.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ def __init__(self, *,
175175
self._edge_is_mapped = None
176176
self._mapped_colors = None # calculated in update_scalarmappable
177177
self._hatch_color = mcolors.to_rgba(mpl.rcParams['hatch.color'])
178+
self._hatch_linewidth = mpl.rcParams['hatch.linewidth']
178179
self.set_facecolor(facecolors)
179180
self.set_edgecolor(edgecolors)
180181
self.set_linewidth(linewidths)
@@ -365,6 +366,7 @@ def draw(self, renderer):
365366
if self._hatch:
366367
gc.set_hatch(self._hatch)
367368
gc.set_hatch_color(self._hatch_color)
369+
gc.set_hatch_linewidth(self._hatch_linewidth)
368370

369371
if self.get_sketch_params() is not None:
370372
gc.set_sketch_params(*self.get_sketch_params())
@@ -543,6 +545,14 @@ def get_hatch(self):
543545
"""Return the current hatching pattern."""
544546
return self._hatch
545547

548+
def set_hatch_linewidth(self, lw):
549+
"""Set the hatch linewidth."""
550+
self._hatch_linewidth = lw
551+
552+
def get_hatch_linewidth(self):
553+
"""Return the hatch linewidth."""
554+
return self._hatch_linewidth
555+
546556
def set_offsets(self, offsets):
547557
"""
548558
Set the offsets for the collection.

lib/matplotlib/collections.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class Collection(colorizer.ColorizingArtist):
4949
def get_urls(self) -> Sequence[str | None]: ...
5050
def set_hatch(self, hatch: str) -> None: ...
5151
def get_hatch(self) -> str: ...
52+
def set_hatch_linewidth(self, lw: float) -> None: ...
53+
def get_hatch_linewidth(self) -> float: ...
5254
def set_offsets(self, offsets: ArrayLike) -> None: ...
5355
def get_offsets(self) -> ArrayLike: ...
5456
def set_linewidth(self, lw: float | Sequence[float]) -> None: ...

lib/matplotlib/patches.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def __init__(self, *,
7272
joinstyle = JoinStyle.miter
7373

7474
self._hatch_color = colors.to_rgba(mpl.rcParams['hatch.color'])
75+
self._hatch_linewidth = mpl.rcParams['hatch.linewidth']
7576
self._fill = bool(fill) # needed for set_facecolor call
7677
if color is not None:
7778
if edgecolor is not None or facecolor is not None:
@@ -571,6 +572,14 @@ def get_hatch(self):
571572
"""Return the hatching pattern."""
572573
return self._hatch
573574

575+
def set_hatch_linewidth(self, lw):
576+
"""Set the hatch linewidth."""
577+
self._hatch_linewidth = lw
578+
579+
def get_hatch_linewidth(self):
580+
"""Return the hatch linewidth."""
581+
return self._hatch_linewidth
582+
574583
def _draw_paths_with_artist_properties(
575584
self, renderer, draw_path_args_list):
576585
"""
@@ -605,6 +614,7 @@ def _draw_paths_with_artist_properties(
605614
if self._hatch:
606615
gc.set_hatch(self._hatch)
607616
gc.set_hatch_color(self._hatch_color)
617+
gc.set_hatch_linewidth(self._hatch_linewidth)
608618

609619
if self.get_sketch_params() is not None:
610620
gc.set_sketch_params(*self.get_sketch_params())

lib/matplotlib/patches.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ class Patch(artist.Artist):
5959
def set_joinstyle(self, s: JoinStyleType) -> None: ...
6060
def get_joinstyle(self) -> Literal["miter", "round", "bevel"]: ...
6161
def set_hatch(self, hatch: str) -> None: ...
62+
def set_hatch_linewidth(self, lw: float) -> None: ...
63+
def get_hatch_linewidth(self) -> float: ...
6264
def get_hatch(self) -> str: ...
6365
def get_path(self) -> Path: ...
6466

0 commit comments

Comments
 (0)
0