[librsvg: 2/7] Implement the legacy sizing decisions in terms of CairoRenderer




commit ff5de371e8d6ccb1c1e1e33cb86e9974ea95d65c
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Oct 27 18:31:07 2020 -0600

    Implement the legacy sizing decisions in terms of CairoRenderer
    
    Do this in a new "sizing" module in the c_api crate.

 Makefile.am       |  1 +
 librsvg/c_api.rs  |  2 +-
 librsvg/lib.rs    |  1 +
 librsvg/sizing.rs | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 71 insertions(+), 1 deletion(-)
---
diff --git a/Makefile.am b/Makefile.am
index 7c5e8cfa..82741ce6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -132,6 +132,7 @@ LIBRSVG_C_API_SRC =                                         \
        librsvg/lib.rs                                          \
        librsvg/messages.rs                                     \
        librsvg/pixbuf_utils.rs                                 \
+       librsvg/sizing.rs                                       \
        librsvg/benches/pixbuf_from_surface.rs                  \
        $(NULL)
 
diff --git a/librsvg/c_api.rs b/librsvg/c_api.rs
index af922a6b..76779778 100644
--- a/librsvg/c_api.rs
+++ b/librsvg/c_api.rs
@@ -1120,7 +1120,7 @@ fn size_in_pixels_from_percentage_width_and_height(
     }
 }
 
-fn unit_rectangle() -> cairo::Rectangle {
+pub fn unit_rectangle() -> cairo::Rectangle {
     cairo::Rectangle::from_size(1.0, 1.0)
 }
 
diff --git a/librsvg/lib.rs b/librsvg/lib.rs
index 8f647f8a..136a4e0c 100644
--- a/librsvg/lib.rs
+++ b/librsvg/lib.rs
@@ -54,3 +54,4 @@ mod c_api;
 mod color_utils;
 mod dpi;
 pub mod pixbuf_utils;
+mod sizing;
diff --git a/librsvg/sizing.rs b/librsvg/sizing.rs
new file mode 100644
index 00000000..69fff74d
--- /dev/null
+++ b/librsvg/sizing.rs
@@ -0,0 +1,68 @@
+use float_cmp::approx_eq;
+use librsvg::{CairoRenderer, IntrinsicDimensions, Length, RenderingError};
+
+use crate::c_api::unit_rectangle;
+
+pub trait LegacySize {
+    fn legacy_document_size_in_pixels(&self) -> Result<(f64, f64), RenderingError>;
+}
+
+impl<'a> LegacySize for CairoRenderer<'a> {
+    fn legacy_document_size_in_pixels(&self) -> Result<(f64, f64), RenderingError> {
+        let size_from_intrinsic_dimensions = self.intrinsic_size_in_pixels().or_else(|| {
+            size_in_pixels_from_percentage_width_and_height(&self.intrinsic_dimensions())
+        });
+
+        if let Some(dim) = size_from_intrinsic_dimensions {
+            // We have a size directly computed from the <svg> attributes
+            Ok(dim)
+        } else {
+            // Compute the extents of all objects in the SVG
+            let (ink_r, _) = self.geometry_for_layer(None, &unit_rectangle())?;
+            Ok((ink_r.width, ink_r.height))
+        }
+    }
+}
+
+/// If the width and height are in percentage units, computes a size equal to the
+/// `viewBox`'s aspect ratio if it exists, or else returns None.
+///
+/// For example, a `viewBox="0 0 100 200"` will yield `Some(100.0, 200.0)`.
+///
+/// Note that this only checks that the width and height are in percentage units, but
+/// it actually ignores their values.  This is because at the point this function is
+/// called, there is no viewport to embed the SVG document in, so those percentage
+/// units cannot be resolved against anything in particular.  The idea is to return
+/// some dimensions with the correct aspect ratio.
+fn size_in_pixels_from_percentage_width_and_height(
+    dim: &IntrinsicDimensions,
+) -> Option<(f64, f64)> {
+    let IntrinsicDimensions {
+        width,
+        height,
+        vbox,
+    } = *dim;
+
+    use librsvg::LengthUnit::*;
+
+    // If both width and height are 100%, just use the vbox size as a pixel size.
+    // This gives a size with the correct aspect ratio.
+
+    match (width, height, vbox) {
+        (None, None, Some(vbox)) => Some((vbox.width, vbox.height)),
+
+        (
+            Some(Length {
+                length: w,
+                unit: Percent,
+            }),
+            Some(Length {
+                length: h,
+                unit: Percent,
+            }),
+            Some(vbox),
+        ) if approx_eq!(f64, w, 1.0) && approx_eq!(f64, h, 1.0) => Some((vbox.width, vbox.height)),
+
+        _ => None,
+    }
+}


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