avm1: Added BitmapData::compare

This commit is contained in:
bbb651 2021-10-08 18:14:44 +03:00 committed by relrelb
parent 3760e0e275
commit 687069ba7d
2 changed files with 93 additions and 0 deletions

View File

@ -40,6 +40,7 @@ const PROTO_DECLS: &[Declaration] = declare_properties! {
"pixelDissolve" => method(pixel_dissolve);
"scroll" => method(scroll);
"threshold" => method(threshold);
"compare" => method(compare);
};
const OBJECT_DECLS: &[Declaration] = declare_properties! {
@ -1063,6 +1064,69 @@ pub fn threshold<'gc>(
Ok((-1).into())
}
pub fn compare<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(bitmap_data) = this.as_bitmap_data_object() {
if bitmap_data.disposed() {
return Ok((-2).into());
}
let other_bitmap = args
.get(0)
.unwrap_or(&Value::Undefined)
.coerce_to_object(activation);
if let Some(other_bitmap_data) = other_bitmap.as_bitmap_data_object() {
if other_bitmap_data.disposed() {
return Ok((-2).into());
}
if bitmap_data.bitmap_data().read().width()
!= other_bitmap_data.bitmap_data().read().width()
{
return Ok((-3).into());
}
if bitmap_data.bitmap_data().read().height()
!= other_bitmap_data.bitmap_data().read().height()
{
return Ok((-4).into());
}
if bitmap_data
.bitmap_data()
.read()
.pixels()
.eq(other_bitmap_data.bitmap_data().read().pixels())
{
return Ok((0).into());
}
let new_bitmap_data = BitmapDataObject::empty_object(
activation.context.gc_context,
Some(activation.context.avm1.prototypes.bitmap_data),
);
new_bitmap_data
.as_bitmap_data_object()
.unwrap()
.bitmap_data()
.write(activation.context.gc_context)
.compare(
&bitmap_data.bitmap_data().read(),
&other_bitmap_data.bitmap_data().read(),
);
return Ok(new_bitmap_data.into());
}
return Ok(Value::Undefined);
}
Ok((-1).into())
}
pub fn create_proto<'gc>(
gc_context: MutationContext<'gc, '_>,
proto: Object<'gc>,

View File

@ -854,6 +854,35 @@ impl<'gc> BitmapData<'gc> {
}
}
pub fn compare(&mut self, bitmap: &Self, other: &Self) {
// Should be replaced with i32::abs_diff once stabilized (https://github.com/rust-lang/rust/issues/89492)
fn abs_diff(a: i32, b: i32) -> i32 {
if a > b {
a.wrapping_sub(b)
} else {
b.wrapping_sub(a)
}
}
for i in 0..self.pixels().len() {
let bitmap_pixel = bitmap.pixels()[i];
let other_pixel = other.pixels()[i];
self.pixels[i] = Color(
if bitmap_pixel.with_alpha(0xffu8) != other_pixel.with_alpha(0xffu8) {
(0xff << 24)
+ (abs_diff(bitmap_pixel.red() as i32, other_pixel.red() as i32) << 16)
+ (abs_diff(bitmap_pixel.green() as i32, other_pixel.green() as i32) << 8)
+ abs_diff(bitmap_pixel.blue() as i32, other_pixel.blue() as i32)
} else if bitmap_pixel.alpha() != other_pixel.alpha() {
(abs_diff(bitmap_pixel.alpha() as i32, other_pixel.alpha() as i32) << 24)
+ 0xffffff
} else {
0
},
)
}
}
pub fn object2(&self) -> Avm2Value<'gc> {
self.avm2_object
.map(|o| o.into())