core: Allow `BitmapData` to hold an AVM2 side.

This commit is contained in:
David Wendt 2021-09-02 20:22:17 -04:00 committed by Mike Welsh
parent 10b98f72f5
commit 54740d6093
5 changed files with 48 additions and 15 deletions

View File

@ -16,7 +16,7 @@ pub struct BitmapDataObject<'gc>(GcCell<'gc, BitmapDataData<'gc>>);
pub struct BitmapDataData<'gc> { pub struct BitmapDataData<'gc> {
/// The underlying script object. /// The underlying script object.
base: ScriptObject<'gc>, base: ScriptObject<'gc>,
data: GcCell<'gc, BitmapData>, data: GcCell<'gc, BitmapData<'gc>>,
disposed: bool, disposed: bool,
} }
@ -32,7 +32,7 @@ impl fmt::Debug for BitmapDataObject<'_> {
impl<'gc> BitmapDataObject<'gc> { impl<'gc> BitmapDataObject<'gc> {
add_field_accessors!( add_field_accessors!(
[disposed, bool, get => disposed], [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<Object<'gc>>) -> Self { pub fn empty_object(gc_context: MutationContext<'gc, '_>, proto: Option<Object<'gc>>) -> Self {

View File

@ -1243,16 +1243,20 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
fn set_sound_instance(self, _mc: MutationContext<'gc, '_>, _sound: SoundInstanceHandle) {} fn set_sound_instance(self, _mc: MutationContext<'gc, '_>, _sound: SoundInstanceHandle) {}
/// Unwrap this object's bitmap data /// Unwrap this object's bitmap data
fn as_bitmap_data(&self) -> Option<GcCell<'gc, BitmapData>> { fn as_bitmap_data(&self) -> Option<GcCell<'gc, BitmapData<'gc>>> {
None None
} }
/// Initialize the bitmap data in this object, if it's capable of /// 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( fn init_bitmap_data(
&self, &self,
_mc: MutationContext<'gc, '_>, _mc: MutationContext<'gc, '_>,
_new_bitmap: GcCell<'gc, BitmapData>, _new_bitmap: GcCell<'gc, BitmapData<'gc>>,
) { ) {
} }
} }

View File

@ -43,13 +43,13 @@ pub struct BitmapDataObjectData<'gc> {
/// Base script object /// Base script object
base: ScriptObjectData<'gc>, base: ScriptObjectData<'gc>,
bitmap_data: Option<GcCell<'gc, BitmapData>>, bitmap_data: Option<GcCell<'gc, BitmapData<'gc>>>,
} }
impl<'gc> BitmapDataObject<'gc> { impl<'gc> BitmapDataObject<'gc> {
pub fn from_bitmap_data( pub fn from_bitmap_data(
activation: &mut Activation<'_, 'gc, '_>, activation: &mut Activation<'_, 'gc, '_>,
bitmap_data: GcCell<'gc, BitmapData>, bitmap_data: GcCell<'gc, BitmapData<'gc>>,
class: Object<'gc>, class: Object<'gc>,
) -> Result<Object<'gc>, Error> { ) -> Result<Object<'gc>, Error> {
let proto = class let proto = class
@ -67,6 +67,10 @@ impl<'gc> BitmapDataObject<'gc> {
bitmap_data: Some(bitmap_data), bitmap_data: Some(bitmap_data),
}, },
)); ));
bitmap_data
.write(activation.context.gc_context)
.init_object2(instance.into());
instance.install_instance_traits(activation, class)?; instance.install_instance_traits(activation, class)?;
class.call_native_init(Some(instance.into()), &[], activation, Some(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 /// Unwrap this object's bitmap data
fn as_bitmap_data(&self) -> Option<GcCell<'gc, BitmapData>> { fn as_bitmap_data(&self) -> Option<GcCell<'gc, BitmapData<'gc>>> {
self.0.read().bitmap_data self.0.read().bitmap_data
} }
/// Initialize the bitmap data in this object, if it's capable of /// Initialize the bitmap data in this object, if it's capable of
/// supporting said data /// 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) self.0.write(mc).bitmap_data = Some(new_bitmap)
} }
} }

