Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8fc0ba4

Browse filesBrowse files
committed
Support hatching in cairo backends.
Direct transposition of the mplcairo implementation (except for the lack of proper stacking, which was already present for the alpha state so it's not really "worse"), itself translated from the agg implementation.
1 parent 365c950 commit 8fc0ba4
Copy full SHA for 8fc0ba4

File tree

Expand file treeCollapse file tree

1 file changed

+42
-13
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+42
-13
lines changed

‎lib/matplotlib/backends/backend_cairo.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_cairo.py
+42-13Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@
3434
from matplotlib.transforms import Affine2D
3535

3636

37+
def _set_rgba(ctx, color, alpha, forced_alpha):
38+
if len(color) == 3 or forced_alpha:
39+
ctx.set_source_rgba(*color[:3], alpha)
40+
else:
41+
ctx.set_source_rgba(*color)
42+
43+
3744
def _append_path(ctx, path, transform, clip=None):
3845
for points, code in path.iter_segments(
3946
transform, remove_nans=True, clip=clip):
@@ -100,13 +107,11 @@ def set_context(self, ctx):
100107
self.gc.ctx = ctx
101108
self.width, self.height = size
102109

103-
def _fill_and_stroke(self, ctx, fill_c, alpha, alpha_overrides):
110+
@staticmethod
111+
def _fill_and_stroke(ctx, fill_c, alpha, alpha_overrides):
104112
if fill_c is not None:
105113
ctx.save()
106-
if len(fill_c) == 3 or alpha_overrides:
107-
ctx.set_source_rgba(fill_c[0], fill_c[1], fill_c[2], alpha)
108-
else:
109-
ctx.set_source_rgba(fill_c[0], fill_c[1], fill_c[2], fill_c[3])
114+
_set_rgba(ctx, fill_c, alpha, alpha_overrides)
110115
ctx.fill_preserve()
111116
ctx.restore()
112117
ctx.stroke()
@@ -122,8 +127,31 @@ def draw_path(self, gc, path, transform, rgbFace=None):
122127
+ Affine2D().scale(1, -1).translate(0, self.height))
123128
ctx.new_path()
124129
_append_path(ctx, path, transform, clip)
125-
self._fill_and_stroke(
126-
ctx, rgbFace, gc.get_alpha(), gc.get_forced_alpha())
130+
if rgbFace is not None:
131+
ctx.save()
132+
_set_rgba(ctx, rgbFace, gc.get_alpha(), gc.get_forced_alpha())
133+
ctx.fill_preserve()
134+
ctx.restore()
135+
hatch_path = gc.get_hatch_path()
136+
if hatch_path:
137+
dpi = int(self.dpi)
138+
hatch_surface = ctx.get_target().create_similar(
139+
cairo.Content.COLOR_ALPHA, dpi, dpi)
140+
hatch_ctx = cairo.Context(hatch_surface)
141+
_append_path(hatch_ctx, hatch_path,
142+
Affine2D().scale(dpi, -dpi).translate(0, dpi),
143+
None)
144+
hatch_ctx.set_line_width(self.points_to_pixels(gc.get_hatch_linewidth()))
145+
hatch_ctx.set_source_rgba(*gc.get_hatch_color())
146+
hatch_ctx.fill_preserve()
147+
hatch_ctx.stroke()
148+
hatch_pattern = cairo.SurfacePattern(hatch_surface)
149+
hatch_pattern.set_extend(cairo.Extend.REPEAT)
150+
ctx.save()
151+
ctx.set_source(hatch_pattern)
152+
ctx.fill_preserve()
153+
ctx.restore()
154+
ctx.stroke()
127155

128156
def draw_markers(self, gc, marker_path, marker_trans, path, transform,
129157
rgbFace=None):
@@ -267,8 +295,13 @@ def get_text_width_height_descent(self, s, prop, ismath):
267295
def new_gc(self):
268296
# docstring inherited
269297
self.gc.ctx.save()
298+
# FIXME: The following doesn't properly implement a stack-like behavior
299+
# and relies instead on the (non-guaranteed) fact that artists never
300+
# rely on nesting gc states, so directly resetting the attributes (IOW
301+
# a single-level stack) is enough.
270302
self.gc._alpha = 1
271303
self.gc._forced_alpha = False # if True, _alpha overrides A from RGBA
304+
self.gc._hatch = None
272305
return self.gc
273306

274307
def points_to_pixels(self, points):
@@ -298,12 +331,8 @@ def restore(self):
298331

299332
def set_alpha(self, alpha):
300333
super().set_alpha(alpha)
301-
_alpha = self.get_alpha()
302-
rgb = self._rgb
303-
if self.get_forced_alpha():
304-
self.ctx.set_source_rgba(rgb[0], rgb[1], rgb[2], _alpha)
305-
else:
306-
self.ctx.set_source_rgba(rgb[0], rgb[1], rgb[2], rgb[3])
334+
_set_rgba(
335+
self.ctx, self._rgb, self.get_alpha(), self.get_forced_alpha())
307336

308337
def set_antialiased(self, b):
309338
self.ctx.set_antialias(

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.