diff options
author | Marge Bot <marge-bot@gnome.org> | 2023-04-25 23:30:10 +0000 |
---|---|---|
committer | Marge Bot <marge-bot@gnome.org> | 2023-04-25 23:30:10 +0000 |
commit | 30567b3eac0148e3e95f5dd011ff76bda5000a99 (patch) | |
tree | 7d5c56dc2b20f91ccc77aee4dad07830e7eb429a /rsvg/src/test_utils/compare_surfaces.rs | |
parent | d597831ff93b09cc41ce4768a833bc6407c95184 (diff) | |
parent | 7608c94036d7a44296a7e135f42e84aed20afeb7 (diff) | |
download | librsvg-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.rs | 112 |
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, + })) +} |