[librsvg] librsvg_crate/tests/compare_surfaces.rs: New file, port of test_utils_compare_surfaces() to Rust



commit 49c18f068419c9882c94c4c24b7ad16889e0b6a9
Author: Federico Mena Quintero <federico gnome org>
Date:   Fri Mar 1 19:45:48 2019 -0600

    librsvg_crate/tests/compare_surfaces.rs: New file, port of test_utils_compare_surfaces() to Rust

 librsvg_crate/Cargo.toml                |   1 +
 librsvg_crate/tests/compare_surfaces.rs | 140 ++++++++++++++++++++++++++++++++
 rsvg_internals/src/lib.rs               |   2 +
 rsvg_internals/src/surface_utils/mod.rs |  20 +++++
 4 files changed, 163 insertions(+)
---
diff --git a/librsvg_crate/Cargo.toml b/librsvg_crate/Cargo.toml
index c4a9aa2b..8e6ce710 100644
--- a/librsvg_crate/Cargo.toml
+++ b/librsvg_crate/Cargo.toml
@@ -17,6 +17,7 @@ url = "1.7.2"
 
 [dev-dependencies]
 cairo-rs = { version = "0.6.0", features = ["png"] }
+rsvg_internals = { path = "../rsvg_internals" }
 
 [build-dependencies]
 pkg-config = "0.3.14"
diff --git a/librsvg_crate/tests/compare_surfaces.rs b/librsvg_crate/tests/compare_surfaces.rs
new file mode 100644
index 00000000..229f494c
--- /dev/null
+++ b/librsvg_crate/tests/compare_surfaces.rs
@@ -0,0 +1,140 @@
+extern crate cairo;
+extern crate rsvg_internals;
+
+use cairo::ImageSurface;
+
+use rsvg_internals::{IRect, RenderingError};
+use rsvg_internals::surface_utils::{
+    iterators::Pixels,
+    shared_surface::{SharedImageSurface, SurfaceType},
+    ImageSurfaceDataExt,
+    Pixel,
+};
+
+pub enum BufferDiff {
+    DifferentSizes,
+    Diff(Diff),
+}
+
+pub struct Diff {
+    num_pixels_changed: usize,
+    max_diff: u8,
+    surface: SharedImageSurface,
+}
+
+#[inline]
+fn pixel_max(p: &Pixel) -> u8 {
+    p.r.max(p.g).max(p.b).max(p.a)
+}
+
+#[inline]
+fn emphasize(p: &Pixel) -> Pixel {
+    let mut r = p.r as u32;
+    let mut g = p.g as u32;
+    let mut b = p.b as u32;
+    let mut a = p.a as u32;
+
+    // emphasize
+    r = r * 4;
+    g = g * 4;
+    b = b * 4;
+    a = a * 4;
+
+    // make sure they are visible
+    if r > 0 {
+        r += 128;
+    }
+
+    if g > 0 {
+        g += 128;
+    }
+
+    if b > 0 {
+        b += 128;
+    }
+
+    if a > 0 {
+        a += 128;
+    }
+
+    let r = r.min(255) as u8;
+    let g = g.min(255) as u8;
+    let b = b.min(255) as u8;
+    let a = a.min(255) as u8;
+
+    Pixel { r, g, b, a }
+}
+
+pub fn compare_surfaces(
+    surf_a: &SharedImageSurface,
+    surf_b: &SharedImageSurface,
+) -> Result<BufferDiff, RenderingError> {
+    let a_width = surf_a.width();
+    let a_height = surf_a.height();
+
+    let b_width = surf_b.width();
+    let b_height = surf_b.height();
+
+    if a_width != b_width || a_height != b_height {
+        return Ok(BufferDiff::DifferentSizes);
+    }
+
+    let mut surf_diff = ImageSurface::create(cairo::Format::ARgb32, a_width, a_height)?;
+    let diff_stride = surf_diff.get_stride() as usize;
+
+    let bounds = IRect {
+        x0: 0,
+        y0: 0,
+        x1: a_width,
+        y1: a_height,
+    };
+
+    let mut num_pixels_changed = 0;
+    let mut max_diff = 0;
+
+    {
+        let mut diff_data = surf_diff.get_data().unwrap();
+
+        for ((xa, ya, pixel_a), (_, _, pixel_b)) in
+            Pixels::new(surf_a, bounds).zip(Pixels::new(surf_b, bounds))
+        {
+            if pixel_a != pixel_b {
+                num_pixels_changed += 1;
+
+                let pixel_diff = pixel_a.diff(&pixel_b);
+
+                let pixel_max_diff = pixel_max(&pixel_diff);
+
+                max_diff = max_diff.max(pixel_max_diff);
+
+                let mut pixel_diff = emphasize(&pixel_diff);
+
+                if pixel_diff.r == 0 && pixel_diff.g == 0 && pixel_diff.b == 0 {
+                    // alpha only difference; convert alpha to gray
+
+                    pixel_diff.r = pixel_diff.a;
+                    pixel_diff.g = pixel_diff.a;
+                    pixel_diff.b = pixel_diff.a;
+                }
+
+                diff_data.set_pixel(diff_stride, pixel_diff, xa, ya);
+            } else {
+                let black = Pixel {
+                    r: 0,
+                    g: 0,
+                    b: 0,
+                    a: 0,
+                };
+                diff_data.set_pixel(diff_stride, black, xa, ya);
+            }
+        }
+    }
+
+    let surface = SharedImageSurface::new(surf_diff, SurfaceType::SRgb)?;
+
+    Ok(BufferDiff::Diff(Diff {
+        num_pixels_changed,
+        max_diff,
+        surface,
+    }))
+}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 5f9b9b94..df93fa7f 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -101,6 +101,8 @@ pub use pixbuf_utils::{
     rsvg_rust_pixbuf_from_file_at_zoom_with_max,
 };
 
+pub use rect::IRect;
+
 #[macro_use]
 mod log;
 
diff --git a/rsvg_internals/src/surface_utils/mod.rs b/rsvg_internals/src/surface_utils/mod.rs
index 00a58306..efc28542 100644
--- a/rsvg_internals/src/surface_utils/mod.rs
+++ b/rsvg_internals/src/surface_utils/mod.rs
@@ -125,6 +125,26 @@ impl Pixel {
             a: (((r * 14042 + g * 47240 + b * 4769) * o) >> 24) as u8,
         }
     }
+
+    #[inline]
+    pub fn diff(self, p: &Pixel) -> Pixel {
+        let a_r = self.r as i32;
+        let a_g = self.g as i32;
+        let a_b = self.b as i32;
+        let a_a = self.a as i32;
+
+        let b_r = p.r as i32;
+        let b_g = p.g as i32;
+        let b_b = p.b as i32;
+        let b_a = p.a as i32;
+
+        let r = (a_r - b_r).abs() as u8;
+        let g = (a_g - b_g).abs() as u8;
+        let b = (a_b - b_b).abs() as u8;
+        let a = (a_a - b_a).abs() as u8;
+
+        Pixel { r, g, b, a }
+    }
 }
 
 impl<'a> ImageSurfaceDataExt for cairo::ImageSurfaceData<'a> {}


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