@@ -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 , tpath ):
126142 for points , code in tpath .iter_segments ():
@@ -144,6 +160,9 @@ def draw_path(self, gc, path, transform, rgbFace=None):
144160 raise ValueError ("The Cairo backend can not draw paths longer than 18980 points." )
145161
146162 ctx = gc .ctx
163+ ctx .save ()
164+ self ._do_clip (ctx , gc ._cliprect , gc ._clippath )
165+
147166 transform = transform + \
148167 Affine2D ().scale (1.0 , - 1.0 ).translate (0 , self .height )
149168 tpath = transform .transform_path (path )
@@ -152,6 +171,7 @@ def draw_path(self, gc, path, transform, rgbFace=None):
152171 self .convert_path (ctx , tpath )
153172
154173 self ._fill_and_stroke (ctx , rgbFace , gc .get_alpha ())
174+ ctx .restore ()
155175
156176 def draw_image (self , x , y , im , bbox , clippath = None , clippath_trans = None ):
157177 # bbox - not currently used
@@ -164,9 +184,16 @@ def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
164184 buf , cairo .FORMAT_ARGB32 , cols , rows , cols * 4 )
165185 # function does not pass a 'gc' so use renderer.ctx
166186 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 ()
167193 y = self .height - y - rows
168194 ctx .set_source_surface (surface , x , y )
169195 ctx .paint ()
196+ ctx .restore ()
170197
171198 im .flipud_out ()
172199
@@ -324,30 +351,9 @@ def set_capstyle(self, cs):
324351
325352 def set_clip_rectangle (self , rectangle ):
326353 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-
340354
341355 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
351357
352358 def set_dashes (self , offset , dashes ):
353359 self ._dashes = offset , dashes
0 commit comments