[librsvg/rect: 8/10] viewbox: make viewbox a newtype on Rect



commit be70421bd68c69dfd2a9977efa2b5170eae6dca4
Author: Paolo Borelli <pborelli gnome org>
Date:   Sun Dec 8 19:39:03 2019 +0100

    viewbox: make viewbox a newtype on Rect

 librsvg/c_api.rs                    |   8 +--
 librsvg_crate/src/lib.rs            |   7 +--
 rsvg_internals/src/aspect_ratio.rs  | 117 +++++++++++-------------------------
 rsvg_internals/src/drawing_ctx.rs   |  30 +++------
 rsvg_internals/src/filters/image.rs |   6 +-
 rsvg_internals/src/image.rs         |   2 +-
 rsvg_internals/src/marker.rs        |  21 +++----
 rsvg_internals/src/pattern.rs       |  10 +--
 rsvg_internals/src/structure.rs     |  12 ++--
 rsvg_internals/src/viewbox.rs       |  28 +++------
 10 files changed, 79 insertions(+), 162 deletions(-)
---
diff --git a/librsvg/c_api.rs b/librsvg/c_api.rs
index 7acd53e6..e44e6718 100644
--- a/librsvg/c_api.rs
+++ b/librsvg/c_api.rs
@@ -229,10 +229,10 @@ impl From<RsvgRectangle> for cairo::Rectangle {
 impl From<ViewBox> for RsvgRectangle {
     fn from(vb: ViewBox) -> RsvgRectangle {
         RsvgRectangle {
-            x: vb.x,
-            y: vb.y,
-            width: vb.width,
-            height: vb.height,
+            x: vb.0.x0,
+            y: vb.0.y0,
+            width: vb.0.x1 - vb.0.x0,
+            height: vb.0.y1 - vb.0.y0,
         }
     }
 }
diff --git a/librsvg_crate/src/lib.rs b/librsvg_crate/src/lib.rs
index e1833501..1514b884 100644
--- a/librsvg_crate/src/lib.rs
+++ b/librsvg_crate/src/lib.rs
@@ -465,12 +465,7 @@ impl<'a> CairoRenderer<'a> {
         IntrinsicDimensions {
             width: d.width.map(Into::into),
             height: d.height.map(Into::into),
-            vbox: d.vbox.map(|v| cairo::Rectangle {
-                x: v.x,
-                y: v.y,
-                width: v.width,
-                height: v.height,
-            }),
+            vbox: d.vbox.map(|v| cairo::Rectangle::from(v.0)),
         }
     }
 
diff --git a/rsvg_internals/src/aspect_ratio.rs b/rsvg_internals/src/aspect_ratio.rs
index 446ad114..f3d9e0ec 100644
--- a/rsvg_internals/src/aspect_ratio.rs
+++ b/rsvg_internals/src/aspect_ratio.rs
@@ -25,7 +25,6 @@ use std::ops::Deref;
 use cairo;
 
 use crate::error::ValueErrorKind;
-use crate::float_eq_cairo::ApproxEqCairo;
 use crate::parsers::Parse;
 use crate::rect::Rect;
 use crate::viewbox::ViewBox;
@@ -130,18 +129,24 @@ impl AspectRatio {
             None => viewport,
 
             Some(Align { x, y, fit }) => {
-                let w_factor = viewport.width() / vbox.width;
-                let h_factor = viewport.height() / vbox.height;
+                let vb_width = vbox.0.width();
+                let vb_height = vbox.0.height();
+                let vp_width = viewport.width();
+                let vp_height = viewport.height();
+
+                let w_factor = vp_width / vb_width;
+                let h_factor = vp_height / vb_height;
+
                 let factor = match fit {
                     FitMode::Meet => w_factor.min(h_factor),
                     FitMode::Slice => w_factor.max(h_factor),
                 };
 
-                let w = vbox.width * factor;
-                let h = vbox.height * factor;
+                let w = vb_width * factor;
+                let h = vb_height * factor;
 
-                let xpos = x.compute(viewport.x0, viewport.width(), w);
-                let ypos = y.compute(viewport.y0, viewport.height(), h);
+                let xpos = x.compute(viewport.x0, vp_width, w);
+                let ypos = y.compute(viewport.y0, vp_height, h);
 
                 Rect::new(xpos, ypos, xpos + w, ypos + h)
             }
@@ -168,7 +173,7 @@ impl AspectRatio {
         // the preserveAspectRatio attribute is only used if viewBox is specified
         // https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
         if let Some(vbox) = vbox {
-            if vbox.width.approx_eq_cairo(0.0) || vbox.height.approx_eq_cairo(0.0) {
+            if vbox.0.is_empty() {
                 // Width or height of 0 for the viewBox disables rendering of the element
                 // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
                 None
@@ -176,8 +181,8 @@ impl AspectRatio {
                 let r = self.compute(&vbox, viewport);
                 let mut matrix = cairo::Matrix::identity();
                 matrix.translate(r.x0, r.y0);
-                matrix.scale(r.width() / vbox.width, r.height() / vbox.height);
-                matrix.translate(-vbox.x, -vbox.y);
+                matrix.scale(r.width() / vbox.0.width(), r.height() / vbox.0.height());
+                matrix.translate(-vbox.0.x0, -vbox.0.y0);
                 Some(matrix)
             }
         } else {
@@ -345,130 +350,78 @@ mod tests {
 
     #[test]
     fn aligns() {
+        let viewbox = ViewBox::new(Rect::from_size(1.0, 10.0));
+
         let foo = AspectRatio::parse_str("xMinYMin meet").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::from_size(0.1, 1.0));
 
         let foo = AspectRatio::parse_str("xMinYMin slice").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::from_size(10.0, 100.0));
 
         let foo = AspectRatio::parse_str("xMinYMid meet").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::from_size(0.1, 1.0));
 
         let foo = AspectRatio::parse_str("xMinYMid slice").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::new(0.0, -49.5, 10.0, 100.0 - 49.5));
 
         let foo = AspectRatio::parse_str("xMinYMax meet").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::from_size(0.1, 1.0));
 
         let foo = AspectRatio::parse_str("xMinYMax slice").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::new(0.0, -99.0, 10.0, 1.0));
 
         let foo = AspectRatio::parse_str("xMidYMin meet").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::new(4.95, 0.0, 4.95 + 0.1, 1.0));
 
         let foo = AspectRatio::parse_str("xMidYMin slice").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::from_size(10.0, 100.0));
 
         let foo = AspectRatio::parse_str("xMidYMid meet").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::new(4.95, 0.0, 4.95 + 0.1, 1.0));
 
         let foo = AspectRatio::parse_str("xMidYMid slice").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::new(0.0, -49.5, 10.0, 100.0 - 49.5));
 
         let foo = AspectRatio::parse_str("xMidYMax meet").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::new(4.95, 0.0, 4.95 + 0.1, 1.0));
 
         let foo = AspectRatio::parse_str("xMidYMax slice").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::new(0.0, -99.0, 10.0, 1.0));
 
         let foo = AspectRatio::parse_str("xMaxYMin meet").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::new(9.9, 0.0, 10.0, 1.0));
 
         let foo = AspectRatio::parse_str("xMaxYMin slice").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::from_size(10.0, 100.0));
 
         let foo = AspectRatio::parse_str("xMaxYMid meet").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::new(9.9, 0.0, 10.0, 1.0));
 
         let foo = AspectRatio::parse_str("xMaxYMid slice").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::new(0.0, -49.5, 10.0, 100.0 - 49.5));
 
         let foo = AspectRatio::parse_str("xMaxYMax meet").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::new(9.9, 0.0, 10.0, 1.0));
 
         let foo = AspectRatio::parse_str("xMaxYMax slice").unwrap();
