[librsvg: 2/3] drawing_ctx: replace clip() method with a with_clip_rect() method



commit 499aea3a781e501e94aadf15dcea78f8cef60339
Author: Paolo Borelli <pborelli gnome org>
Date:   Tue Jan 21 09:59:38 2020 +0100

    drawing_ctx: replace clip() method with a with_clip_rect() method
    
    The clip method was just a helper, but it is confusing because it
    does not save/restore the cairo state. Just use cairo internally
    to the drawing context and expose a with_clip_rect method in the
    public api.

 rsvg_internals/src/drawing_ctx.rs | 60 ++++++++++++++++++++++++++++++---------
 rsvg_internals/src/marker.rs      | 27 +++++++++---------
 2 files changed, 59 insertions(+), 28 deletions(-)
---
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 64cfbbb8..cb3f9a4c 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -296,8 +296,16 @@ impl DrawingCtx {
         preserve_aspect_ratio: AspectRatio,
         clip_mode: Option<ClipMode>,
     ) -> Option<ViewParams> {
+        let cr = self.get_cairo_context();
+
         if let Some(ClipMode::ClipToViewport) = clip_mode {
-            self.clip(viewport);
+            cr.rectangle(
+                viewport.x0,
+                viewport.y0,
+                viewport.width(),
+                viewport.height(),
+            );
+            cr.clip();
         }
 
         preserve_aspect_ratio
@@ -307,7 +315,8 @@ impl DrawingCtx {
 
                 if let Some(vbox) = vbox {
                     if let Some(ClipMode::ClipToVbox) = clip_mode {
-                        self.clip(vbox.0);
+                        cr.rectangle(vbox.0.x0, vbox.0.y0, vbox.0.width(), vbox.0.height());
+                        cr.clip();
                     }
 
                     Some(self.push_view_box(vbox.0.width(), vbox.0.height()))
@@ -423,13 +432,21 @@ impl DrawingCtx {
 
             let bbtransform = Transform::new(bb_w, 0.0, 0.0, bb_h, bb_x, bb_y);
 
-            self.push_cairo_context(mask_cr);
-
-            if mask_units == CoordUnits::ObjectBoundingBox {
-                self.clip(bbtransform.transform_rect(&mask_rect));
+            let clip_rect = if mask_units == CoordUnits::ObjectBoundingBox {
+                bbtransform.transform_rect(&mask_rect)
             } else {
-                self.clip(mask_rect);
-            }
+                mask_rect
+            };
+
+            mask_cr.rectangle(
+                clip_rect.x0,
+                clip_rect.y0,
+                clip_rect.width(),
+                clip_rect.height(),
+            );
+            mask_cr.clip();
+
+            self.push_cairo_context(mask_cr);
 
             let _params = if mask.get_content_units() == CoordUnits::ObjectBoundingBox {
                 self.get_cairo_context().transform(bbtransform.into());
@@ -644,6 +661,27 @@ impl DrawingCtx {
         }
     }
 
+    /// if a rectangle is specified, clips and runs the draw_fn, otherwise simply run the draw_fn
+    pub fn with_clip_rect(
+        &mut self,
+        clip: Option<Rect>,
+        draw_fn: &mut dyn FnMut(&mut DrawingCtx) -> Result<BoundingBox, RenderingError>,
+    ) -> Result<BoundingBox, RenderingError> {
+        if let Some(rect) = clip {
+            self.cr.save();
+            self.cr.rectangle(rect.x0, rect.y0, rect.width(), rect.height());
+            self.cr.clip();
+        }
+
+        let res = draw_fn(self);
+
+        if clip.is_some() {
+            self.cr.restore();
+        }
+
+        res
+    }
+
     /// Saves the current Cairo context, runs the draw_fn, and restores the context
     pub fn with_saved_cr(
         &mut self,
@@ -907,12 +945,6 @@ impl DrawingCtx {
         }
     }
 
-    pub fn clip(&self, rect: Rect) {
-        let cr = self.get_cairo_context();
-        cr.rectangle(rect.x0, rect.y0, rect.width(), rect.height());
-        cr.clip();
-    }
-
     pub fn get_snapshot(
         &self,
         width: i32,
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index b5d6d75b..001336fe 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -153,21 +153,20 @@ impl Marker {
             -self.ref_y.normalize(&values, &params),
         );
 
-        draw_ctx.with_saved_cr(&mut |dc| {
-            let cr = dc.get_cairo_context();
-
-            cr.transform(transform.into());
-
-            if !values.is_overflow() {
-                let clip_rect = self
-                    .vbox
-                    .map_or_else(|| Rect::from_size(marker_width, marker_height), |vb| vb.0);
-
-                dc.clip(clip_rect);
-            }
+        let clip = if values.is_overflow() {
+            None
+        } else {
+            Some(
+                self.vbox
+                    .map_or_else(|| Rect::from_size(marker_width, marker_height), |vb| vb.0),
+            )
+        };
 
-            dc.with_discrete_layer(node, values, clipping, &mut |dc| {
-                node.draw_children(&cascaded, dc, clipping)
+        draw_ctx.with_saved_transform(Some(transform), &mut |dc| {
+            dc.with_clip_rect(clip, &mut |dc| {
+                dc.with_discrete_layer(node, values, clipping, &mut |dc| {
+                    node.draw_children(&cascaded, dc, clipping)
+                })
             })
         })
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]