From 2c65f23eb8c6d94ad04b72718f8b01682eba006b Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Fri, 24 Mar 2023 12:20:57 +0100 Subject: [PATCH] core: Move compare from BitmapData to bitmap_data_operations --- core/src/avm1/globals/bitmap_data.rs | 8 +-- core/src/bitmap/bitmap_data.rs | 68 ++++++----------------- core/src/bitmap/bitmap_data_operations.rs | 54 ++++++++++++++++++ 3 files changed, 75 insertions(+), 55 deletions(-) diff --git a/core/src/avm1/globals/bitmap_data.rs b/core/src/avm1/globals/bitmap_data.rs index 5897dc7bb..2899b86ce 100644 --- a/core/src/avm1/globals/bitmap_data.rs +++ b/core/src/avm1/globals/bitmap_data.rs @@ -1365,10 +1365,8 @@ pub fn compare<'gc>( return Ok(BITMAP_DISPOSED.into()); } - let this_bitmap_data = this_bitmap_data.bitmap_data(); - let this_bitmap_data = this_bitmap_data.read(); - let other_bitmap_data = other_bitmap_data.bitmap_data(); - let other_bitmap_data = other_bitmap_data.read(); + let this_bitmap_data = this_bitmap_data.bitmap_data_wrapper(); + let other_bitmap_data = other_bitmap_data.bitmap_data_wrapper(); if this_bitmap_data.width() != other_bitmap_data.width() { return Ok(DIFFERENT_WIDTHS.into()); @@ -1378,7 +1376,7 @@ pub fn compare<'gc>( return Ok(DIFFERENT_HEIGHTS.into()); } - match BitmapData::compare(&this_bitmap_data, &other_bitmap_data) { + match bitmap_data_operations::compare(this_bitmap_data, other_bitmap_data) { Some(bitmap_data) => Ok(BitmapDataObject::with_bitmap_data( activation.context.gc_context, activation.context.avm1.prototypes().bitmap_data, diff --git a/core/src/bitmap/bitmap_data.rs b/core/src/bitmap/bitmap_data.rs index 1f9ac6c20..870f8ba17 100644 --- a/core/src/bitmap/bitmap_data.rs +++ b/core/src/bitmap/bitmap_data.rs @@ -450,6 +450,24 @@ impl<'gc> BitmapData<'gc> { self.set_cpu_dirty(PixelRegion::for_whole_size(width, height)); } + pub fn new_with_pixels( + width: u32, + height: u32, + transparency: bool, + pixels: Vec, + ) -> Self { + Self { + pixels, + width, + height, + transparency, + bitmap_handle: None, + avm2_object: None, + disposed: false, + dirty_state: DirtyState::Clean, + } + } + pub fn check_valid( &self, activation: &mut crate::avm2::Activation<'_, 'gc>, @@ -839,56 +857,6 @@ impl<'gc> BitmapData<'gc> { } } - /// Compare two BitmapData objects. - /// Returns `None` if the bitmaps are equivalent. - pub fn compare(bitmap: &Self, other: &Self) -> Option { - // This function expects that the two bitmaps have the same dimensions. - // TODO: Relax this assumption and return a special value instead? - debug_assert_eq!(bitmap.width, other.width); - debug_assert_eq!(bitmap.height, other.height); - - let mut different = false; - let pixels = bitmap - .pixels - .iter() - .zip(&other.pixels) - .map(|(bitmap_pixel, other_pixel)| { - let bitmap_pixel = bitmap_pixel.to_un_multiplied_alpha(); - let other_pixel = other_pixel.to_un_multiplied_alpha(); - if bitmap_pixel == other_pixel { - Color::argb(0, 0, 0, 0) - } else if bitmap_pixel.with_alpha(0) != other_pixel.with_alpha(0) { - different = true; - Color::argb( - 0xff, - bitmap_pixel.red().wrapping_sub(other_pixel.red()), - bitmap_pixel.green().wrapping_sub(other_pixel.green()), - bitmap_pixel.blue().wrapping_sub(other_pixel.blue()), - ) - } else { - different = true; - let alpha = bitmap_pixel.alpha().wrapping_sub(other_pixel.alpha()); - Color::argb(alpha, alpha, alpha, alpha) - } - }) - .collect(); - - if different { - Some(Self { - pixels, - width: bitmap.width, - height: bitmap.height, - transparency: true, - bitmap_handle: None, - avm2_object: None, - disposed: false, - dirty_state: DirtyState::Clean, - }) - } else { - None - } - } - pub fn object2(&self) -> Avm2Value<'gc> { self.avm2_object .map(|o| o.into()) diff --git a/core/src/bitmap/bitmap_data_operations.rs b/core/src/bitmap/bitmap_data_operations.rs index 1791f1196..4d04a0c68 100644 --- a/core/src/bitmap/bitmap_data_operations.rs +++ b/core/src/bitmap/bitmap_data_operations.rs @@ -672,3 +672,57 @@ pub fn palette_map<'gc>( dirty_region.clamp(write.width(), write.height()); write.set_cpu_dirty(dirty_region); } + +/// Compare two BitmapData objects. +/// Returns `None` if the bitmaps are equivalent. +pub fn compare<'gc>( + left: BitmapDataWrapper<'gc>, + right: BitmapDataWrapper<'gc>, +) -> Option> { + // This function expects that the two bitmaps have the same dimensions. + // TODO: Relax this assumption and return a special value instead? + debug_assert_eq!(left.width(), right.width()); + debug_assert_eq!(left.height(), right.height()); + + let left = left.sync(); + let left = left.read(); + let right = right.sync(); + let right = right.read(); + + let mut different = false; + let pixels = left + .pixels() + .iter() + .zip(right.pixels()) + .map(|(bitmap_pixel, other_pixel)| { + let bitmap_pixel = bitmap_pixel.to_un_multiplied_alpha(); + let other_pixel = other_pixel.to_un_multiplied_alpha(); + if bitmap_pixel == other_pixel { + Color::argb(0, 0, 0, 0) + } else if bitmap_pixel.with_alpha(0) != other_pixel.with_alpha(0) { + different = true; + Color::argb( + 0xff, + bitmap_pixel.red().wrapping_sub(other_pixel.red()), + bitmap_pixel.green().wrapping_sub(other_pixel.green()), + bitmap_pixel.blue().wrapping_sub(other_pixel.blue()), + ) + } else { + different = true; + let alpha = bitmap_pixel.alpha().wrapping_sub(other_pixel.alpha()); + Color::argb(alpha, alpha, alpha, alpha) + } + }) + .collect(); + + if different { + Some(BitmapData::new_with_pixels( + left.width(), + left.height(), + true, + pixels, + )) + } else { + None + } +}