@@ -109,6 +109,23 @@ def set_width_height(self, width, height):
109109 # font transform?
110110
111111
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+
112129 def _fill_and_stroke (self , ctx , fill_c , alpha ):
113130 if fill_c is not None :
114131 ctx .save ()
@@ -120,7 +137,6 @@ def _fill_and_stroke (self, ctx, fill_c, alpha):
120137 ctx .restore ()
121138 ctx .stroke ()
122139
123-
124140 @staticmethod
125141 def convert_path (ctx , path , transform ):
126142 for points , code in path .iter_segments (transform ):
@@ -143,13 +159,17 @@ def draw_path(self, gc, path, transform, rgbFace=None):
143159 raise ValueError ("The Cairo backend can not draw paths longer than 18980 points." )
144160
145161 ctx = gc .ctx
162+ ctx .save ()
163+ self ._do_clip (ctx , gc ._cliprect , gc ._clippath )
164+
146165 transform = transform + \
147166 Affine2D ().scale (1.0 , - 1.0 ).translate (0 , self .height )
148167
149168 ctx .new_path ()
150169 self .convert_path (ctx , path , transform )
151170
152171 self ._fill_and_stroke (ctx , rgbFace , gc .get_alpha ())
172+ ctx .restore ()
153173
154174 def draw_image (self , x , y , im , bbox , clippath = None , clippath_trans = None ):
155175 # bbox - not currently used
@@ -162,9 +182,16 @@ def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
162182 buf , cairo .FORMAT_ARGB32 , cols , rows , cols * 4 )
163183 # function does not pass a 'gc' so use renderer.ctx
164184 ctx = self .ctx
185+ ctx .save ()
186+ if clippath is not None :
187+ tpath = clippath_trans .transform_path (clippath )
188+ ctx .new_path ()
189+ RendererCairo .convert_path (ctx , tpath )
190+ ctx .clip ()
165191 y = self .height - y - rows
166192 ctx .set_source_surface (surface , x , y )
167193 ctx .paint ()
194+ ctx .restore ()
168195
169196 im .flipud_out ()
170197
@@ -322,29 +349,9 @@ def set_capstyle(self, cs):
322349
323350 def set_clip_rectangle (self , rectangle ):
324351 self ._cliprect = rectangle
325- if rectangle is None :
326- return
327-
328- x ,y ,w ,h = rectangle .bounds
329- # pixel-aligned clip-regions are faster
330- x ,y ,w ,h = round (x ), round (y ), round (w ), round (h )
331- ctx = self .ctx
332- ctx .new_path ()
333- ctx .rectangle (x , self .renderer .height - h - y , w , h )
334- ctx .clip ()
335- # Alternative: just set _cliprect here and actually set cairo clip rect
336- # in fill_and_stroke() inside ctx.save() ... ctx.restore()
337-
338352
339353 def set_clip_path (self , path ):
340- if path is not None :
341- tpath , affine = path .get_transformed_path_and_affine ()
342- ctx = self .ctx
343- ctx .new_path ()
344- affine = affine + Affine2D ().scale (1.0 , - 1.0 ).translate (0.0 , self .renderer .height )
345- RendererCairo .convert_path (ctx , path , affine )
346- ctx .clip ()
347-
354+ self ._clippath = path
348355
349356 def set_dashes (self , offset , dashes ):
350357 self ._dashes = offset , dashes
0 commit comments