[librsvg: 16/53] Reference tests: check that all test images have "obvious" intrinsic dimensions




commit f2d9924adacb5cd7b3ebaa764777a16a6ef91e8a
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Oct 14 13:34:01 2020 -0500

    Reference tests: check that all test images have "obvious" intrinsic dimensions
    
    I.e. that they don't need to figure out the document size from the
    font size (em/ex units in the width/height attributes of <svg>), or
    have non-100% percentage units.

 Cargo.lock             |   1 +
 librsvg/c_api.rs       |   2 +
 tests/Cargo.toml       |   1 +
 tests/src/main.rs      |   3 ++
 tests/src/reference.rs | 142 +++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 149 insertions(+)
---
diff --git a/Cargo.lock b/Cargo.lock
index 001703e2..03227de2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -781,6 +781,7 @@ version = "0.1.0"
 dependencies = [
  "assert_cmd",
  "cairo-rs",
+ "cast",
  "chrono",
  "float-cmp",
  "librsvg",
diff --git a/librsvg/c_api.rs b/librsvg/c_api.rs
index 116877d7..25555236 100644
--- a/librsvg/c_api.rs
+++ b/librsvg/c_api.rs
@@ -466,6 +466,7 @@ impl ObjectImpl for CHandle {
     }
 }
 
+// Keep in sync with tests/src/reference.rs
 pub fn checked_i32(x: f64) -> Result<i32, cairo::Status> {
     cast::i32(x).map_err(|_| cairo::Status::InvalidSize)
 }
