[librsvg/librsvg-2.48] clip_to_node - Use a new function BoundingBox.rect_to_transform



commit a12435fd60dcf5f5fcd9ca4997ada7fdc8ad5821
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Apr 29 19:53:54 2020 -0500

    clip_to_node - Use a new function BoundingBox.rect_to_transform
    
    This checks the bbox.rect and the given CoordUnits, so that
    ObjectBoundingBox with an empty bbox.rect will not produce an invalid
    transform.

 rsvg_internals/src/bbox.rs        | 31 +++++++++++++++++++++++++++++++
 rsvg_internals/src/drawing_ctx.rs | 38 +++++++++++---------------------------
 2 files changed, 42 insertions(+), 27 deletions(-)
---
diff --git a/rsvg_internals/src/bbox.rs b/rsvg_internals/src/bbox.rs
index 311ebafc..46dba3a0 100644
--- a/rsvg_internals/src/bbox.rs
+++ b/rsvg_internals/src/bbox.rs
@@ -1,5 +1,6 @@
 //! Bounding boxes that know their coordinate space.
 
+use crate::coord_units::CoordUnits;
 use crate::rect::Rect;
 use crate::transform::Transform;
 
@@ -69,6 +70,36 @@ impl BoundingBox {
     pub fn ink_rect_is_empty(&self) -> bool {
         self.ink_rect.map(|r| r.is_empty()).unwrap_or(true)
     }
+
+    /// Creates a transform to map to the `self.rect`.
+    ///
+    /// This depends on a `CoordUnits` parameter.  When this is
+    /// `CoordUnits::ObjectBoundingBox`, the bounding box must not be
+    /// empty, since the calling code would then not have a usable
+    /// size to work with.  In that case, if the bbox is empty, this
+    /// function returns `Err(())`.
+    ///
+    /// Usually calling code can simply ignore the action it was about
+    /// to take if this function returns an error.
+    pub fn rect_to_transform(&self, units: CoordUnits) -> Result<Transform, ()> {
+        match units {
+            CoordUnits::UserSpaceOnUse => Ok(Transform::identity()),
+            CoordUnits::ObjectBoundingBox => {
+                if self.rect_is_empty() {
+                    Err(())
+                } else {
+                    let r = self.rect.as_ref().unwrap();
+                    let t = Transform::new_unchecked(r.width(), 0.0, 0.0, r.height(), r.x0, r.y0);
+
+                    if t.is_invertible() {
+                        Ok(t)
+                    } else {
+                        Err(())
+                    }
+                }
+            }
+        }
+    }
 }
 
 fn combine_rects(
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 53467413..db6e30f0 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -334,33 +334,17 @@ impl DrawingCtx {
         acquired_nodes: &mut AcquiredNodes,
         bbox: &BoundingBox,
     ) -> Result<(), RenderingError> {
-        if let Some(node) = clip_node {
-            let units = node.borrow().get_impl::<ClipPath>().get_units();
+        if clip_node.is_none() {
+            return Ok(());
+        }
 
-            if units == CoordUnits::ObjectBoundingBox && bbox.rect.is_none() {
-                // The node being clipped is empty / doesn't have a
-                // bounding box, so there's nothing to clip!
-                return Ok(());
-            }
+        let node = clip_node.as_ref().unwrap();
+        let units = node.borrow().get_impl::<ClipPath>().get_units();
 
+        if let Ok(transform) = bbox.rect_to_transform(units) {
             let cascaded = CascadedValues::new_from_node(node);
 
-            let transform = if units == CoordUnits::ObjectBoundingBox {
-                let bbox_rect = bbox.rect.as_ref().unwrap();
-
-                Some(Transform::new_unchecked(
-                    bbox_rect.width(),
-                    0.0,
-                    0.0,
-                    bbox_rect.height(),
-                    bbox_rect.x0,
-                    bbox_rect.y0,
-                ))
-            } else {
-                Transform::identity()
-            };
-
-            self.with_saved_transform(transform, &mut |dc| {
+            self.with_saved_transform(Some(transform), &mut |dc| {
                 let cr = dc.get_cairo_context();
 
                 // here we don't push a layer because we are clipping
@@ -371,10 +355,10 @@ impl DrawingCtx {
                 res
             })
             .and_then(|_bbox|
-                // Clipping paths do not contribute to bounding boxes (they should,
-                // but we need Real Computational Geometry(tm), so ignore the
-                // bbox from the clip path.
-                Ok(()))
+                         // Clipping paths do not contribute to bounding boxes (they should,
+                         // but we need Real Computational Geometry(tm), so ignore the
+                         // bbox from the clip path.
+                         Ok(()))
         } else {
             Ok(())
         }


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