@@ -109,6 +109,23 @@ def set_width_height(self, width, height):
109
109
# font transform?
110
110
111
111
112
+ def _do_clip (self , ctx , cliprect , clippath ):
113
+ if cliprect is not None :
114
+ x ,y ,w ,h = cliprect .bounds
115
+ # pixel-aligned clip-regions are faster
116
+ x ,y ,w ,h = round (x ), round (y ), round (w ), round (h )
117
+ ctx .new_path ()
118
+ ctx .rectangle (x , self .height - h - y , w , h )
119
+ ctx .clip ()
120
+
121
+ if clippath is not None :
122
+ tpath , affine = clippath .get_transformed_path_and_affine ()
123
+ ctx .new_path ()
124
+ affine = affine + Affine2D ().scale (1.0 , - 1.0 ).translate (0.0 , self .height )
125
+ tpath = affine .transform_path (tpath )
126
+ RendererCairo .convert_path (ctx , tpath )
127
+ ctx .clip ()
128
+
112
129
def _fill_and_stroke (self , ctx , fill_c , alpha ):
113
130
if fill_c is not None :
114
131
ctx .save ()
@@ -120,7 +137,6 @@ def _fill_and_stroke (self, ctx, fill_c, alpha):
120
137
ctx .restore ()
121
138
ctx .stroke ()
122
139
123
-
124
140
#@staticmethod
125
141
def convert_path (ctx , tpath ):
126
142
for points , code in tpath .iter_segments ():
@@ -144,6 +160,9 @@ def draw_path(self, gc, path, transform, rgbFace=None):
144
160
raise ValueError ("The Cairo backend can not draw paths longer than 18980 points." )
145
161
146
162
ctx = gc .ctx
163
+ ctx .save ()
164
+ self ._do_clip (ctx , gc ._cliprect , gc ._clippath )
165
+
147
166
transform = transform + \
148
167
Affine2D ().scale (1.0 , - 1.0 ).translate (0 , self .height )
149
168
tpath = transform .transform_path (path )
@@ -152,6 +171,7 @@ def draw_path(self, gc, path, transform, rgbFace=None):
152
171
self .convert_path (ctx , tpath )
153
172
154
173
self ._fill_and_stroke (ctx , rgbFace , gc .get_alpha ())
174
+ ctx .restore ()
155
175
156
176
def draw_image (self , x , y , im , bbox , clippath = None , clippath_trans = None ):
157
177
# bbox - not currently used
@@ -164,9 +184,16 @@ def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
164
184
buf , cairo .FORMAT_ARGB32 , cols , rows , cols * 4 )
165
185
# function does not pass a 'gc' so use renderer.ctx
166
186
ctx = self .ctx
187
+ ctx .save ()
188
+ if clippath is not None :
189
+ tpath = clippath_trans .transform_path (clippath )
190
+ ctx .new_path ()
191
+ RendererCairo .convert_path (ctx , tpath )
192
+ ctx .clip ()
167
193
y = self .height - y - rows
168
194
ctx .set_source_surface (surface , x , y )
169
195
ctx .paint ()
196
+ ctx .restore ()
170
197
171
198
im .flipud_out ()
172
199
@@ -324,30 +351,9 @@ def set_capstyle(self, cs):
324
351
325
352
def set_clip_rectangle (self , rectangle ):
326
353
self ._cliprect = rectangle
327
- if rectangle is None :
328
- return
329
-
330
- x ,y ,w ,h = rectangle .bounds
331
- # pixel-aligned clip-regions are faster
332
- x ,y ,w ,h = round (x ), round (y ), round (w ), round (h )
333
- ctx = self .ctx
334
- ctx .new_path ()
335
- ctx .rectangle (x , self .renderer .height - h - y , w , h )
336
- ctx .clip ()
337
- # Alternative: just set _cliprect here and actually set cairo clip rect
338
- # in fill_and_stroke() inside ctx.save() ... ctx.restore()
339
-
340
354
341
355
def set_clip_path (self , path ):
342
- if path is not None :
343
- tpath , affine = path .get_transformed_path_and_affine ()
344
- ctx = self .ctx
345
- ctx .new_path ()
346
- affine = affine + Affine2D ().scale (1.0 , - 1.0 ).translate (0.0 , self .renderer .height )
347
- tpath = affine .transform_path (tpath )
348
- RendererCairo .convert_path (ctx , tpath )
349
- ctx .clip ()
350
-
356
+ self ._clippath = path
351
357
352
358
def set_dashes (self , offset , dashes ):
353
359
self ._dashes = offset , dashes
0 commit comments