View File

@ -1,5 +1,6 @@
use gc_arena::Collect; use gc_arena::Collect;
use crate::avm2::{Object as Avm2Object, Value as Avm2Value};
use crate::backend::render::{BitmapHandle, RenderBackend}; use crate::backend::render::{BitmapHandle, RenderBackend};
use crate::bitmap::color_transform_params::ColorTransformParams; use crate::bitmap::color_transform_params::ColorTransformParams;
use crate::bitmap::turbulence::Turbulence; use crate::bitmap::turbulence::Turbulence;
@ -130,7 +131,7 @@ bitflags! {
#[derive(Clone, Collect, Default, Debug)] #[derive(Clone, Collect, Default, Debug)]
#[collect(no_drop)] #[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 /// The pixels in the bitmap, stored as a array of pre-multiplied ARGB colour values
pub pixels: Vec<Color>, pub pixels: Vec<Color>,
dirty: bool, dirty: bool,
@ -138,10 +139,20 @@ pub struct BitmapData {
height: u32, height: u32,
transparency: bool, 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<BitmapHandle>, bitmap_handle: Option<BitmapHandle>,
/// 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<Avm2Object<'gc>>,
} }
impl BitmapData { impl<'gc> BitmapData<'gc> {
pub fn init_pixels(&mut self, width: u32, height: u32, transparency: bool, fill_color: i32) { pub fn init_pixels(&mut self, width: u32, height: u32, transparency: bool, fill_color: i32) {
self.width = width; self.width = width;
self.height = height; self.height = height;
@ -842,4 +853,14 @@ impl BitmapData {
src_y += dy; 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)
}
} }

View File

@ -31,7 +31,7 @@ pub struct BitmapData<'gc> {
static_data: Gc<'gc, BitmapStatic>, static_data: Gc<'gc, BitmapStatic>,
/// The current bitmap data object. /// The current bitmap data object.
bitmap_data: Option<GcCell<'gc, crate::bitmap::bitmap_data::BitmapData>>, bitmap_data: Option<GcCell<'gc, crate::bitmap::bitmap_data::BitmapData<'gc>>>,
/// The current bitmap handle. /// The current bitmap handle.
/// ///
@ -59,7 +59,7 @@ impl<'gc> Bitmap<'gc> {
bitmap_handle: BitmapHandle, bitmap_handle: BitmapHandle,
width: u16, width: u16,
height: u16, height: u16,
bitmap_data: Option<GcCell<'gc, crate::bitmap::bitmap_data::BitmapData>>, bitmap_data: Option<GcCell<'gc, crate::bitmap::bitmap_data::BitmapData<'gc>>>,
smoothing: bool, smoothing: bool,
) -> Self { ) -> Self {
let bitmap_handle = bitmap_data let bitmap_handle = bitmap_data
@ -112,7 +112,7 @@ impl<'gc> Bitmap<'gc> {
} }
/// Retrieve the bitmap data associated with this `Bitmap`. /// Retrieve the bitmap data associated with this `Bitmap`.
pub fn bitmap_data(self) -> Option<GcCell<'gc, crate::bitmap::bitmap_data::BitmapData>> { pub fn bitmap_data(self) -> Option<GcCell<'gc, crate::bitmap::bitmap_data::BitmapData<'gc>>> {
self.0.read().bitmap_data self.0.read().bitmap_data
} }
@ -127,7 +127,7 @@ impl<'gc> Bitmap<'gc> {
pub fn set_bitmap_data( pub fn set_bitmap_data(
self, self,
context: &mut UpdateContext<'_, 'gc, '_>, 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 let bitmap_handle = bitmap_data
.write(context.gc_context) .write(context.gc_context)