[librsvg/wip/dimensions-api] AspectRatio.compute(): take the destination viewport as a cairo::Rectangle



commit 8368470b13cf09a3a3a46101f3e1f114a1e37b35
Author: Federico Mena Quintero <federico gnome org>
Date:   Fri Feb 8 20:15:33 2019 -0600

    AspectRatio.compute(): take the destination viewport as a cairo::Rectangle
    
    ... and actually name the argument "viewport", since that is what the
    SVG spec calls it.

 rsvg_internals/src/aspect_ratio.rs  | 113 ++++++++++++++++++++++++++----------
 rsvg_internals/src/filters/image.rs |  14 +++--
 rsvg_internals/src/image.rs         |   8 ++-
 rsvg_internals/src/marker.rs        |  11 ++--
 rsvg_internals/src/pattern.rs       |  14 +++--
 rsvg_internals/src/rect.rs          |  10 ++++
 rsvg_internals/src/viewport.rs      |   6 +-
 7 files changed, 124 insertions(+), 52 deletions(-)
---
diff --git a/rsvg_internals/src/aspect_ratio.rs b/rsvg_internals/src/aspect_ratio.rs
index f686b336..8af83ed3 100644
--- a/rsvg_internals/src/aspect_ratio.rs
+++ b/rsvg_internals/src/aspect_ratio.rs
@@ -22,6 +22,8 @@
 
 use std::ops::Deref;
 
+use cairo;
+
 use cssparser::{CowRcStr, Parser};
 use error::ValueErrorKind;
 use parsers::Parse;
@@ -122,20 +124,13 @@ impl AspectRatio {
         }
     }
 
