summaryrefslogtreecommitdiff
path: root/rsvg/src/test_utils/compare_surfaces.rs
diff options
context:
space:
mode:
authorMarge Bot <marge-bot@gnome.org>2023-04-25 23:30:10 +0000
committerMarge Bot <marge-bot@gnome.org>2023-04-25 23:30:10 +0000
commit30567b3eac0148e3e95f5dd011ff76bda5000a99 (patch)
tree7d5c56dc2b20f91ccc77aee4dad07830e7eb429a /rsvg/src/test_utils/compare_surfaces.rs
parentd597831ff93b09cc41ce4768a833bc6407c95184 (diff)
parent7608c94036d7a44296a7e135f42e84aed20afeb7 (diff)
downloadlibrsvg-30567b3eac0148e3e95f5dd011ff76bda5000a99.tar.gz
Merge branch 'wip/sophie-h/workspace' into 'main'
meta: Move lib and bins into separate crates Closes #950 See merge request GNOME/librsvg!822
Diffstat (limited to 'rsvg/src/test_utils/compare_surfaces.rs')
-rw-r--r--rsvg/src/test_utils/compare_surfaces.rs112
1 files changed, 112 insertions, 0 deletions
diff --git a/rsvg/src/test_utils/compare_surfaces.rs b/rsvg/src/test_utils/compare_surfaces.rs
new file mode 100644
index 00000000..06100db9
--- /dev/null
+++ b/rsvg/src/test_utils/compare_surfaces.rs
@@ -0,0 +1,112 @@
+use std::fmt;
+
+use crate::surface_utils::{
+ iterators::Pixels,
+ shared_surface::{SharedImageSurface, SurfaceType},
+ ImageSurfaceDataExt, Pixel, PixelOps,
+};
+
+use rgb::{ComponentMap, RGB};
+
+pub enum BufferDiff {
+ DifferentSizes,
+ Diff(Diff),
+}
+
+pub struct Diff {
+ pub num_pixels_changed: usize,
+ pub max_diff: u8,
+ pub surface: SharedImageSurface,
+}
+
+impl fmt::Display for BufferDiff {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ BufferDiff::DifferentSizes => write!(f, "different sizes"),
+ BufferDiff::Diff(diff) => diff.fmt(f),
+ }
+ }
+}
+
+impl fmt::Display for Diff {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "{} pixels are different, with a maximum difference of {}",
+ self.num_pixels_changed, self.max_diff
+ )
+ }
+}
+
+#[inline]
+fn emphasize(p: &Pixel) -> Pixel {
+ let emphasize_component = |c| {
+ // emphasize
+ let mut c = c as u32 * 4;
+ // make sure it's visible
+ if c > 0 {
+ c += 128;
+ }
+ c.min(255) as u8
+ };
+ p.map(emphasize_component)
+}
+
+pub fn compare_surfaces(
+ surf_a: &SharedImageSurface,
+ surf_b: &SharedImageSurface,
+) -> Result<BufferDiff, cairo::Error> {
+ 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 = cairo::ImageSurface::create(cairo::Format::ARgb32, a_width, a_height)?;
+ let diff_stride = surf_diff.stride() as usize;
+
+ let mut num_pixels_changed = 0;
+ let mut max_diff = 0;
+
+ let black = Pixel::default().alpha(255);
+
+ {
+ let mut diff_data = surf_diff.data().unwrap();
+
+ for ((xa, ya, pixel_a), (_, _, pixel_b)) in Pixels::new(surf_a).zip(Pixels::new(surf_b)) {
+ let dest = if pixel_a != pixel_b {
+ num_pixels_changed += 1;
+
+ let pixel_diff = pixel_a.diff(&pixel_b);
+
+ max_diff = pixel_diff.iter().fold(max_diff, |acc, c| acc.max(c));
+
+ let pixel_diff = emphasize(&pixel_diff);
+
+ if pixel_diff.rgb() == RGB::default() {
+ // alpha only difference; convert alpha to gray
+ let a = pixel_diff.a;
+ pixel_diff.map_rgb(|_| a)
+ } else {
+ pixel_diff.alpha(255)
+ }
+ } else {
+ black
+ };
+
+ diff_data.set_pixel(diff_stride, dest, xa, ya);
+ }
+ }
+
+ let surface = SharedImageSurface::wrap(surf_diff, SurfaceType::SRgb)?;
+
+ Ok(BufferDiff::Diff(Diff {
+ num_pixels_changed,
+ max_diff,
+ surface,
+ }))
+}