[librsvg: 6/9] clip_to_node - Use a new function BoundingBox.rect_to_transform
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 6/9] clip_to_node - Use a new function BoundingBox.rect_to_transform
- Date: Thu, 30 Apr 2020 21:04:46 +0000 (UTC)
commit 89f21a75463dedfdf5f485e76d74b8b6ea4324ff
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 | 51 +++++++++++++--------------------------
2 files changed, 48 insertions(+), 34 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 f550abf1..c04cd7c7 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -340,44 +340,27 @@ impl DrawingCtx {
let node = clip_node.as_ref().unwrap();
let units = borrow_element_as!(node, ClipPath).get_units();
- 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 cascaded = CascadedValues::new_from_node(node);
-
- let transform = if units == CoordUnits::ObjectBoundingBox {
- let bbox_rect = bbox.rect.as_ref().unwrap();
-
- Transform::new_unchecked(
- bbox_rect.width(),
- 0.0,
- 0.0,
- bbox_rect.height(),
- bbox_rect.x0,
- bbox_rect.y0,
- )
- } else {
- Transform::identity()
- };
+ if let Ok(transform) = bbox.rect_to_transform(units) {
+ let cascaded = CascadedValues::new_from_node(node);
- self.with_saved_transform(Some(transform), &mut |dc| {
- let cr = dc.get_cairo_context();
+ 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
- let res = node.draw_children(acquired_nodes, &cascaded, dc, true);
+ // here we don't push a layer because we are clipping
+ let res = node.draw_children(acquired_nodes, &cascaded, dc, true);
- cr.clip();
+ cr.clip();
- 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(()))
+ 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(()))
+ } else {
+ Ok(())
+ }
}
fn generate_cairo_mask(
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]