-    pub fn compute(
-        &self,
-        vbox: &ViewBox,
-        dest_x: f64,
-        dest_y: f64,
-        dest_width: f64,
-        dest_height: f64,
-    ) -> (f64, f64, f64, f64) {
+    pub fn compute(&self, vbox: &ViewBox, viewport: &cairo::Rectangle) -> (f64, f64, f64, f64) {
         match self.align {
-            None => (dest_x, dest_y, dest_width, dest_height),
+            None => (viewport.x, viewport.y, viewport.width, viewport.height),
 
             Some(Align { x, y, fit }) => {
-                let w_factor = dest_width / vbox.width;
-                let h_factor = dest_height / vbox.height;
+                let w_factor = viewport.width / vbox.width;
+                let h_factor = viewport.height / vbox.height;
                 let factor = match fit {
                     FitMode::Meet => w_factor.min(h_factor),
                     FitMode::Slice => w_factor.max(h_factor),
@@ -144,8 +139,8 @@ impl AspectRatio {
                 let w = vbox.width * factor;
                 let h = vbox.height * factor;
 
-                let xpos = x.compute(dest_x, dest_width, w);
-                let ypos = y.compute(dest_y, dest_height, h);
+                let xpos = x.compute(viewport.x, viewport.width, w);
+                let ypos = y.compute(viewport.y, viewport.height, h);
 
                 (xpos, ypos, w, h)
             }
@@ -216,7 +211,9 @@ impl Parse for AspectRatio {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use cairo::Rectangle;
     use float_eq_cairo::ApproxEqCairo;
+    use rect::RectangleExt;
 
     #[test]
     fn parsing_invalid_strings_yields_error() {
@@ -311,75 +308,129 @@ mod tests {
     #[test]
     fn aligns() {
         let foo = AspectRatio::parse_str("xMinYMin meet").unwrap();
-        let foo = foo.compute(&ViewBox::new(0.0, 0.0, 1.0, 10.0), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(0.0, 0.0, 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), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(0.0, 0.0, 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), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(0.0, 0.0, 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), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(0.0, -49.5, 10.0, 100.0));
 
         let foo = AspectRatio::parse_str("xMinYMax meet").unwrap();
-        let foo = foo.compute(&ViewBox::new(0.0, 0.0, 1.0, 10.0), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(0.0, 0.0, 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), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(0.0, -99.0, 10.0, 100.0));
 
         let foo = AspectRatio::parse_str("xMidYMin meet").unwrap();
-        let foo = foo.compute(&ViewBox::new(0.0, 0.0, 1.0, 10.0), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(4.95, 0.0, 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), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(0.0, 0.0, 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), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(4.95, 0.0, 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), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(0.0, -49.5, 10.0, 100.0));
 
         let foo = AspectRatio::parse_str("xMidYMax meet").unwrap();
-        let foo = foo.compute(&ViewBox::new(0.0, 0.0, 1.0, 10.0), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(4.95, 0.0, 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), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(0.0, -99.0, 10.0, 100.0));
 
         let foo = AspectRatio::parse_str("xMaxYMin meet").unwrap();
-        let foo = foo.compute(&ViewBox::new(0.0, 0.0, 1.0, 10.0), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(9.9, 0.0, 0.1, 1.0));
 
         let foo = AspectRatio::parse_str("xMaxYMin slice").unwrap();
-        let foo = foo.compute(&ViewBox::new(0.0, 0.0, 1.0, 10.0), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(0.0, 0.0, 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), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(9.9, 0.0, 0.1, 1.0));
 
         let foo = AspectRatio::parse_str("xMaxYMid slice").unwrap();
-        let foo = foo.compute(&ViewBox::new(0.0, 0.0, 1.0, 10.0), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(0.0, -49.5, 10.0, 100.0));
 
         let foo = AspectRatio::parse_str("xMaxYMax meet").unwrap();
-        let foo = foo.compute(&ViewBox::new(0.0, 0.0, 1.0, 10.0), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(9.9, 0.0, 0.1, 1.0));
 
         let foo = AspectRatio::parse_str("xMaxYMax slice").unwrap();
-        let foo = foo.compute(&ViewBox::new(0.0, 0.0, 1.0, 10.0), 0.0, 0.0, 10.0, 1.0);
+        let foo = foo.compute(
+            &ViewBox::new(0.0, 0.0, 1.0, 10.0),
+            &Rectangle::new(0.0, 0.0, 10.0, 1.0),
+        );
         assert_quadruples_equal(&foo, &(0.0, -99.0, 10.0, 100.0));
     }
 }
diff --git a/rsvg_internals/src/filters/image.rs b/rsvg_internals/src/filters/image.rs
index bb28e456..e517a31e 100644
--- a/rsvg_internals/src/filters/image.rs
+++ b/rsvg_internals/src/filters/image.rs
@@ -1,6 +1,6 @@
 use std::cell::{Cell, RefCell};
 
-use cairo::{self, ImageSurface, MatrixTrait, PatternTrait};
+use cairo::{self, ImageSurface, MatrixTrait, PatternTrait, Rectangle};
 
 use allowed_url::{Fragment, Href};
 use aspect_ratio::AspectRatio;
@@ -11,7 +11,7 @@ use float_eq_cairo::ApproxEqCairo;
 use node::{CascadedValues, NodeResult, NodeTrait, RsvgNode};
 use parsers::{ParseError, ParseValue};
 use property_bag::PropertyBag;
-use rect::IRect;
+use rect::{IRect, RectangleExt};
 use surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
 use viewbox::ViewBox;
 
@@ -134,10 +134,12 @@ impl Image {
                 f64::from(surface.width()),
                 f64::from(surface.height()),
             ),
-            f64::from(render_bounds.x0),
-            f64::from(render_bounds.y0),
-            f64::from(render_bounds.x1 - render_bounds.x0),
-            f64::from(render_bounds.y1 - render_bounds.y0),
+            &Rectangle::new(
+                f64::from(render_bounds.x0),
+                f64::from(render_bounds.y0),
+                f64::from(render_bounds.x1 - render_bounds.x0),
+                f64::from(render_bounds.y1 - render_bounds.y0),
+            ),
         );
 
         if w.approx_eq_cairo(&0.0) || h.approx_eq_cairo(&0.0) {
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index a3f0306b..01fc92b2 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -1,5 +1,5 @@
 use cairo;
-use cairo::{MatrixTrait, PatternTrait};
+use cairo::{MatrixTrait, PatternTrait, Rectangle};
 use std::cell::{Cell, RefCell};
 
 use allowed_url::Href;
@@ -13,6 +13,7 @@ use length::{LengthHorizontal, LengthVertical};
 use node::*;
 use parsers::{ParseError, ParseValue};
 use property_bag::PropertyBag;
+use rect::RectangleExt;
 use viewbox::ViewBox;
 
 pub struct NodeImage {
@@ -124,7 +125,10 @@ impl NodeTrait for NodeImage {
             let width = f64::from(width);
             let height = f64::from(height);
 
-            let (x, y, w, h) = aspect.compute(&ViewBox::new(0.0, 0.0, width, height), x, y, w, h);
+            let (x, y, w, h) = aspect.compute(
+                &ViewBox::new(0.0, 0.0, width, height),
+                &Rectangle::new(x, y, w, h),
+            );
 
             let cr = dc.get_cairo_context();
 
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index 082eb90e..fa401e8a 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -2,7 +2,7 @@ use std::cell::Cell;
 use std::f64::consts::*;
 use std::ops::Deref;
 
-use cairo::MatrixTrait;
+use cairo::{MatrixTrait, Rectangle};
 use cssparser::{CowRcStr, Parser, Token};
 
 use allowed_url::Fragment;
@@ -19,6 +19,7 @@ use parsers::{Parse, ParseError, ParseValue};
 use path_builder::*;
 use properties::{ComputedValues, SpecifiedValue, SpecifiedValues};
 use property_bag::PropertyBag;
+use rect::RectangleExt;
 use viewbox::*;
 
 // markerUnits attribute: https://www.w3.org/TR/SVG/painting.html#MarkerElement
@@ -152,10 +153,10 @@ impl NodeMarker {
         }
 
         let params = if let Some(vbox) = self.vbox.get() {
-            let (_, _, w, h) =
-                self.aspect
-                    .get()
-                    .compute(&vbox, 0.0, 0.0, marker_width, marker_height);
+            let (_, _, w, h) = self.aspect.get().compute(
+                &vbox,
+                &Rectangle::new(0.0, 0.0, marker_width, marker_height),
+            );
 
             if vbox.width.approx_eq_cairo(&0.0) || vbox.height.approx_eq_cairo(&0.0) {
                 return Ok(());
diff --git a/rsvg_internals/src/pattern.rs b/rsvg_internals/src/pattern.rs
index 28634956..6e0b51db 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -1,6 +1,5 @@
 use cairo;
-use cairo::MatrixTrait;
-use cairo::PatternTrait;
+use cairo::{MatrixTrait, PatternTrait};
 use std::cell::RefCell;
 use std::f64;
 use std::rc::*;
@@ -19,6 +18,7 @@ use paint_server::PaintSource;
 use parsers::ParseValue;
 use properties::ComputedValues;
 use property_bag::PropertyBag;
+use rect::RectangleExt;
 use unit_interval::UnitInterval;
 use viewbox::*;
 
@@ -368,10 +368,12 @@ impl PaintSource for NodePattern {
             // If there is a vbox, use that
             let (mut x, mut y, w, h) = preserve_aspect_ratio.compute(
                 &vbox,
-                0.0,
-                0.0,
-                pattern_width * bbwscale,
-                pattern_height * bbhscale,
+                &cairo::Rectangle::new(
+                    0.0,
+                    0.0,
+                    pattern_width * bbwscale,
+                    pattern_height * bbhscale,
+                ),
             );
 
             x -= vbox.x * w / vbox.width;
diff --git a/rsvg_internals/src/rect.rs b/rsvg_internals/src/rect.rs
index dc43aec5..c2035152 100644
--- a/rsvg_internals/src/rect.rs
+++ b/rsvg_internals/src/rect.rs
@@ -4,6 +4,7 @@ use cairo::MatrixTrait;
 use float_eq_cairo::ApproxEqCairo;
 
 pub trait RectangleExt {
+    fn new(x: f64, y: f64, width: f64, height: f64) -> cairo::Rectangle;
     fn is_empty(&self) -> bool;
     fn intersect(&self, rect: &cairo::Rectangle) -> cairo::Rectangle;
     fn union(&self, rect: &cairo::Rectangle) -> cairo::Rectangle;
@@ -12,6 +13,15 @@ pub trait RectangleExt {
 }
 
 impl RectangleExt for cairo::Rectangle {
+    fn new(x: f64, y: f64, width: f64, height: f64) -> cairo::Rectangle {
+        cairo::Rectangle {
+            x,
+            y,
+            width,
+            height,
+        }
+    }
+
     fn is_empty(&self) -> bool {
         self.width.approx_eq_cairo(&0.0) || self.height.approx_eq_cairo(&0.0)
     }
diff --git a/rsvg_internals/src/viewport.rs b/rsvg_internals/src/viewport.rs
index 3f9103d8..f2641cf5 100644
--- a/rsvg_internals/src/viewport.rs
+++ b/rsvg_internals/src/viewport.rs
@@ -1,5 +1,5 @@
 use cairo;
-use cairo::MatrixTrait;
+use cairo::{MatrixTrait, Rectangle};
 
 use aspect_ratio::AspectRatio;
 use drawing_ctx::DrawingCtx;
@@ -7,6 +7,7 @@ use error::RenderingError;
 use float_eq_cairo::ApproxEqCairo;
 use node::RsvgNode;
 use properties::ComputedValues;
+use rect::RectangleExt;
 use viewbox::*;
 
 #[derive(Debug, Copy, Clone, PartialEq)]
@@ -59,7 +60,8 @@ pub fn draw_in_viewport(
 
             let params = dc.push_view_box(vbox.width, vbox.height);
 
-            let (x, y, w, h) = preserve_aspect_ratio.compute(&vbox, vx, vy, vw, vh);
+            let (x, y, w, h) =
+                preserve_aspect_ratio.compute(&vbox, &Rectangle::new(vx, vy, vw, vh));
 
             affine.translate(x, y);
             affine.scale(w / vbox.width, h / vbox.height);


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