[librsvg/wip/dimensions-api] AspectRatio.compute() - Take a ViewBox instead of an object_width/object_height



commit dbab8b64089742948d68371f2a58bf060402d538
Author: Federico Mena Quintero <federico gnome org>
Date:   Fri Feb 8 19:45:59 2019 -0600

    AspectRatio.compute() - Take a ViewBox instead of an object_width/object_height
    
    We will gradually move AspectRatio to computing a full affine
    transformation instead of just the destination x/y/w/h which are then
    handled by hand all over the place.
    
    For now, compute() just uses vbox.width and vbox.height, not all of
    its fields.

 rsvg_internals/src/aspect_ratio.rs  | 51 +++++++++++++++++++------------------
 rsvg_internals/src/filters/image.rs |  9 +++++--
 rsvg_internals/src/handle.rs        | 12 ++++++---
 rsvg_internals/src/image.rs         |  3 ++-
 rsvg_internals/src/length.rs        | 32 +++++++++++++++--------
 rsvg_internals/src/marker.rs        | 12 +++------
 rsvg_internals/src/pattern.rs       |  3 +--
 rsvg_internals/src/viewport.rs      |  3 +--
 8 files changed, 70 insertions(+), 55 deletions(-)
---
diff --git a/rsvg_internals/src/aspect_ratio.rs b/rsvg_internals/src/aspect_ratio.rs
index 0c563684..f686b336 100644
--- a/rsvg_internals/src/aspect_ratio.rs
+++ b/rsvg_internals/src/aspect_ratio.rs
@@ -20,11 +20,13 @@
 //! [`AspectRatio`]: struct.AspectRatio.html
 //! [spec]: https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
 
+use std::ops::Deref;
+
 use cssparser::{CowRcStr, Parser};
 use error::ValueErrorKind;
 use parsers::Parse;
 use parsers::ParseError;