-        let foo = foo.compute(
-            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
-            Rect::from_size(10.0, 1.0),
-        );
+        let foo = foo.compute(&viewbox, Rect::from_size(10.0, 1.0));
         assert_rect_equal(&foo, &Rect::new(0.0, -99.0, 10.0, 1.0));
     }
 }
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 8961724e..9fd6c89f 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -115,10 +115,8 @@ impl DrawingCtx {
         // while the code gets refactored not to need special cases for that.
 
         let (rect, vbox) = if measuring {
-            (
-                Rect::from_size(1.0, 1.0),
-                ViewBox::new(0.0, 0.0, 1.0, 1.0),
-            )
+            let unit_rect = Rect::from_size(1.0, 1.0);
+            (unit_rect, ViewBox::new(unit_rect))
         } else {
             // https://www.w3.org/TR/SVG2/coords.html#InitialCoordinateSystem
             //
@@ -132,12 +130,7 @@ impl DrawingCtx {
             // "... the initial viewport coordinate system (and therefore
             // the initial user coordinate system) must have its origin at
             // the top/left of the viewport"
-            let vbox = ViewBox {
-                x: 0.0,
-                y: 0.0,
-                width: viewport.width(),
-                height: viewport.height(),
-            };
+            let vbox = ViewBox::new(Rect::from_size(viewport.width(), viewport.height()));
 
             (viewport, vbox)
         };
@@ -255,13 +248,13 @@ impl DrawingCtx {
     pub fn get_view_params(&self) -> ViewParams {
         let view_box_stack = self.view_box_stack.borrow();
         let last = view_box_stack.len() - 1;
-        let stack_top = &view_box_stack[last];
+        let top_rect = &view_box_stack[last].0;
 
         ViewParams {
             dpi_x: self.dpi.x(),
             dpi_y: self.dpi.y(),
-            view_box_width: stack_top.width,
-            view_box_height: stack_top.height,
+            view_box_width: top_rect.width(),
+            view_box_height: top_rect.height(),
             view_box_stack: None,
         }
     }
@@ -276,7 +269,7 @@ impl DrawingCtx {
     pub fn push_view_box(&self, width: f64, height: f64) -> ViewParams {
         self.view_box_stack
             .borrow_mut()
-            .push(ViewBox::new(0.0, 0.0, width, height));
+            .push(ViewBox::new(Rect::from_size(width, height)));
 
         ViewParams {
             dpi_x: self.dpi.x(),
@@ -308,16 +301,11 @@ impl DrawingCtx {
                 if let Some(vbox) = vbox {
                     if let Some(ref clip) = clip_mode {
                         if *clip == ClipMode::ClipToVbox {
-                            self.clip(Rect::new(
-                                vbox.x,
-                                vbox.y,
-                                vbox.x + vbox.width,
-                                vbox.y + vbox.height,
-                            ));
+                            self.clip(vbox.0);
                         }
                     }
 
-                    Some(self.push_view_box(vbox.width, vbox.height))
+                    Some(self.push_view_box(vbox.0.width(), vbox.0.height()))
                 } else {
                     Some(self.get_view_params())
                 }
diff --git a/rsvg_internals/src/filters/image.rs b/rsvg_internals/src/filters/image.rs
index a443778f..fe05485d 100644
--- a/rsvg_internals/src/filters/image.rs
+++ b/rsvg_internals/src/filters/image.rs
@@ -120,12 +120,10 @@ impl FeImage {
 
         // TODO: this goes through a f64->i32->f64 conversion.
         let r = self.aspect.compute(
-            &ViewBox::new(
-                0.0,
-                0.0,
+            &ViewBox::new(Rect::from_size(
                 f64::from(surface.width()),
                 f64::from(surface.height()),
-            ),
+            )),
             unclipped_bounds,
         );
 
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index 94615c5c..9d45bd23 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -109,7 +109,7 @@ impl NodeTrait for Image {
                 let image_height = f64::from(image_height);
 
                 if let Some(_params) = dc.push_new_viewport(
-                    Some(ViewBox::new(0.0, 0.0, image_width, image_height)),
+                    Some(ViewBox::new(Rect::from_size(image_width, image_height))),
                     Rect::new(x, y, x + w, y + h),
                     self.aspect,
                     clip_mode,
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index 508416bd..caa2e7ca 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -150,18 +150,19 @@ impl Marker {
             }
 
             let params = if let Some(vbox) = self.vbox {
-                let r = self.aspect.compute(
-                    &vbox,
-                    Rect::from_size(marker_width, marker_height),
-                );
+                let r = self
+                    .aspect
+                    .compute(&vbox, Rect::from_size(marker_width, marker_height));
 
                 if r.is_empty() {
                     return Ok(dc.empty_bbox());
                 }
 
-                cr.scale(r.width() / vbox.width, r.height() / vbox.height);
+                let vb_width = vbox.0.width();
+                let vb_height = vbox.0.height();
+                cr.scale(r.width() / vb_width, r.height() / vb_height);
 
-                dc.push_view_box(vbox.width, vbox.height)
+                dc.push_view_box(vb_width, vb_height)
             } else {
                 dc.push_view_box(marker_width, marker_height)
             };
@@ -172,11 +173,9 @@ impl Marker {
             );
 
             if !values.is_overflow() {
-                let clip_rect = if let Some(vbox) = self.vbox {
-                    Rect::new(vbox.x, vbox.y, vbox.x + vbox.width, vbox.y + vbox.height)
-                } else {
-                    Rect::from_size(marker_width, marker_height)
-                };
+                let clip_rect = self
+                    .vbox
+                    .map_or_else(|| Rect::from_size(marker_width, marker_height), |vb| vb.0);
 
                 dc.clip(clip_rect);
             }
diff --git a/rsvg_internals/src/pattern.rs b/rsvg_internals/src/pattern.rs
index e047d6d6..f471feb3 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -325,14 +325,14 @@ impl AsPaintSource for ResolvedPattern {
                 Rect::from_size(scaled_width, scaled_height),
             );
 
-            let sw = r.width() / vbox.width;
-            let sh = r.height() / vbox.height;
-            let x = r.x0 - vbox.x * sw;
-            let y = r.y0 - vbox.y * sh;
+            let sw = r.width() / vbox.0.width();
+            let sh = r.height() / vbox.0.height();
+            let x = r.x0 - vbox.0.x0 * sw;
+            let y = r.y0 - vbox.0.y0 * sh;
 
             caffine = cairo::Matrix::new(sw, 0.0, 0.0, sh, x, y);
 
-            draw_ctx.push_view_box(vbox.width, vbox.height)
+            draw_ctx.push_view_box(vbox.0.width(), vbox.0.height())
         } else if content_units == PatternContentUnits(CoordUnits::ObjectBoundingBox) {
             // If coords are in terms of the bounding box, use them
             let bbrect = bbox.rect.unwrap();
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index 473855cb..c06deaf5 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -107,7 +107,7 @@ impl Svg {
 
         match (w, h, self.vbox) {
             (w, h, Some(vbox)) => {
-                let params = ViewParams::new(dpi.x(), dpi.y(), vbox.width, vbox.height);
+                let params = ViewParams::new(dpi.x(), dpi.y(), vbox.0.width(), vbox.0.height());
 
                 Some((
                     w.normalize(values, &params).round() as i32,
@@ -243,12 +243,10 @@ impl NodeTrait for Svg {
                 // Use our viewBox if available, or try to derive one from
                 // the intrinsic dimensions.
                 self.vbox.or_else(|| {
-                    Some(ViewBox {
-                        x: 0.0,
-                        y: 0.0,
-                        width: svg_viewport.width(),
-                        height: svg_viewport.height(),
-                    })
+                    Some(ViewBox(Rect::from_size(
+                        svg_viewport.width(),
+                        svg_viewport.height(),
+                    )))
                 }),
             )
         };
diff --git a/rsvg_internals/src/viewbox.rs b/rsvg_internals/src/viewbox.rs
index ac18d4d9..577156ec 100644
--- a/rsvg_internals/src/viewbox.rs
+++ b/rsvg_internals/src/viewbox.rs
@@ -3,28 +3,14 @@ use cssparser::Parser;
 use crate::error::*;
 use crate::number_list::{NumberList, NumberListLength};
 use crate::parsers::Parse;
+use crate::rect::Rect;
 
 #[derive(Debug, Copy, Clone, PartialEq)]
-pub struct ViewBox {
-    pub x: f64,
-    pub y: f64,
-    pub width: f64,
-    pub height: f64,
-}
+pub struct ViewBox(pub Rect);
 
 impl ViewBox {
-    pub fn new(x: f64, y: f64, w: f64, h: f64) -> ViewBox {
-        assert!(
-            w >= 0.0 && h >= 0.0,
-            "width and height must not be negative"
-        );
-
-        ViewBox {
-            x,
-            y,
-            width: w,
-            height: h,
-        }
+    pub fn new(r: Rect) -> ViewBox {
+        ViewBox(r)
     }
 }
 
@@ -46,7 +32,7 @@ impl Parse for ViewBox {
         let (x, y, width, height) = (v[0], v[1], v[2], v[3]);
 
         if width >= 0.0 && height >= 0.0 {
-            Ok(ViewBox::new(x, y, width, height))
+            Ok(ViewBox::new(Rect::new(x, y, x + width, y + height)))
         } else {
             Err(ValueErrorKind::value_error("width and height must not be negative"))
         }
@@ -61,12 +47,12 @@ mod tests {
     fn parses_valid_viewboxes() {
         assert_eq!(
             ViewBox::parse_str("  1 2 3 4"),
-            Ok(ViewBox::new(1.0, 2.0, 3.0, 4.0))
+            Ok(ViewBox::new(Rect::new(1.0, 2.0, 4.0, 6.0)))
         );
 
         assert_eq!(
             ViewBox::parse_str(" -1.5 -2.5e1,34,56e2  "),
-            Ok(ViewBox::new(-1.5, -25.0, 34.0, 5600.0))
+            Ok(ViewBox::new(Rect::new(-1.5, -25.0, 32.5, 5575.0)))
         );
     }
 


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