From 54740d6093825b74af8d6c8428706b6342a8f1b4 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Thu, 2 Sep 2021 20:22:17 -0400 Subject: [PATCH] core: Allow `BitmapData` to hold an AVM2 side. --- core/src/avm1/object/bitmap_data.rs | 4 ++-- core/src/avm2/object.rs | 10 ++++++--- core/src/avm2/object/bitmapdata_object.rs | 16 +++++++++++---- core/src/bitmap/bitmap_data.rs | 25 +++++++++++++++++++++-- core/src/display_object/bitmap.rs | 8 ++++---- 5 files changed, 48 insertions(+), 15 deletions(-) diff --git a/core/src/avm1/object/bitmap_data.rs b/core/src/avm1/object/bitmap_data.rs index 11584911c..21eee60dc 100644 --- a/core/src/avm1/object/bitmap_data.rs +++ b/core/src/avm1/object/bitmap_data.rs @@ -16,7 +16,7 @@ pub struct BitmapDataObject<'gc>(GcCell<'gc, BitmapDataData<'gc>>); pub struct BitmapDataData<'gc> { /// The underlying script object. base: ScriptObject<'gc>, - data: GcCell<'gc, BitmapData>, + data: GcCell<'gc, BitmapData<'gc>>, disposed: bool, } @@ -32,7 +32,7 @@ impl fmt::Debug for BitmapDataObject<'_> { impl<'gc> BitmapDataObject<'gc> { add_field_accessors!( [disposed, bool, get => disposed], - [data, GcCell<'gc, BitmapData>, set => set_bitmap_data, get => bitmap_data], + [data, GcCell<'gc, BitmapData<'gc>>, set => set_bitmap_data, get => bitmap_data], ); pub fn empty_object(gc_context: MutationContext<'gc, '_>, proto: Option>) -> Self { diff --git a/core/src/avm2/object.rs b/core/src/avm2/object.rs index 77dd58d54..5a42d2f6e 100644 --- a/core/src/avm2/object.rs +++ b/core/src/avm2/object.rs @@ -1243,16 +1243,20 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into> + Clone + Copy fn set_sound_instance(self, _mc: MutationContext<'gc, '_>, _sound: SoundInstanceHandle) {} /// Unwrap this object's bitmap data - fn as_bitmap_data(&self) -> Option> { + fn as_bitmap_data(&self) -> Option>> { None } /// Initialize the bitmap data in this object, if it's capable of - /// supporting said data + /// supporting said data. + /// + /// This should only be called to initialize the association between an AVM + /// object and it's associated bitmap data. This association should not be + /// reinitialized later. fn init_bitmap_data( &self, _mc: MutationContext<'gc, '_>, - _new_bitmap: GcCell<'gc, BitmapData>, + _new_bitmap: GcCell<'gc, BitmapData<'gc>>, ) { } } diff --git a/core/src/avm2/object/bitmapdata_object.rs b/core/src/avm2/object/bitmapdata_object.rs index 7a7965767..0c31f1dc8 100644 --- a/core/src/avm2/object/bitmapdata_object.rs +++ b/core/src/avm2/object/bitmapdata_object.rs @@ -43,13 +43,13 @@ pub struct BitmapDataObjectData<'gc> { /// Base script object base: ScriptObjectData<'gc>, - bitmap_data: Option>, + bitmap_data: Option>>, } impl<'gc> BitmapDataObject<'gc> { pub fn from_bitmap_data( activation: &mut Activation<'_, 'gc, '_>, - bitmap_data: GcCell<'gc, BitmapData>, + bitmap_data: GcCell<'gc, BitmapData<'gc>>, class: Object<'gc>, ) -> Result, Error> { let proto = class @@ -67,6 +67,10 @@ impl<'gc> BitmapDataObject<'gc> { bitmap_data: Some(bitmap_data), }, )); + + bitmap_data + .write(activation.context.gc_context) + .init_object2(instance.into()); instance.install_instance_traits(activation, class)?; class.call_native_init(Some(instance.into()), &[], activation, Some(class))?; @@ -101,13 +105,17 @@ impl<'gc> TObject<'gc> for BitmapDataObject<'gc> { } /// Unwrap this object's bitmap data - fn as_bitmap_data(&self) -> Option> { + fn as_bitmap_data(&self) -> Option>> { self.0.read().bitmap_data } /// Initialize the bitmap data in this object, if it's capable of /// supporting said data - fn init_bitmap_data(&self, mc: MutationContext<'gc, '_>, new_bitmap: GcCell<'gc, BitmapData>) { + fn init_bitmap_data( + &self, + mc: MutationContext<'gc, '_>, + new_bitmap: GcCell<'gc, BitmapData<'gc>>, + ) { self.0.write(mc).bitmap_data = Some(new_bitmap) } } diff --git a/core/src/bitmap/bitmap_data.rs b/core/src/bitmap/bitmap_data.rs index 823aa566a..068440ba6 100644 --- a/core/src/bitmap/bitmap_data.rs +++ b/core/src/bitmap/bitmap_data.rs @@ -1,5 +1,6 @@ use gc_arena::Collect; +use crate::avm2::{Object as Avm2Object, Value as Avm2Value}; use crate::backend::render::{BitmapHandle, RenderBackend}; use crate::bitmap::color_transform_params::ColorTransformParams; use crate::bitmap::turbulence::Turbulence; @@ -130,7 +131,7 @@ bitflags! { #[derive(Clone, Collect, Default, Debug)] #[collect(no_drop)] -pub struct BitmapData { +pub struct BitmapData<'gc> { /// The pixels in the bitmap, stored as a array of pre-multiplied ARGB colour values pub pixels: Vec, dirty: bool, @@ -138,10 +139,20 @@ pub struct BitmapData { height: u32, transparency: bool, + /// The bitmap handle for this data. + /// + /// This is lazily initialized; a value of `None` indicates that + /// initialization has not yet happened. bitmap_handle: Option, + + /// The AVM2 side of this `BitmapData`. + /// + /// AVM1 cannot retrieve `BitmapData` back from the display object tree, so + /// this does not need to hold an AVM1 object. + avm2_object: Option>, } -impl BitmapData { +impl<'gc> BitmapData<'gc> { pub fn init_pixels(&mut self, width: u32, height: u32, transparency: bool, fill_color: i32) { self.width = width; self.height = height; @@ -842,4 +853,14 @@ impl BitmapData { src_y += dy; } } + + pub fn object2(&self) -> Avm2Value<'gc> { + self.avm2_object + .map(|o| o.into()) + .unwrap_or(Avm2Value::Undefined) + } + + pub fn init_object2(&mut self, object: Avm2Object<'gc>) { + self.avm2_object = Some(object) + } } diff --git a/core/src/display_object/bitmap.rs b/core/src/display_object/bitmap.rs index ce38b2b43..66b96c77e 100644 --- a/core/src/display_object/bitmap.rs +++ b/core/src/display_object/bitmap.rs @@ -31,7 +31,7 @@ pub struct BitmapData<'gc> { static_data: Gc<'gc, BitmapStatic>, /// The current bitmap data object. - bitmap_data: Option>, + bitmap_data: Option>>, /// The current bitmap handle. /// @@ -59,7 +59,7 @@ impl<'gc> Bitmap<'gc> { bitmap_handle: BitmapHandle, width: u16, height: u16, - bitmap_data: Option>, + bitmap_data: Option>>, smoothing: bool, ) -> Self { let bitmap_handle = bitmap_data @@ -112,7 +112,7 @@ impl<'gc> Bitmap<'gc> { } /// Retrieve the bitmap data associated with this `Bitmap`. - pub fn bitmap_data(self) -> Option> { + pub fn bitmap_data(self) -> Option>> { self.0.read().bitmap_data } @@ -127,7 +127,7 @@ impl<'gc> Bitmap<'gc> { pub fn set_bitmap_data( self, context: &mut UpdateContext<'_, 'gc, '_>, - bitmap_data: GcCell<'gc, crate::bitmap::bitmap_data::BitmapData>, + bitmap_data: GcCell<'gc, crate::bitmap::bitmap_data::BitmapData<'gc>>, ) { let bitmap_handle = bitmap_data .write(context.gc_context)