-use std::ops::Deref;
+use viewbox::ViewBox;
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub struct AspectRatio {
@@ -122,8 +124,7 @@ impl AspectRatio {
 
     pub fn compute(
         &self,
-        object_width: f64,
-        object_height: f64,
+        vbox: &ViewBox,
         dest_x: f64,
         dest_y: f64,
         dest_width: f64,
@@ -133,15 +134,15 @@ impl AspectRatio {
             None => (dest_x, dest_y, dest_width, dest_height),
 
             Some(Align { x, y, fit }) => {
-                let w_factor = dest_width / object_width;
-                let h_factor = dest_height / object_height;
+                let w_factor = dest_width / vbox.width;
+                let h_factor = dest_height / vbox.height;
                 let factor = match fit {
                     FitMode::Meet => w_factor.min(h_factor),
                     FitMode::Slice => w_factor.max(h_factor),
                 };
 
-                let w = object_width * factor;
-                let h = object_height * factor;
+                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);
@@ -310,75 +311,75 @@ mod tests {
     #[test]
     fn aligns() {
         let foo = AspectRatio::parse_str("xMinYMin meet").unwrap();
-        let foo = foo.compute(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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(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), 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 7c41f813..bb28e456 100644
--- a/rsvg_internals/src/filters/image.rs
+++ b/rsvg_internals/src/filters/image.rs
@@ -13,6 +13,7 @@ use parsers::{ParseError, ParseValue};
 use property_bag::PropertyBag;
 use rect::IRect;
 use surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
+use viewbox::ViewBox;
 
 use super::bounds::BoundsBuilder;
 use super::context::{FilterContext, FilterOutput, FilterResult};
@@ -127,8 +128,12 @@ impl Image {
         let render_bounds = bounds_builder.into_irect_without_clipping(draw_ctx);
         let aspect = self.aspect.get();
         let (x, y, w, h) = aspect.compute(
-            f64::from(surface.width()),
-            f64::from(surface.height()),
+            &ViewBox::new(
+                0.0,
+                0.0,
+                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),
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index 4e8d85ee..c050dc51 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -1133,7 +1133,11 @@ pub unsafe extern "C" fn rsvg_handle_rust_new_from_data(
     ret
 }
 
-unsafe fn set_out_param<T: Copy>(out_has_param: *mut glib_sys::gboolean, out_param: *mut T, value: 
&Option<T>) {
+unsafe fn set_out_param<T: Copy>(
+    out_has_param: *mut glib_sys::gboolean,
+    out_param: *mut T,
+    value: &Option<T>,
+) {
     let has_value = if let Some(ref v) = *value {
         if !out_param.is_null() {
             *out_param = *v;
@@ -1171,7 +1175,7 @@ pub unsafe extern "C" fn rsvg_handle_rust_get_intrinsic_dimensions(
     let h = d.width.map(|l| l.to_length());
     let r = d.vbox.map(RsvgRectangle::from);
 
-    set_out_param (out_has_width, out_width, &w);
-    set_out_param (out_has_height, out_height, &h);
-    set_out_param (out_has_viewbox, out_viewbox, &r);
+    set_out_param(out_has_width, out_width, &w);
+    set_out_param(out_has_height, out_height, &h);
+    set_out_param(out_has_viewbox, out_viewbox, &r);
 }
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index 448caf20..a3f0306b 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -13,6 +13,7 @@ use length::{LengthHorizontal, LengthVertical};
 use node::*;
 use parsers::{ParseError, ParseValue};
 use property_bag::PropertyBag;
+use viewbox::ViewBox;
 
 pub struct NodeImage {
     aspect: Cell<AspectRatio>,
@@ -123,7 +124,7 @@ impl NodeTrait for NodeImage {
             let width = f64::from(width);
             let height = f64::from(height);
 
-            let (x, y, w, h) = aspect.compute(width, height, x, y, w, h);
+            let (x, y, w, h) = aspect.compute(&ViewBox::new(0.0, 0.0, width, height), x, y, w, h);
 
             let cr = dc.get_cairo_context();
 
diff --git a/rsvg_internals/src/length.rs b/rsvg_internals/src/length.rs
index 0f99b7c5..50874b7f 100644
--- a/rsvg_internals/src/length.rs
+++ b/rsvg_internals/src/length.rs
@@ -107,28 +107,30 @@ macro_rules! define_length_type {
 
                     LengthUnit::Em => self.length() * font_size_from_values(values, params),
 
-                    LengthUnit::Ex => {
-                        self.length() * font_size_from_values(values, params) / 2.0
-                    }
+                    LengthUnit::Ex => self.length() * font_size_from_values(values, params) / 2.0,
 
                     LengthUnit::In => {
                         self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y)
                     }
 
                     LengthUnit::Cm => {
-                        self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y) / CM_PER_INCH
+                        self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y)
+                            / CM_PER_INCH
                     }
 
                     LengthUnit::Mm => {
-                        self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y) / MM_PER_INCH
+                        self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y)
+                            / MM_PER_INCH
                     }
 
                     LengthUnit::Pt => {
-                        self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y) / POINTS_PER_INCH
+                        self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y)
+                            / POINTS_PER_INCH
                     }
 
                     LengthUnit::Pc => {
-                        self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y) / PICA_PER_INCH
+                        self.length() * $dir.scaling_factor(params.dpi_x, params.dpi_y)
+                            / PICA_PER_INCH
                     }
                 }
             }
@@ -347,10 +349,18 @@ fn font_size_from_values(values: &ComputedValues, params: &ViewParams) -> f64 {
 
         // FontSize always is a LengthDir::Both, per properties.rs
         LengthUnit::In => v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y),
-        LengthUnit::Cm => v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y) / 
CM_PER_INCH,
-        LengthUnit::Mm => v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y) / 
MM_PER_INCH,
-        LengthUnit::Pt => v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y) / 
POINTS_PER_INCH,
-        LengthUnit::Pc => v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y) / 
PICA_PER_INCH,
+        LengthUnit::Cm => {
+            v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y) / CM_PER_INCH
+        }
+        LengthUnit::Mm => {
+            v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y) / MM_PER_INCH
+        }
+        LengthUnit::Pt => {
+            v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y) / POINTS_PER_INCH
+        }
+        LengthUnit::Pc => {
+            v.length * LengthDir::Both.scaling_factor(params.dpi_x, params.dpi_y) / PICA_PER_INCH
+        }
     }
 }
 
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index 310c0638..082eb90e 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -152,14 +152,10 @@ impl NodeMarker {
         }
 
         let params = if let Some(vbox) = self.vbox.get() {
-            let (_, _, w, h) = self.aspect.get().compute(
-                vbox.width,
-                vbox.height,
-                0.0,
-                0.0,
-                marker_width,
-                marker_height,
-            );
+            let (_, _, w, h) =
+                self.aspect
+                    .get()
+                    .compute(&vbox, 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 becd7fd2..28634956 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -367,8 +367,7 @@ impl PaintSource for NodePattern {
         let _params = if let Some(vbox) = vbox {
             // If there is a vbox, use that
             let (mut x, mut y, w, h) = preserve_aspect_ratio.compute(
-                vbox.width,
-                vbox.height,
+                &vbox,
                 0.0,
                 0.0,
                 pattern_width * bbwscale,
diff --git a/rsvg_internals/src/viewport.rs b/rsvg_internals/src/viewport.rs
index 25ef4ed0..3f9103d8 100644
--- a/rsvg_internals/src/viewport.rs
+++ b/rsvg_internals/src/viewport.rs
@@ -59,8 +59,7 @@ 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.width, vbox.height, vx, vy, vw, vh);
+            let (x, y, w, h) = preserve_aspect_ratio.compute(&vbox, 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]