[librsvg: 21/53] Start comparing to the reference images
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 21/53] Start comparing to the reference images
- Date: Fri, 23 Oct 2020 02:19:07 +0000 (UTC)
commit fb37a68896f1e47101854adf258ac23d275dbb87
Author: Federico Mena Quintero <federico gnome org>
Date: Wed Oct 14 18:40:20 2020 -0500
Start comparing to the reference images
A bunch succeed, a bunch fail. Still missing:
* Set the "testing" flag.
* Create and set an FcConfig.
* Environment vars for language tests.
Cargo.lock | 1 +
tests/Cargo.toml | 1 +
tests/src/reference.rs | 144 +++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 136 insertions(+), 10 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 03227de2..fe05794d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -788,6 +788,7 @@ dependencies = [
"lopdf",
"png",
"predicates",
+ "rsvg_internals",
"tempfile",
"test-generator",
]
diff --git a/tests/Cargo.toml b/tests/Cargo.toml
index 932b4ab6..256c13f7 100644
--- a/tests/Cargo.toml
+++ b/tests/Cargo.toml
@@ -15,5 +15,6 @@ librsvg = { path = "../librsvg_crate" }
lopdf = "0.25.0"
png = "0.16.1"
predicates = "1.0.2"
+rsvg_internals = { path = "../rsvg_internals" }
tempfile = "3"
test-generator = "0.3"
diff --git a/tests/src/reference.rs b/tests/src/reference.rs
index d9ffca17..4efeb420 100644
--- a/tests/src/reference.rs
+++ b/tests/src/reference.rs
@@ -10,36 +10,73 @@
use test_generator::test_resources;
use cairo;
-use librsvg::{CairoRenderer, IntrinsicDimensions, Length, LengthUnit, Loader};
+use librsvg::{CairoRenderer, IntrinsicDimensions, Length, Loader};
+use rsvg_internals::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
use std::fs::File;
use std::io::BufReader;
use std::path::PathBuf;
use crate::utils::fixture_path;
+use self::duplicated_from_librsvg_crate::compare_to_file;
+
// The original reference images from the SVG1.1 test suite are at 72 DPI.
const TEST_SUITE_DPI: f64 = 72.0;
+// https://gitlab.gnome.org/GNOME/librsvg/issues/91
+//
+// We were computing some offsets incorrectly if the initial transformation matrix
+// passed to rsvg_handle_render_cairo() was not the identity matrix. So,
+// we create a surface with a "frame" around the destination for the image,
+// and then only consider the pixels inside the frame. This will require us
+// to have a non-identity transformation (i.e. a translation matrix), which
+// will test for this bug.
+//
+// The frame size is meant to be a ridiculous number to simulate an arbitrary
+// offset.
+const FRAME_SIZE: i32 = 47;
+
fn reference_test(name: &str) {
let path = fixture_path(name);
- if path.file_stem().unwrap().to_string_lossy().starts_with("ignore") {
+ let path_base_name = path.file_stem().unwrap().to_string_lossy().to_owned();
+ if path_base_name.starts_with("ignore") {
return;
}
let reference = reference_path(&path);
let handle = Loader::new()
- .read_path(path)
+ .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);
- let mut reference_file = BufReader::new(File::open(reference).unwrap());
- let expected = cairo::ImageSurface::create_from_png(&mut reference_file).unwrap();
+ let surface = cairo::ImageSurface::create(
+ cairo::Format::ARgb32,
+ width + 2 * FRAME_SIZE,
+ height + 2 * FRAME_SIZE,
+ ).unwrap();
+
+ {
+ let cr = cairo::Context::new(&surface);
+ cr.translate(f64::from(FRAME_SIZE), f64::from(FRAME_SIZE));
+ renderer.render_document(
+ &cr,
+ &cairo::Rectangle {
+ x: 0.0,
+ y: 0.0,
+ width: f64::from(width),
+ height: f64::from(height),
+ }
+ ).unwrap();
+ }
+
+ let surface = extract_rectangle(&surface, FRAME_SIZE, FRAME_SIZE, width, height).unwrap();
+
+ let output_surf = SharedImageSurface::wrap(surface, SurfaceType::SRgb).unwrap();
- assert!(width == expected.get_width() && height == expected.get_height());
+ compare_to_file(&output_surf, &path_base_name, &reference);
}
/// Turns `/foo/bar/baz.svg` into `/foo/bar/baz-ref.svg`.
@@ -52,6 +89,14 @@ fn reference_path(path: &PathBuf) -> PathBuf {
path.with_file_name(reference_filename)
}
+fn extract_rectangle(source: &cairo::ImageSurface, x: i32, y: i32, w: i32, h: i32) ->
Result<cairo::ImageSurface, cairo::Status> {
+ let dest = cairo::ImageSurface::create(cairo::Format::ARgb32, w, h)?;
+ let cr = cairo::Context::new(&dest);
+ cr.set_source_surface(&source, f64::from(-x), f64::from(-y));
+ cr.paint();
+ Ok(dest)
+}
+
/// Computes the (width, height) pixel size at which an SVG should be rendered, based on its intrinsic
dimensions.
///
/// # Panics:
@@ -67,7 +112,7 @@ fn image_size(dim: IntrinsicDimensions, dpi: f64) -> (i32, i32) {
vbox,
} = dim;
- use LengthUnit::*;
+ use librsvg::LengthUnit::*;
if let (Some(width), Some(height)) = (width, height) {
if !(has_supported_unit(&width) && has_supported_unit(&height)) {
@@ -113,7 +158,7 @@ fn checked_i32(x: f64) -> i32 {
}
fn has_supported_unit(l: &Length) -> bool {
- use LengthUnit::*;
+ use librsvg::LengthUnit::*;
match l.unit {
Percent | Px | In | Cm | Mm | Pt | Pc => true,
@@ -127,7 +172,7 @@ const MM_PER_INCH: f64 = 25.4;
const PICA_PER_INCH: f64 = 6.0;
fn normalize(l: &Length, dpi: f64) -> f64 {
- use LengthUnit::*;
+ use librsvg::LengthUnit::*;
match l.unit {
Px => l.length,
@@ -140,6 +185,85 @@ fn normalize(l: &Length, dpi: f64) -> f64 {
}
}
+// FIXME: see how to share this code
+mod duplicated_from_librsvg_crate {
+ use super::*;
+ use std::env;
+ use std::fs;
+ use rsvg_internals::{compare_surfaces, BufferDiff};
+
+ fn output_dir() -> PathBuf {
+ let path = PathBuf::from(
+ env::var_os("OUT_DIR")
+ .expect(r#"OUT_DIR is not set, please set it or run under "cargo test""#),
+ );
+
+ fs::create_dir_all(&path).expect("could not create output directory for tests");
+
+ println!("outputting to {}", path.to_string_lossy());
+
+ path
+ }
+
+ // FIXME: this is slightly different from librsvg_crate
+ pub fn compare_to_file(
+ output_surf: &SharedImageSurface,
+ output_base_name: &str,
+ reference_path: &PathBuf,
+ ) {
+ let file = File::open(reference_path).unwrap();
+
+ let mut reference_file = BufReader::new(file);
+
+ let reference = cairo::ImageSurface::create_from_png(&mut reference_file).unwrap();
+ let reference_surf = SharedImageSurface::wrap(reference, SurfaceType::SRgb).unwrap();
+
+ compare_to_surface(output_surf, &reference_surf, output_base_name);
+ }
+
+ fn compare_to_surface(
+ output_surf: &SharedImageSurface,
+ reference_surf: &SharedImageSurface,
+ output_base_name: &str,
+ ) {
+ let output_path = output_dir().join(&format!("{}-out.png", output_base_name));
+
+ let mut output_file = File::create(output_path).unwrap();
+ output_surf
+ .clone()
+ .into_image_surface()
+ .unwrap()
+ .write_to_png(&mut output_file)
+ .unwrap();
+
+ let diff = compare_surfaces(output_surf, reference_surf).unwrap();
+ evaluate_diff(&diff, output_base_name);
+ }
+
+ const MAX_DIFF: u8 = 2;
+
+ fn evaluate_diff(diff: &BufferDiff, output_base_name: &str) {
+ match diff {
+ BufferDiff::DifferentSizes => unreachable!("surfaces should be of the same size"),
+
+ BufferDiff::Diff(diff) => {
+ let surf = diff.surface.clone().into_image_surface().unwrap();
+ let diff_path = output_dir().join(&format!("{}-diff.png", output_base_name));
+ let mut output_file = File::create(diff_path).unwrap();
+ surf.write_to_png(&mut output_file).unwrap();
+
+ if diff.num_pixels_changed != 0 && diff.max_diff > MAX_DIFF {
+ println!(
+ "{}: {} pixels changed with maximum difference of {}",
+ output_base_name, diff.num_pixels_changed, diff.max_diff,
+ );
+ panic!("surfaces are too different");
+ }
+ }
+ }
+ }
+}
+
#[test_resources("tests/fixtures/reftests/*.svg")]
fn reftests(name: &str) {
reference_test(name);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]