From f476968693aee6c5bb82edfba53ea1a0f1d44b62 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Fri, 24 Mar 2023 11:41:33 +0100 Subject: [PATCH] core: Move color_transform from BitmapData to bitmap_data_operations --- core/src/avm1/globals/bitmap_data.rs | 13 +++-- .../avm2/globals/flash/display/bitmap_data.rs | 14 +++-- core/src/bitmap/bitmap_data.rs | 44 +-------------- core/src/bitmap/bitmap_data_operations.rs | 53 +++++++++++++++++++ 4 files changed, 74 insertions(+), 50 deletions(-) diff --git a/core/src/avm1/globals/bitmap_data.rs b/core/src/avm1/globals/bitmap_data.rs index 7c5f5596f..182ded7d6 100644 --- a/core/src/avm1/globals/bitmap_data.rs +++ b/core/src/avm1/globals/bitmap_data.rs @@ -630,10 +630,15 @@ pub fn color_transform<'gc>( None => return Ok((-3).into()), }; - bitmap_data - .bitmap_data() - .write(activation.context.gc_context) - .color_transform(x_min, y_min, x_max, y_max, &color_transform.into()); + bitmap_data_operations::color_transform( + &mut activation.context, + bitmap_data.bitmap_data_wrapper(), + x_min, + y_min, + x_max, + y_max, + &color_transform.into(), + ); } } } diff --git a/core/src/avm2/globals/flash/display/bitmap_data.rs b/core/src/avm2/globals/flash/display/bitmap_data.rs index 43d09c56b..193e47b4a 100644 --- a/core/src/avm2/globals/flash/display/bitmap_data.rs +++ b/core/src/avm2/globals/flash/display/bitmap_data.rs @@ -578,8 +578,7 @@ pub fn color_transform<'gc>( this: Option>, args: &[Value<'gc>], ) -> Result, Error<'gc>> { - if let Some(bitmap_data) = this.and_then(|t| t.as_bitmap_data()) { - let mut bitmap_data = bitmap_data.write(activation.context.gc_context); + if let Some(bitmap_data) = this.and_then(|t| t.as_bitmap_data_wrapper()) { if !bitmap_data.disposed() { // TODO: Re-use `object_to_rectangle` in `movie_clip.rs`. let rectangle = args.get_object(activation, 0, "rect")?; @@ -607,7 +606,16 @@ pub fn color_transform<'gc>( color_transform, activation, )?; - bitmap_data.color_transform(x_min, y_min, x_max, y_max, &color_transform); + + bitmap_data_operations::color_transform( + &mut activation.context, + bitmap_data, + x_min, + y_min, + x_max, + y_max, + &color_transform, + ); } } diff --git a/core/src/bitmap/bitmap_data.rs b/core/src/bitmap/bitmap_data.rs index 3a24d1821..c5111eba0 100644 --- a/core/src/bitmap/bitmap_data.rs +++ b/core/src/bitmap/bitmap_data.rs @@ -15,7 +15,7 @@ use ruffle_render::quality::StageQuality; use ruffle_render::transform::Transform; use ruffle_wstr::WStr; use std::ops::Range; -use swf::{BlendMode, ColorTransform, Fixed8, Rectangle, Twips}; +use swf::{BlendMode, Rectangle, Twips}; use tracing::instrument; /// An implementation of the Lehmer/Park-Miller random number generator @@ -622,48 +622,6 @@ impl<'gc> BitmapData<'gc> { self.pixels[(x + y * self.width()) as usize] } - pub fn color_transform( - &mut self, - x_min: u32, - y_min: u32, - x_max: u32, - y_max: u32, - color_transform: &ColorTransform, - ) { - // Flash bug: applying a color transform with only an alpha multiplier > 1 has no effect. - if color_transform.r_multiply != Fixed8::ONE - || color_transform.g_multiply != Fixed8::ONE - || color_transform.b_multiply != Fixed8::ONE - || color_transform.a_multiply < Fixed8::ONE - || color_transform.r_add != 0 - || color_transform.g_add != 0 - || color_transform.b_add != 0 - || color_transform.a_add != 0 - { - let x_max = x_max.min(self.width()); - let y_max = y_max.min(self.height()); - if x_max > 0 && y_max > 0 { - for x in x_min..x_max { - for y in y_min..y_max { - let color = self.get_pixel32_raw(x, y).to_un_multiplied_alpha(); - - let color = color_transform * swf::Color::from(color); - - self.set_pixel32_raw( - x, - y, - Color::from(color).to_premultiplied_alpha(self.transparency()), - ) - } - } - self.set_cpu_dirty(PixelRegion::encompassing_pixels( - (x_min, y_min), - (x_max - 1, y_max - 1), - )); - } - } - } - pub fn color_bounds_rect( &self, find_color: bool, diff --git a/core/src/bitmap/bitmap_data_operations.rs b/core/src/bitmap/bitmap_data_operations.rs index 98bf8b1de..090417b83 100644 --- a/core/src/bitmap/bitmap_data_operations.rs +++ b/core/src/bitmap/bitmap_data_operations.rs @@ -3,6 +3,7 @@ use crate::bitmap::turbulence::Turbulence; use crate::context::UpdateContext; use gc_arena::GcCell; use ruffle_render::bitmap::PixelRegion; +use swf::{ColorTransform, Fixed8}; /// AVM1 and AVM2 have a shared set of operations they can perform on BitmapDatas. /// Instead of directly manipulating the BitmapData in each place, they should call @@ -410,3 +411,55 @@ pub fn copy_channel<'gc>( dirty_region.clamp(write.width(), write.height()); write.set_cpu_dirty(dirty_region); } + +pub fn color_transform<'gc>( + context: &mut UpdateContext<'_, 'gc>, + target: BitmapDataWrapper<'gc>, + x_min: u32, + y_min: u32, + x_max: u32, + y_max: u32, + color_transform: &ColorTransform, +) { + // Flash bug: applying a color transform with only an alpha multiplier > 1 has no effect. + if color_transform.r_multiply == Fixed8::ONE + && color_transform.g_multiply == Fixed8::ONE + && color_transform.b_multiply == Fixed8::ONE + && color_transform.a_multiply >= Fixed8::ONE + && color_transform.r_add == 0 + && color_transform.g_add == 0 + && color_transform.b_add == 0 + && color_transform.a_add == 0 + { + return; + } + + let x_max = x_max.min(target.width()); + let y_max = y_max.min(target.height()); + + if x_max == 0 || y_max == 0 { + return; + } + + let target = target.sync(); + let mut write = target.write(context.gc_context); + let transparency = write.transparency(); + + for x in x_min..x_max { + for y in y_min..y_max { + let color = write.get_pixel32_raw(x, y).to_un_multiplied_alpha(); + + let color = color_transform * swf::Color::from(color); + + write.set_pixel32_raw( + x, + y, + Color::from(color).to_premultiplied_alpha(transparency), + ) + } + } + write.set_cpu_dirty(PixelRegion::encompassing_pixels( + (x_min, y_min), + (x_max - 1, y_max - 1), + )); +}