@@ -815,6 +816,7 @@ impl CHandle {
         let res = handle
             .get_geometry_sub(id, inner.dpi.into(), inner.is_testing)
             .and_then(|(ink_r, _)| {
+                // Keep these in sync with tests/src/reference.rs
                 let width = checked_i32(ink_r.width().round())?;
                 let height = checked_i32(ink_r.height().round())?;
 
diff --git a/tests/Cargo.toml b/tests/Cargo.toml
index ac6a537d..932b4ab6 100644
--- a/tests/Cargo.toml
+++ b/tests/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2018"
 [dev-dependencies]
 assert_cmd = "1.0.1"
 cairo-rs = { version = "0.8.0", features = ["png"] }
+cast = "0.2.3"
 chrono = "0.4.0"
 float-cmp = "0.8.0"
 librsvg = { path = "../librsvg_crate" }
diff --git a/tests/src/main.rs b/tests/src/main.rs
index 8bd5ba4a..a8a3a6df 100644
--- a/tests/src/main.rs
+++ b/tests/src/main.rs
@@ -14,6 +14,9 @@ mod loading_crash;
 #[cfg(test)]
 mod predicates;
 
+#[cfg(test)]
+mod reference;
+
 #[cfg(test)]
 mod render_crash;
 
diff --git a/tests/src/reference.rs b/tests/src/reference.rs
new file mode 100644
index 00000000..c7cb7e7d
--- /dev/null
+++ b/tests/src/reference.rs
@@ -0,0 +1,142 @@
+//! Tests with reference images.
+//!
+//! This is the bulk of librsvg's black-box tests.  In principle, each test takes an SVG file, renders
+//! it to a raster image, and compares that image to a reference image stored on disk.  If the images
+//! are "too different", the test fails.  We allow for minor differences in rendering to account for
+//! antialiasing artifacts, floating-point variations, and such.
+//!
+
+#![cfg(test)]
+use test_generator::test_resources;
+
+use librsvg::{CairoRenderer, IntrinsicDimensions, Length, LengthUnit, Loader};
+
+use crate::utils::fixture_path;
+
+// The original reference images from the SVG1.1 test suite are at 72 DPI.
+const TEST_SUITE_DPI: f64 = 72.0;
+
+fn reference_test(name: &str) {
+    let path = fixture_path(name);
+
+    let handle = Loader::new()
+        .read_path(path)
+        .unwrap_or_else(|e| panic!("could not load: {}", e));
+
+    let renderer = CairoRenderer::new(&handle).with_dpi(TEST_SUITE_DPI, TEST_SUITE_DPI);
+
+    let (width, height) = image_size(renderer.intrinsic_dimensions(), TEST_SUITE_DPI);
+}
+
+/// Computes the (width, height) pixel size at which an SVG should be rendered, based on its intrinsic 
dimensions.
+///
+/// # Panics:
+///
+/// Will panic if none of the following conditions are met:
+///
+/// * Width and height both exist
+/// * Width and height do not exist, but viewBox exists.
+fn image_size(dim: IntrinsicDimensions, dpi: f64) -> (i32, i32) {
+    let IntrinsicDimensions {
+        width,
+        height,
+        vbox,
+    } = dim;
+
+    use LengthUnit::*;
+
+    if let (Some(width), Some(height)) = (width, height) {
+        if !(has_supported_unit(&width) && has_supported_unit(&height)) {
+            panic!("SVG has unsupported unit type in width or height");
+        }
+    }
+
+    #[rustfmt::skip]
+    let (width, height) = match (width, height, vbox) {
+        (Some(Length { length: w, unit: Percent }),
+         Some(Length { length: h, unit: Percent }), vbox) if w == 1.0 && h == 1.0 => {
+            if let Some(vbox) = vbox {
+                (vbox.width, vbox.height)
+            } else {
+                panic!("SVG with percentage width/height must have a viewBox");
+            }
+        }
+
+        (Some(Length { length: _, unit: Percent }),
+         Some(Length { length: _, unit: Percent }), _) => {
+            panic!("Test suite only supports percentage width/height at 100%");
+        }
+
+        (Some(w), Some(h), _) => {
+            (normalize(&w, dpi), normalize(&h, dpi))
+        }
+
+        (None, None, Some(vbox)) => (vbox.width, vbox.height),
+
+        (_, _, _) => panic!("Test suite does not support the dimensions of this file"),
+    };
+
+    // Keep in sync with c_api.rs
+    let width = checked_i32(width.round());
+    let height = checked_i32(height.round());
+
+    (width, height)
+}
+
+// Keep in sync with c_api.rs
+fn checked_i32(x: f64) -> i32 {
+    cast::i32(x).expect("overflow when converting f64 to i32")
+}
+
+fn has_supported_unit(l: &Length) -> bool {
+    use LengthUnit::*;
+
+    match l.unit {
+        Percent | Px | In | Cm | Mm | Pt | Pc => true,
+        _ => false,
+    }
+}
+
+const POINTS_PER_INCH: f64 = 72.0;
+const CM_PER_INCH: f64 = 2.54;
+const MM_PER_INCH: f64 = 25.4;
+const PICA_PER_INCH: f64 = 6.0;
+
+fn normalize(l: &Length, dpi: f64) -> f64 {
+    use LengthUnit::*;
+
+    match l.unit {
+        Px => l.length,
+        In => l.length * dpi,
+        Cm => l.length * dpi / CM_PER_INCH,
+        Mm => l.length * dpi / MM_PER_INCH,
+        Pt => l.length * dpi / POINTS_PER_INCH,
+        Pc => l.length * dpi / PICA_PER_INCH,
+        _ => panic!("unsupported length unit"),
+    }
+}
+
+#[test_resources("tests/fixtures/reftests/*.svg")]
+fn reftests(name: &str) {
+    reference_test(name);
+}
+
+#[test_resources("tests/fixtures/reftests/adwaita/*.svg")]
+fn adwaita(name: &str) {
+    reference_test(name);
+}
+
+#[test_resources("tests/fixtures/reftests/bugs/*.svg")]
+fn bugs(name: &str) {
+    reference_test(name);
+}
+
+#[test_resources("tests/fixtures/reftests/svg1.1/*.svg")]
+fn svg_1_1(name: &str) {
+    reference_test(name);
+}
+
+#[test_resources("tests/fixtures/reftests/svg2/*.svg")]
+fn svg_2(name: &str) {
+    reference_test(name);
+}


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