avm1: Migrate `BitmapData` to `NativeObject`
This commit is contained in:
parent
5d48484d99
commit
c230dcf0f8
|
@ -508,7 +508,6 @@ pub struct SystemPrototypes<'gc> {
|
||||||
pub gradient_glow_filter: Object<'gc>,
|
pub gradient_glow_filter: Object<'gc>,
|
||||||
pub gradient_glow_filter_constructor: Object<'gc>,
|
pub gradient_glow_filter_constructor: Object<'gc>,
|
||||||
pub date_constructor: Object<'gc>,
|
pub date_constructor: Object<'gc>,
|
||||||
pub bitmap_data: Object<'gc>,
|
|
||||||
pub bitmap_data_constructor: Object<'gc>,
|
pub bitmap_data_constructor: Object<'gc>,
|
||||||
pub video: Object<'gc>,
|
pub video: Object<'gc>,
|
||||||
pub video_constructor: Object<'gc>,
|
pub video_constructor: Object<'gc>,
|
||||||
|
@ -863,9 +862,7 @@ pub fn create_globals<'gc>(
|
||||||
Attribute::empty(),
|
Attribute::empty(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let bitmap_data_proto = bitmap_data::create_proto(context, object_proto, function_proto);
|
let bitmap_data = bitmap_data::create_constructor(context, object_proto, function_proto);
|
||||||
let bitmap_data =
|
|
||||||
bitmap_data::create_bitmap_data_object(context, bitmap_data_proto, function_proto);
|
|
||||||
|
|
||||||
display.define_value(
|
display.define_value(
|
||||||
gc_context,
|
gc_context,
|
||||||
|
@ -1130,7 +1127,6 @@ pub fn create_globals<'gc>(
|
||||||
gradient_glow_filter: gradient_glow_filter_proto,
|
gradient_glow_filter: gradient_glow_filter_proto,
|
||||||
gradient_glow_filter_constructor: gradient_glow_filter,
|
gradient_glow_filter_constructor: gradient_glow_filter,
|
||||||
date_constructor: date,
|
date_constructor: date,
|
||||||
bitmap_data: bitmap_data_proto,
|
|
||||||
bitmap_data_constructor: bitmap_data,
|
bitmap_data_constructor: bitmap_data,
|
||||||
video: video_proto,
|
video: video_proto,
|
||||||
video_constructor: video,
|
video_constructor: video,
|
||||||
|
|
|
@ -3,17 +3,19 @@
|
||||||
use super::matrix::object_to_matrix;
|
use super::matrix::object_to_matrix;
|
||||||
use crate::avm1::function::{Executable, FunctionObject};
|
use crate::avm1::function::{Executable, FunctionObject};
|
||||||
use crate::avm1::globals::color_transform::ColorTransformObject;
|
use crate::avm1::globals::color_transform::ColorTransformObject;
|
||||||
use crate::avm1::object::bitmap_data::BitmapDataObject;
|
use crate::avm1::object::NativeObject;
|
||||||
use crate::avm1::property_decl::{define_properties_on, Declaration};
|
use crate::avm1::property_decl::{define_properties_on, Declaration};
|
||||||
use crate::avm1::{Activation, Error, Object, TObject, Value};
|
use crate::avm1::{Activation, Attribute, Error, Object, ScriptObject, TObject, Value};
|
||||||
|
use crate::bitmap::bitmap_data::{BitmapData, BitmapDataWrapper};
|
||||||
use crate::bitmap::bitmap_data::{BitmapDataDrawError, IBitmapDrawable};
|
use crate::bitmap::bitmap_data::{BitmapDataDrawError, IBitmapDrawable};
|
||||||
use crate::bitmap::bitmap_data::{ChannelOptions, ThresholdOperation};
|
use crate::bitmap::bitmap_data::{ChannelOptions, ThresholdOperation};
|
||||||
use crate::bitmap::{is_size_valid, operations};
|
use crate::bitmap::{is_size_valid, operations};
|
||||||
use crate::character::Character;
|
use crate::character::Character;
|
||||||
use crate::context::GcContext;
|
use crate::context::GcContext;
|
||||||
use crate::display_object::TDisplayObject;
|
use crate::display_object::DisplayObject;
|
||||||
use crate::swf::BlendMode;
|
use crate::swf::BlendMode;
|
||||||
use crate::{avm1_stub, avm_error};
|
use crate::{avm1_stub, avm_error};
|
||||||
|
use gc_arena::{GcCell, MutationContext};
|
||||||
use ruffle_render::transform::Transform;
|
use ruffle_render::transform::Transform;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
@ -52,93 +54,117 @@ const OBJECT_DECLS: &[Declaration] = declare_properties! {
|
||||||
"loadBitmap" => method(load_bitmap);
|
"loadBitmap" => method(load_bitmap);
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn constructor<'gc>(
|
fn new_bitmap_data<'gc>(
|
||||||
|
gc_context: MutationContext<'gc, '_>,
|
||||||
|
proto: Option<Value<'gc>>,
|
||||||
|
bitmap_data: BitmapData<'gc>,
|
||||||
|
) -> ScriptObject<'gc> {
|
||||||
|
let object = ScriptObject::new(gc_context, None);
|
||||||
|
// Set `__proto__` manually since `ScriptObject::new()` doesn't support primitive prototypes.
|
||||||
|
// TODO: Pass `proto` to `ScriptObject::new()` once possible.
|
||||||
|
if let Some(proto) = proto {
|
||||||
|
object.define_value(
|
||||||
|
gc_context,
|
||||||
|
"__proto__",
|
||||||
|
proto,
|
||||||
|
Attribute::DONT_ENUM | Attribute::DONT_DELETE,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
object.set_native(
|
||||||
|
gc_context,
|
||||||
|
NativeObject::BitmapData(BitmapDataWrapper::new(GcCell::allocate(
|
||||||
|
gc_context,
|
||||||
|
bitmap_data,
|
||||||
|
))),
|
||||||
|
);
|
||||||
|
object
|
||||||
|
}
|
||||||
|
|
||||||
|
fn constructor<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
let width = args.get(0).unwrap_or(&0.into()).coerce_to_i32(activation)? as u32;
|
let (width, height) = match args {
|
||||||
|
[width, height, ..] => (
|
||||||
let height = args.get(1).unwrap_or(&0.into()).coerce_to_i32(activation)? as u32;
|
width.coerce_to_u32(activation)?,
|
||||||
|
height.coerce_to_u32(activation)?,
|
||||||
let transparency = args
|
),
|
||||||
.get(2)
|
[] | [_] => return Ok(Value::Undefined),
|
||||||
.unwrap_or(&true.into())
|
};
|
||||||
.as_bool(activation.swf_version());
|
let transparency = match args.get(2) {
|
||||||
|
Some(transparency) => transparency.as_bool(activation.swf_version()),
|
||||||
let fill_color = args
|
None => true,
|
||||||
.get(3)
|
};
|
||||||
.unwrap_or(&(-1).into())
|
let fill_color = match args.get(3) {
|
||||||
.coerce_to_i32(activation)?;
|
Some(fill_color) => fill_color.coerce_to_i32(activation)?,
|
||||||
|
None => -1,
|
||||||
|
};
|
||||||
|
|
||||||
if !is_size_valid(activation.swf_version(), width, height) {
|
if !is_size_valid(activation.swf_version(), width, height) {
|
||||||
tracing::warn!("Invalid BitmapData size: {}x{}", width, height);
|
tracing::warn!("Invalid BitmapData size: {}x{}", width, height);
|
||||||
return Ok(Value::Undefined);
|
return Ok(Value::Undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
let bitmap_data = BitmapData::new(width, height, transparency, fill_color);
|
||||||
let (sync, _) = bitmap_data
|
this.set_native(
|
||||||
.bitmap_data()
|
activation.context.gc_context,
|
||||||
.overwrite_cpu_pixels_from_gpu(activation.context.gc_context);
|
NativeObject::BitmapData(BitmapDataWrapper::new(GcCell::allocate(
|
||||||
sync.write(activation.context.gc_context).init_pixels(
|
activation.context.gc_context,
|
||||||
width,
|
bitmap_data,
|
||||||
height,
|
))),
|
||||||
transparency,
|
);
|
||||||
fill_color,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(this.into())
|
Ok(this.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn height<'gc>(
|
fn height<'gc>(
|
||||||
_activation: &mut Activation<'_, 'gc>,
|
_activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
return Ok(bitmap_data.bitmap_data().height().into());
|
return Ok(bitmap_data.height().into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn width<'gc>(
|
fn width<'gc>(
|
||||||
_activation: &mut Activation<'_, 'gc>,
|
_activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
return Ok(bitmap_data.bitmap_data().width().into());
|
return Ok(bitmap_data.width().into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_transparent<'gc>(
|
fn get_transparent<'gc>(
|
||||||
_activation: &mut Activation<'_, 'gc>,
|
_activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
return Ok(bitmap_data.bitmap_data().transparency().into());
|
return Ok(bitmap_data.transparency().into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_rectangle<'gc>(
|
fn get_rectangle<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let proto = activation.context.avm1.prototypes().rectangle_constructor;
|
let proto = activation.context.avm1.prototypes().rectangle_constructor;
|
||||||
let rect = proto.construct(
|
let rect = proto.construct(
|
||||||
|
@ -157,17 +183,17 @@ pub fn get_rectangle<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pixel<'gc>(
|
fn get_pixel<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
if let (Some(x_val), Some(y_val)) = (args.get(0), args.get(1)) {
|
if let (Some(x_val), Some(y_val)) = (args.get(0), args.get(1)) {
|
||||||
let x = x_val.coerce_to_u32(activation)?;
|
let x = x_val.coerce_to_u32(activation)?;
|
||||||
let y = y_val.coerce_to_u32(activation)?;
|
let y = y_val.coerce_to_u32(activation)?;
|
||||||
let col = operations::get_pixel(bitmap_data.bitmap_data(), x, y);
|
let col = operations::get_pixel(bitmap_data, x, y);
|
||||||
return Ok(col.into());
|
return Ok(col.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,17 +202,17 @@ pub fn get_pixel<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pixel32<'gc>(
|
fn get_pixel32<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
if let (Some(x_val), Some(y_val)) = (args.get(0), args.get(1)) {
|
if let (Some(x_val), Some(y_val)) = (args.get(0), args.get(1)) {
|
||||||
let x = x_val.coerce_to_u32(activation)?;
|
let x = x_val.coerce_to_u32(activation)?;
|
||||||
let y = y_val.coerce_to_u32(activation)?;
|
let y = y_val.coerce_to_u32(activation)?;
|
||||||
let col = operations::get_pixel32(bitmap_data.bitmap_data(), x, y);
|
let col = operations::get_pixel32(bitmap_data, x, y);
|
||||||
return Ok(col.into());
|
return Ok(col.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,12 +221,12 @@ pub fn get_pixel32<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_pixel<'gc>(
|
fn set_pixel<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
if let (Some(x_val), Some(y_val), Some(color_val)) =
|
if let (Some(x_val), Some(y_val), Some(color_val)) =
|
||||||
(args.get(0), args.get(1), args.get(2))
|
(args.get(0), args.get(1), args.get(2))
|
||||||
|
@ -211,7 +237,7 @@ pub fn set_pixel<'gc>(
|
||||||
|
|
||||||
operations::set_pixel(
|
operations::set_pixel(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
color.into(),
|
color.into(),
|
||||||
|
@ -225,12 +251,12 @@ pub fn set_pixel<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_pixel32<'gc>(
|
fn set_pixel32<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
if let (Some(x_val), Some(y_val), Some(color_val)) =
|
if let (Some(x_val), Some(y_val), Some(color_val)) =
|
||||||
(args.get(0), args.get(1), args.get(2))
|
(args.get(0), args.get(1), args.get(2))
|
||||||
|
@ -239,13 +265,7 @@ pub fn set_pixel32<'gc>(
|
||||||
let y = y_val.coerce_to_u32(activation)?;
|
let y = y_val.coerce_to_u32(activation)?;
|
||||||
let color = color_val.coerce_to_i32(activation)?;
|
let color = color_val.coerce_to_i32(activation)?;
|
||||||
|
|
||||||
operations::set_pixel32(
|
operations::set_pixel32(activation.context.gc_context, bitmap_data, x, y, color);
|
||||||
activation.context.gc_context,
|
|
||||||
bitmap_data.bitmap_data(),
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
color,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(Value::Undefined);
|
return Ok(Value::Undefined);
|
||||||
|
@ -255,7 +275,7 @@ pub fn set_pixel32<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_channel<'gc>(
|
fn copy_channel<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
|
@ -285,9 +305,9 @@ pub fn copy_channel<'gc>(
|
||||||
.unwrap_or(&Value::Undefined)
|
.unwrap_or(&Value::Undefined)
|
||||||
.coerce_to_i32(activation)?;
|
.coerce_to_i32(activation)?;
|
||||||
|
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
if let Some(source_bitmap) = source_bitmap.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(source_bitmap) = source_bitmap.native() {
|
||||||
//TODO: what if source is disposed
|
//TODO: what if source is disposed
|
||||||
let min_x = dest_point.get("x", activation)?.coerce_to_i32(activation)?;
|
let min_x = dest_point.get("x", activation)?.coerce_to_i32(activation)?;
|
||||||
let min_y = dest_point.get("y", activation)?.coerce_to_i32(activation)?;
|
let min_y = dest_point.get("y", activation)?.coerce_to_i32(activation)?;
|
||||||
|
@ -307,10 +327,10 @@ pub fn copy_channel<'gc>(
|
||||||
|
|
||||||
operations::copy_channel(
|
operations::copy_channel(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
(min_x, min_y),
|
(min_x, min_y),
|
||||||
(src_min_x, src_min_y, src_width, src_height),
|
(src_min_x, src_min_y, src_width, src_height),
|
||||||
source_bitmap.bitmap_data(),
|
source_bitmap,
|
||||||
source_channel,
|
source_channel,
|
||||||
dest_channel,
|
dest_channel,
|
||||||
);
|
);
|
||||||
|
@ -323,7 +343,7 @@ pub fn copy_channel<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_rect<'gc>(
|
fn fill_rect<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
|
@ -333,7 +353,7 @@ pub fn fill_rect<'gc>(
|
||||||
.unwrap_or(&Value::Undefined)
|
.unwrap_or(&Value::Undefined)
|
||||||
.coerce_to_object(activation);
|
.coerce_to_object(activation);
|
||||||
|
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
if let Some(color_val) = args.get(1) {
|
if let Some(color_val) = args.get(1) {
|
||||||
let color = color_val.coerce_to_i32(activation)?;
|
let color = color_val.coerce_to_i32(activation)?;
|
||||||
|
@ -349,7 +369,7 @@ pub fn fill_rect<'gc>(
|
||||||
|
|
||||||
operations::fill_rect(
|
operations::fill_rect(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
width,
|
width,
|
||||||
|
@ -364,35 +384,33 @@ pub fn fill_rect<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clone<'gc>(
|
fn clone<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let new_bitmap_data = operations::clone(bitmap_data.bitmap_data());
|
return Ok(new_bitmap_data(
|
||||||
let new_bitmap_data = BitmapDataObject::with_bitmap_data(
|
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
activation.context.avm1.prototypes().bitmap_data,
|
this.get_local_stored("__proto__", activation),
|
||||||
new_bitmap_data,
|
operations::clone(bitmap_data),
|
||||||
);
|
)
|
||||||
|
.into());
|
||||||
return Ok(new_bitmap_data.into());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dispose<'gc>(
|
fn dispose<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
bitmap_data.dispose(&mut activation.context);
|
bitmap_data.dispose(activation.context.gc_context);
|
||||||
return Ok(Value::Undefined);
|
return Ok(Value::Undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,12 +418,12 @@ pub fn dispose<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flood_fill<'gc>(
|
fn flood_fill<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
if let (Some(x_val), Some(y_val), Some(color_val)) =
|
if let (Some(x_val), Some(y_val), Some(color_val)) =
|
||||||
(args.get(0), args.get(1), args.get(2))
|
(args.get(0), args.get(1), args.get(2))
|
||||||
|
@ -414,13 +432,7 @@ pub fn flood_fill<'gc>(
|
||||||
let y = y_val.coerce_to_u32(activation)?;
|
let y = y_val.coerce_to_u32(activation)?;
|
||||||
let color = color_val.coerce_to_i32(activation)?;
|
let color = color_val.coerce_to_i32(activation)?;
|
||||||
|
|
||||||
operations::flood_fill(
|
operations::flood_fill(activation.context.gc_context, bitmap_data, x, y, color);
|
||||||
activation.context.gc_context,
|
|
||||||
bitmap_data.bitmap_data(),
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
color,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return Ok(Value::Undefined);
|
return Ok(Value::Undefined);
|
||||||
}
|
}
|
||||||
|
@ -429,7 +441,7 @@ pub fn flood_fill<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noise<'gc>(
|
fn noise<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
|
@ -452,13 +464,13 @@ pub fn noise<'gc>(
|
||||||
.unwrap_or(&false.into())
|
.unwrap_or(&false.into())
|
||||||
.as_bool(activation.swf_version());
|
.as_bool(activation.swf_version());
|
||||||
|
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
if let Some(random_seed_val) = args.get(0) {
|
if let Some(random_seed_val) = args.get(0) {
|
||||||
let random_seed = random_seed_val.coerce_to_i32(activation)?;
|
let random_seed = random_seed_val.coerce_to_i32(activation)?;
|
||||||
operations::noise(
|
operations::noise(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
random_seed,
|
random_seed,
|
||||||
low,
|
low,
|
||||||
high.max(low),
|
high.max(low),
|
||||||
|
@ -474,12 +486,12 @@ pub fn noise<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw<'gc>(
|
fn draw<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let matrix = args
|
let matrix = args
|
||||||
.get(1)
|
.get(1)
|
||||||
|
@ -521,8 +533,8 @@ pub fn draw<'gc>(
|
||||||
.coerce_to_object(activation);
|
.coerce_to_object(activation);
|
||||||
let source = if let Some(source_object) = source.as_display_object() {
|
let source = if let Some(source_object) = source.as_display_object() {
|
||||||
IBitmapDrawable::DisplayObject(source_object)
|
IBitmapDrawable::DisplayObject(source_object)
|
||||||
} else if let Some(source_bitmap) = source.as_bitmap_data_object() {
|
} else if let NativeObject::BitmapData(source_bitmap) = source.native() {
|
||||||
IBitmapDrawable::BitmapData(source_bitmap.bitmap_data())
|
IBitmapDrawable::BitmapData(source_bitmap)
|
||||||
} else {
|
} else {
|
||||||
avm_error!(
|
avm_error!(
|
||||||
activation,
|
activation,
|
||||||
|
@ -538,7 +550,7 @@ pub fn draw<'gc>(
|
||||||
let quality = activation.context.stage.quality();
|
let quality = activation.context.stage.quality();
|
||||||
match operations::draw(
|
match operations::draw(
|
||||||
&mut activation.context,
|
&mut activation.context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
source,
|
source,
|
||||||
Transform {
|
Transform {
|
||||||
matrix,
|
matrix,
|
||||||
|
@ -564,7 +576,7 @@ pub fn draw<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_filter<'gc>(
|
fn apply_filter<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
_this: Object<'gc>,
|
_this: Object<'gc>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
|
@ -573,12 +585,12 @@ pub fn apply_filter<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_filter_rect<'gc>(
|
fn generate_filter_rect<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
_args: &[Value<'gc>],
|
_args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
avm1_stub!(activation, "BitmapData", "generateFilterRect");
|
avm1_stub!(activation, "BitmapData", "generateFilterRect");
|
||||||
return Ok(Value::Undefined);
|
return Ok(Value::Undefined);
|
||||||
|
@ -588,12 +600,12 @@ pub fn generate_filter_rect<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn color_transform<'gc>(
|
fn color_transform<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
if let [rectangle, color_transform, ..] = args {
|
if let [rectangle, color_transform, ..] = args {
|
||||||
// TODO: Re-use `object_to_rectangle` in `movie_clip.rs`.
|
// TODO: Re-use `object_to_rectangle` in `movie_clip.rs`.
|
||||||
|
@ -619,7 +631,7 @@ pub fn color_transform<'gc>(
|
||||||
|
|
||||||
operations::color_transform(
|
operations::color_transform(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
x_min,
|
x_min,
|
||||||
y_min,
|
y_min,
|
||||||
x_max,
|
x_max,
|
||||||
|
@ -633,12 +645,12 @@ pub fn color_transform<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_color_bounds_rect<'gc>(
|
fn get_color_bounds_rect<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let find_color = args
|
let find_color = args
|
||||||
.get(2)
|
.get(2)
|
||||||
|
@ -649,12 +661,8 @@ pub fn get_color_bounds_rect<'gc>(
|
||||||
let mask = mask_val.coerce_to_i32(activation)?;
|
let mask = mask_val.coerce_to_i32(activation)?;
|
||||||
let color = color_val.coerce_to_i32(activation)?;
|
let color = color_val.coerce_to_i32(activation)?;
|
||||||
|
|
||||||
let (x, y, w, h) = operations::color_bounds_rect(
|
let (x, y, w, h) =
|
||||||
bitmap_data.bitmap_data(),
|
operations::color_bounds_rect(bitmap_data, find_color, mask, color);
|
||||||
find_color,
|
|
||||||
mask,
|
|
||||||
color,
|
|
||||||
);
|
|
||||||
|
|
||||||
let proto = activation.context.avm1.prototypes().rectangle_constructor;
|
let proto = activation.context.avm1.prototypes().rectangle_constructor;
|
||||||
let rect =
|
let rect =
|
||||||
|
@ -667,12 +675,12 @@ pub fn get_color_bounds_rect<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn perlin_noise<'gc>(
|
fn perlin_noise<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let base_x = args
|
let base_x = args
|
||||||
.get(0)
|
.get(0)
|
||||||
|
@ -727,7 +735,7 @@ pub fn perlin_noise<'gc>(
|
||||||
|
|
||||||
operations::perlin_noise(
|
operations::perlin_noise(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
(base_x, base_y),
|
(base_x, base_y),
|
||||||
num_octaves,
|
num_octaves,
|
||||||
seed,
|
seed,
|
||||||
|
@ -743,12 +751,12 @@ pub fn perlin_noise<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hit_test<'gc>(
|
fn hit_test<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let first_point = args
|
let first_point = args
|
||||||
.get(0)
|
.get(0)
|
||||||
|
@ -776,7 +784,7 @@ pub fn hit_test<'gc>(
|
||||||
|
|
||||||
// Overload based on the object we are hit-testing against.
|
// Overload based on the object we are hit-testing against.
|
||||||
// BitmapData vs. BitmapData
|
// BitmapData vs. BitmapData
|
||||||
if let Some(other_bmd) = compare_object.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(other_bmd) = compare_object.native() {
|
||||||
if other_bmd.disposed() {
|
if other_bmd.disposed() {
|
||||||
return Ok((-3).into());
|
return Ok((-3).into());
|
||||||
}
|
}
|
||||||
|
@ -801,10 +809,10 @@ pub fn hit_test<'gc>(
|
||||||
.clamp(0, u8::MAX.into()) as u8;
|
.clamp(0, u8::MAX.into()) as u8;
|
||||||
|
|
||||||
let result = operations::hit_test_bitmapdata(
|
let result = operations::hit_test_bitmapdata(
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
top_left,
|
top_left,
|
||||||
source_threshold,
|
source_threshold,
|
||||||
other_bmd.bitmap_data(),
|
other_bmd,
|
||||||
second_point,
|
second_point,
|
||||||
second_threshold,
|
second_threshold,
|
||||||
);
|
);
|
||||||
|
@ -826,7 +834,7 @@ pub fn hit_test<'gc>(
|
||||||
test_y.coerce_to_i32(activation)? - top_left.1,
|
test_y.coerce_to_i32(activation)? - top_left.1,
|
||||||
);
|
);
|
||||||
return Ok(Value::Bool(operations::hit_test_point(
|
return Ok(Value::Bool(operations::hit_test_point(
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
source_threshold,
|
source_threshold,
|
||||||
test_point,
|
test_point,
|
||||||
)));
|
)));
|
||||||
|
@ -843,7 +851,7 @@ pub fn hit_test<'gc>(
|
||||||
test_height.coerce_to_i32(activation)?,
|
test_height.coerce_to_i32(activation)?,
|
||||||
);
|
);
|
||||||
return Ok(Value::Bool(operations::hit_test_rectangle(
|
return Ok(Value::Bool(operations::hit_test_rectangle(
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
source_threshold,
|
source_threshold,
|
||||||
test_point,
|
test_point,
|
||||||
size,
|
size,
|
||||||
|
@ -863,12 +871,12 @@ pub fn hit_test<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_pixels<'gc>(
|
fn copy_pixels<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let source_bitmap = args
|
let source_bitmap = args
|
||||||
.get(0)
|
.get(0)
|
||||||
|
@ -901,7 +909,7 @@ pub fn copy_pixels<'gc>(
|
||||||
let dest_x = dest_point.get("x", activation)?.coerce_to_f64(activation)? as i32;
|
let dest_x = dest_point.get("x", activation)?.coerce_to_f64(activation)? as i32;
|
||||||
let dest_y = dest_point.get("y", activation)?.coerce_to_f64(activation)? as i32;
|
let dest_y = dest_point.get("y", activation)?.coerce_to_f64(activation)? as i32;
|
||||||
|
|
||||||
if let Some(src_bitmap) = source_bitmap.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(src_bitmap) = source_bitmap.native() {
|
||||||
if !src_bitmap.disposed() {
|
if !src_bitmap.disposed() {
|
||||||
let merge_alpha = if args.len() >= 6 {
|
let merge_alpha = if args.len() >= 6 {
|
||||||
Some(
|
Some(
|
||||||
|
@ -918,7 +926,7 @@ pub fn copy_pixels<'gc>(
|
||||||
.unwrap_or(&Value::Undefined)
|
.unwrap_or(&Value::Undefined)
|
||||||
.coerce_to_object(activation);
|
.coerce_to_object(activation);
|
||||||
|
|
||||||
if let Some(alpha_bitmap) = alpha_bitmap.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(alpha_bitmap) = alpha_bitmap.native() {
|
||||||
if !alpha_bitmap.disposed() {
|
if !alpha_bitmap.disposed() {
|
||||||
let alpha_point = args
|
let alpha_point = args
|
||||||
.get(4)
|
.get(4)
|
||||||
|
@ -937,11 +945,11 @@ pub fn copy_pixels<'gc>(
|
||||||
|
|
||||||
operations::copy_pixels_with_alpha_source(
|
operations::copy_pixels_with_alpha_source(
|
||||||
&mut activation.context,
|
&mut activation.context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
src_bitmap.bitmap_data(),
|
src_bitmap,
|
||||||
(src_min_x, src_min_y, src_width, src_height),
|
(src_min_x, src_min_y, src_width, src_height),
|
||||||
(dest_x, dest_y),
|
(dest_x, dest_y),
|
||||||
alpha_bitmap.bitmap_data(),
|
alpha_bitmap,
|
||||||
(alpha_x, alpha_y),
|
(alpha_x, alpha_y),
|
||||||
merge_alpha.unwrap_or(true),
|
merge_alpha.unwrap_or(true),
|
||||||
);
|
);
|
||||||
|
@ -949,8 +957,8 @@ pub fn copy_pixels<'gc>(
|
||||||
} else {
|
} else {
|
||||||
operations::copy_pixels(
|
operations::copy_pixels(
|
||||||
&mut activation.context,
|
&mut activation.context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
src_bitmap.bitmap_data(),
|
src_bitmap,
|
||||||
(src_min_x, src_min_y, src_width, src_height),
|
(src_min_x, src_min_y, src_width, src_height),
|
||||||
(dest_x, dest_y),
|
(dest_x, dest_y),
|
||||||
// Despite what the docs claim, mergeAlpa appears to be treated as 'false'
|
// Despite what the docs claim, mergeAlpa appears to be treated as 'false'
|
||||||
|
@ -968,12 +976,12 @@ pub fn copy_pixels<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn merge<'gc>(
|
fn merge<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let source_bitmap = args
|
let source_bitmap = args
|
||||||
.get(0)
|
.get(0)
|
||||||
|
@ -1026,12 +1034,12 @@ pub fn merge<'gc>(
|
||||||
.unwrap_or(&Value::Undefined)
|
.unwrap_or(&Value::Undefined)
|
||||||
.coerce_to_i32(activation)?;
|
.coerce_to_i32(activation)?;
|
||||||
|
|
||||||
if let Some(src_bitmap) = source_bitmap.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(src_bitmap) = source_bitmap.native() {
|
||||||
if !src_bitmap.disposed() {
|
if !src_bitmap.disposed() {
|
||||||
operations::merge(
|
operations::merge(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
src_bitmap.bitmap_data(),
|
src_bitmap,
|
||||||
(src_min_x, src_min_y, src_width, src_height),
|
(src_min_x, src_min_y, src_width, src_height),
|
||||||
(dest_x, dest_y),
|
(dest_x, dest_y),
|
||||||
(red_mult, green_mult, blue_mult, alpha_mult),
|
(red_mult, green_mult, blue_mult, alpha_mult),
|
||||||
|
@ -1046,12 +1054,12 @@ pub fn merge<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn palette_map<'gc>(
|
fn palette_map<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let source_bitmap = args
|
let source_bitmap = args
|
||||||
.get(0)
|
.get(0)
|
||||||
|
@ -1105,12 +1113,12 @@ pub fn palette_map<'gc>(
|
||||||
let blue_array = get_channel(5, 0)?;
|
let blue_array = get_channel(5, 0)?;
|
||||||
let alpha_array = get_channel(6, 24)?;
|
let alpha_array = get_channel(6, 24)?;
|
||||||
|
|
||||||
if let Some(src_bitmap) = source_bitmap.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(src_bitmap) = source_bitmap.native() {
|
||||||
if !src_bitmap.disposed() {
|
if !src_bitmap.disposed() {
|
||||||
operations::palette_map(
|
operations::palette_map(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
src_bitmap.bitmap_data(),
|
src_bitmap,
|
||||||
(src_min_x, src_min_y, src_width, src_height),
|
(src_min_x, src_min_y, src_width, src_height),
|
||||||
(dest_x, dest_y),
|
(dest_x, dest_y),
|
||||||
(red_array, green_array, blue_array, alpha_array),
|
(red_array, green_array, blue_array, alpha_array),
|
||||||
|
@ -1125,12 +1133,12 @@ pub fn palette_map<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pixel_dissolve<'gc>(
|
fn pixel_dissolve<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let src_bitmap_data = args
|
let src_bitmap_data = args
|
||||||
.get(0)
|
.get(0)
|
||||||
|
@ -1159,7 +1167,7 @@ pub fn pixel_dissolve<'gc>(
|
||||||
return Ok((-4).into());
|
return Ok((-4).into());
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(src_bitmap_data) = src_bitmap_data.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(src_bitmap_data) = src_bitmap_data.native() {
|
||||||
if !src_bitmap_data.disposed() {
|
if !src_bitmap_data.disposed() {
|
||||||
let dest_point = args
|
let dest_point = args
|
||||||
.get(2)
|
.get(2)
|
||||||
|
@ -1186,8 +1194,8 @@ pub fn pixel_dissolve<'gc>(
|
||||||
|
|
||||||
return Ok(operations::pixel_dissolve(
|
return Ok(operations::pixel_dissolve(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
src_bitmap_data.bitmap_data(),
|
src_bitmap_data,
|
||||||
(src_min_x, src_min_y, src_width, src_height),
|
(src_min_x, src_min_y, src_width, src_height),
|
||||||
dest_point,
|
dest_point,
|
||||||
random_seed,
|
random_seed,
|
||||||
|
@ -1203,12 +1211,12 @@ pub fn pixel_dissolve<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scroll<'gc>(
|
fn scroll<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let x = args
|
let x = args
|
||||||
.get(0)
|
.get(0)
|
||||||
|
@ -1219,12 +1227,7 @@ pub fn scroll<'gc>(
|
||||||
.unwrap_or(&Value::Undefined)
|
.unwrap_or(&Value::Undefined)
|
||||||
.coerce_to_i32(activation)?;
|
.coerce_to_i32(activation)?;
|
||||||
|
|
||||||
operations::scroll(
|
operations::scroll(activation.context.gc_context, bitmap_data, x, y);
|
||||||
activation.context.gc_context,
|
|
||||||
bitmap_data.bitmap_data(),
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Ok(Value::Undefined);
|
return Ok(Value::Undefined);
|
||||||
}
|
}
|
||||||
|
@ -1233,12 +1236,12 @@ pub fn scroll<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn threshold<'gc>(
|
fn threshold<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(bitmap_data) = this.native() {
|
||||||
if !bitmap_data.disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let source_bitmap = args
|
let source_bitmap = args
|
||||||
.get(0)
|
.get(0)
|
||||||
|
@ -1298,12 +1301,12 @@ pub fn threshold<'gc>(
|
||||||
.unwrap_or(&false.into())
|
.unwrap_or(&false.into())
|
||||||
.as_bool(activation.swf_version());
|
.as_bool(activation.swf_version());
|
||||||
|
|
||||||
if let Some(src_bitmap) = source_bitmap.as_bitmap_data_object() {
|
if let NativeObject::BitmapData(src_bitmap) = source_bitmap.native() {
|
||||||
if !src_bitmap.disposed() {
|
if !src_bitmap.disposed() {
|
||||||
let modified_count = operations::threshold(
|
let modified_count = operations::threshold(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
bitmap_data.bitmap_data(),
|
bitmap_data,
|
||||||
src_bitmap.bitmap_data(),
|
src_bitmap,
|
||||||
(src_min_x, src_min_y, src_width, src_height),
|
(src_min_x, src_min_y, src_width, src_height),
|
||||||
(dest_x, dest_y),
|
(dest_x, dest_y),
|
||||||
operation,
|
operation,
|
||||||
|
@ -1324,7 +1327,7 @@ pub fn threshold<'gc>(
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compare<'gc>(
|
fn compare<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
|
@ -1335,11 +1338,7 @@ pub fn compare<'gc>(
|
||||||
const DIFFERENT_WIDTHS: i32 = -3;
|
const DIFFERENT_WIDTHS: i32 = -3;
|
||||||
const DIFFERENT_HEIGHTS: i32 = -4;
|
const DIFFERENT_HEIGHTS: i32 = -4;
|
||||||
|
|
||||||
let this_bitmap_data = if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
let NativeObject::BitmapData(this_bitmap_data) = this.native() else { return Ok(NOT_BITMAP.into()); };
|
||||||
bitmap_data
|
|
||||||
} else {
|
|
||||||
return Ok(NOT_BITMAP.into());
|
|
||||||
};
|
|
||||||
|
|
||||||
if this_bitmap_data.disposed() {
|
if this_bitmap_data.disposed() {
|
||||||
// The documentation says that -2 should be returned here, but -1 is actually returned.
|
// The documentation says that -2 should be returned here, but -1 is actually returned.
|
||||||
|
@ -1351,9 +1350,7 @@ pub fn compare<'gc>(
|
||||||
.unwrap_or(&Value::Undefined)
|
.unwrap_or(&Value::Undefined)
|
||||||
.coerce_to_object(activation);
|
.coerce_to_object(activation);
|
||||||
|
|
||||||
let other_bitmap_data = if let Some(other_bitmap_data) = other.as_bitmap_data_object() {
|
let NativeObject::BitmapData(other_bitmap_data) = other.native() else {
|
||||||
other_bitmap_data
|
|
||||||
} else {
|
|
||||||
// The documentation says that -1 should be returned here, but -2 is actually returned.
|
// The documentation says that -1 should be returned here, but -2 is actually returned.
|
||||||
return Ok(BITMAP_DISPOSED.into());
|
return Ok(BITMAP_DISPOSED.into());
|
||||||
};
|
};
|
||||||
|
@ -1362,9 +1359,6 @@ pub fn compare<'gc>(
|
||||||
return Ok(BITMAP_DISPOSED.into());
|
return Ok(BITMAP_DISPOSED.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let this_bitmap_data = this_bitmap_data.bitmap_data();
|
|
||||||
let other_bitmap_data = other_bitmap_data.bitmap_data();
|
|
||||||
|
|
||||||
if this_bitmap_data.width() != other_bitmap_data.width() {
|
if this_bitmap_data.width() != other_bitmap_data.width() {
|
||||||
return Ok(DIFFERENT_WIDTHS.into());
|
return Ok(DIFFERENT_WIDTHS.into());
|
||||||
}
|
}
|
||||||
|
@ -1374,9 +1368,9 @@ pub fn compare<'gc>(
|
||||||
}
|
}
|
||||||
|
|
||||||
match operations::compare(this_bitmap_data, other_bitmap_data) {
|
match operations::compare(this_bitmap_data, other_bitmap_data) {
|
||||||
Some(bitmap_data) => Ok(BitmapDataObject::with_bitmap_data(
|
Some(bitmap_data) => Ok(new_bitmap_data(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
activation.context.avm1.prototypes().bitmap_data,
|
this.get_local_stored("__proto__", activation),
|
||||||
bitmap_data,
|
bitmap_data,
|
||||||
)
|
)
|
||||||
.into()),
|
.into()),
|
||||||
|
@ -1384,20 +1378,9 @@ pub fn compare<'gc>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_proto<'gc>(
|
fn load_bitmap<'gc>(
|
||||||
context: &mut GcContext<'_, 'gc>,
|
|
||||||
proto: Object<'gc>,
|
|
||||||
fn_proto: Object<'gc>,
|
|
||||||
) -> Object<'gc> {
|
|
||||||
let bitmap_data_object = BitmapDataObject::empty_object(context.gc_context, proto);
|
|
||||||
let object = bitmap_data_object.raw_script_object();
|
|
||||||
define_properties_on(PROTO_DECLS, context, object, fn_proto);
|
|
||||||
bitmap_data_object.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_bitmap<'gc>(
|
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
_this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
let name = args
|
let name = args
|
||||||
|
@ -1407,50 +1390,47 @@ pub fn load_bitmap<'gc>(
|
||||||
|
|
||||||
let library = &*activation.context.library;
|
let library = &*activation.context.library;
|
||||||
|
|
||||||
let movie = activation.target_clip_or_root().movie();
|
let movie = <DisplayObject as crate::display_object::TDisplayObject>::movie(
|
||||||
|
&activation.target_clip_or_root(),
|
||||||
|
);
|
||||||
|
|
||||||
let character = library
|
let character = library
|
||||||
.library_for_movie(movie)
|
.library_for_movie(movie)
|
||||||
.and_then(|l| l.character_by_export_name(name));
|
.and_then(|l| l.character_by_export_name(name));
|
||||||
|
|
||||||
if let Some(Character::Bitmap(bitmap)) = character {
|
let Some(Character::Bitmap(bitmap)) = character else { return Ok(Value::Undefined); };
|
||||||
let new_bitmap_data = BitmapDataObject::empty_object(
|
|
||||||
activation.context.gc_context,
|
|
||||||
activation.context.avm1.prototypes().bitmap_data,
|
|
||||||
);
|
|
||||||
|
|
||||||
let width = bitmap.width() as u32;
|
let transparency = true;
|
||||||
let height = bitmap.height() as u32;
|
let bitmap_data = BitmapData::new_with_pixels(
|
||||||
|
bitmap.width().into(),
|
||||||
let pixels: Vec<_> = bitmap.bitmap_data().read().pixels().to_vec();
|
bitmap.height().into(),
|
||||||
let (sync, _) = new_bitmap_data
|
transparency,
|
||||||
.as_bitmap_data_object()
|
bitmap.bitmap_data().read().pixels().to_vec(),
|
||||||
.unwrap()
|
);
|
||||||
.bitmap_data()
|
Ok(new_bitmap_data(
|
||||||
.overwrite_cpu_pixels_from_gpu(activation.context.gc_context);
|
activation.context.gc_context,
|
||||||
|
this.get_local_stored("prototype", activation),
|
||||||
sync.write(activation.context.gc_context)
|
bitmap_data,
|
||||||
.set_pixels(width, height, true, pixels);
|
)
|
||||||
|
.into())
|
||||||
return Ok(new_bitmap_data.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Value::Undefined)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_bitmap_data_object<'gc>(
|
pub fn create_constructor<'gc>(
|
||||||
context: &mut GcContext<'_, 'gc>,
|
context: &mut GcContext<'_, 'gc>,
|
||||||
bitmap_data_proto: Object<'gc>,
|
proto: Object<'gc>,
|
||||||
fn_proto: Object<'gc>,
|
fn_proto: Object<'gc>,
|
||||||
) -> Object<'gc> {
|
) -> Object<'gc> {
|
||||||
let bitmap_data = FunctionObject::constructor(
|
let bitmap_data_proto = ScriptObject::new(context.gc_context, Some(proto));
|
||||||
|
define_properties_on(PROTO_DECLS, context, bitmap_data_proto, fn_proto);
|
||||||
|
|
||||||
|
let bitmap_data_constructor = FunctionObject::constructor(
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
Executable::Native(constructor),
|
Executable::Native(constructor),
|
||||||
constructor_to_fn!(constructor),
|
constructor_to_fn!(constructor),
|
||||||
fn_proto,
|
fn_proto,
|
||||||
bitmap_data_proto,
|
bitmap_data_proto.into(),
|
||||||
);
|
);
|
||||||
let object = bitmap_data.raw_script_object();
|
let object = bitmap_data_constructor.raw_script_object();
|
||||||
define_properties_on(OBJECT_DECLS, context, object, fn_proto);
|
define_properties_on(OBJECT_DECLS, context, object, fn_proto);
|
||||||
bitmap_data
|
bitmap_data_constructor
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::avm1::activation::Activation;
|
||||||
use crate::avm1::clamp::Clamp;
|
use crate::avm1::clamp::Clamp;
|
||||||
use crate::avm1::error::Error;
|
use crate::avm1::error::Error;
|
||||||
use crate::avm1::object::displacement_map_filter::DisplacementMapFilterObject;
|
use crate::avm1::object::displacement_map_filter::DisplacementMapFilterObject;
|
||||||
|
use crate::avm1::object::NativeObject;
|
||||||
use crate::avm1::property_decl::{define_properties_on, Declaration};
|
use crate::avm1::property_decl::{define_properties_on, Declaration};
|
||||||
use crate::avm1::{Object, TObject, Value};
|
use crate::avm1::{Object, TObject, Value};
|
||||||
use crate::context::GcContext;
|
use crate::context::GcContext;
|
||||||
|
@ -169,14 +170,11 @@ pub fn set_map_bitmap<'gc>(
|
||||||
this: Object<'gc>,
|
this: Object<'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
let bitmap = args
|
|
||||||
.get(0)
|
|
||||||
.unwrap_or(&Value::Undefined)
|
|
||||||
.coerce_to_object(activation);
|
|
||||||
|
|
||||||
if let Some(object) = this.as_displacement_map_filter_object() {
|
if let Some(object) = this.as_displacement_map_filter_object() {
|
||||||
if bitmap.as_bitmap_data_object().is_some() {
|
if let [Value::Object(map_bitmap), ..] = args {
|
||||||
object.set_map_bitmap(activation.context.gc_context, Some(bitmap));
|
if let NativeObject::BitmapData(_) = map_bitmap.native() {
|
||||||
|
object.set_map_bitmap(activation.context.gc_context, Some(*map_bitmap));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::avm1::activation::Activation;
|
||||||
use crate::avm1::error::Error;
|
use crate::avm1::error::Error;
|
||||||
use crate::avm1::globals::matrix::gradient_object_to_matrix;
|
use crate::avm1::globals::matrix::gradient_object_to_matrix;
|
||||||
use crate::avm1::globals::{self, AVM_DEPTH_BIAS, AVM_MAX_DEPTH};
|
use crate::avm1::globals::{self, AVM_DEPTH_BIAS, AVM_MAX_DEPTH};
|
||||||
|
use crate::avm1::object::NativeObject;
|
||||||
use crate::avm1::property_decl::{define_properties_on, Declaration};
|
use crate::avm1::property_decl::{define_properties_on, Declaration};
|
||||||
use crate::avm1::{self, Object, ScriptObject, TObject, Value};
|
use crate::avm1::{self, Object, ScriptObject, TObject, Value};
|
||||||
use crate::avm_error;
|
use crate::avm_error;
|
||||||
|
@ -17,7 +18,6 @@ use crate::ecma_conversions::f64_to_wrapping_i32;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::string::AvmString;
|
use crate::string::AvmString;
|
||||||
use crate::vminterface::Instantiator;
|
use crate::vminterface::Instantiator;
|
||||||
|
|
||||||
use ruffle_render::shape_utils::DrawCommand;
|
use ruffle_render::shape_utils::DrawCommand;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use swf::{
|
use swf::{
|
||||||
|
@ -243,12 +243,8 @@ fn attach_bitmap<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap) = args.get(0) {
|
if let [Value::Object(bitmap_data), ..] = args {
|
||||||
if let Some(bitmap_data) = bitmap
|
if let NativeObject::BitmapData(bitmap_data) = bitmap_data.native() {
|
||||||
.coerce_to_object(activation)
|
|
||||||
.as_bitmap_data_object()
|
|
||||||
.map(|bd| bd.bitmap_data())
|
|
||||||
{
|
|
||||||
if let Some(depth) = args.get(1) {
|
if let Some(depth) = args.get(1) {
|
||||||
let depth = depth
|
let depth = depth
|
||||||
.coerce_to_i32(activation)?
|
.coerce_to_i32(activation)?
|
||||||
|
@ -395,55 +391,54 @@ fn begin_bitmap_fill<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = args
|
let fill_style = if let [Value::Object(bitmap_data), ..] = args {
|
||||||
.get(0)
|
if let NativeObject::BitmapData(bitmap_data) = bitmap_data.native() {
|
||||||
.and_then(|val| val.coerce_to_object(activation).as_bitmap_data_object())
|
// Register the bitmap data with the drawing.
|
||||||
{
|
let handle = bitmap_data
|
||||||
// Register the bitmap data with the drawing.
|
.bitmap_handle(activation.context.gc_context, activation.context.renderer);
|
||||||
let bitmap_data = bitmap_data.bitmap_data();
|
let bitmap = ruffle_render::bitmap::BitmapInfo {
|
||||||
let handle =
|
handle,
|
||||||
bitmap_data.bitmap_handle(activation.context.gc_context, activation.context.renderer);
|
width: bitmap_data.width() as u16,
|
||||||
let bitmap = ruffle_render::bitmap::BitmapInfo {
|
height: bitmap_data.height() as u16,
|
||||||
handle,
|
};
|
||||||
width: bitmap_data.width() as u16,
|
let id = movie_clip
|
||||||
height: bitmap_data.height() as u16,
|
.drawing(activation.context.gc_context)
|
||||||
};
|
.add_bitmap(bitmap);
|
||||||
let id = movie_clip
|
|
||||||
.drawing(activation.context.gc_context)
|
|
||||||
.add_bitmap(bitmap);
|
|
||||||
|
|
||||||
let mut matrix = avm1::globals::matrix::object_to_matrix_or_default(
|
let mut matrix = avm1::globals::matrix::object_to_matrix_or_default(
|
||||||
args.get(1)
|
args.get(1)
|
||||||
.unwrap_or(&Value::Undefined)
|
.unwrap_or(&Value::Undefined)
|
||||||
.coerce_to_object(activation),
|
.coerce_to_object(activation),
|
||||||
activation,
|
activation,
|
||||||
)?;
|
)?;
|
||||||
// Flash matrix is in pixels. Scale from pixels to twips.
|
// Flash matrix is in pixels. Scale from pixels to twips.
|
||||||
matrix *= Matrix::scale(Twips::TWIPS_PER_PIXEL as f32, Twips::TWIPS_PER_PIXEL as f32);
|
matrix *= Matrix::scale(Twips::TWIPS_PER_PIXEL as f32, Twips::TWIPS_PER_PIXEL as f32);
|
||||||
|
|
||||||
// `repeating` defaults to true, `smoothed` to false.
|
// `repeating` defaults to true, `smoothed` to false.
|
||||||
// `smoothed` parameter may not be listed in some documentation.
|
// `smoothed` parameter may not be listed in some documentation.
|
||||||
let is_repeating = args
|
let is_repeating = args
|
||||||
.get(2)
|
.get(2)
|
||||||
.unwrap_or(&true.into())
|
.unwrap_or(&true.into())
|
||||||
.as_bool(activation.swf_version());
|
.as_bool(activation.swf_version());
|
||||||
let is_smoothed = args
|
let is_smoothed = args
|
||||||
.get(3)
|
.get(3)
|
||||||
.unwrap_or(&false.into())
|
.unwrap_or(&false.into())
|
||||||
.as_bool(activation.swf_version());
|
.as_bool(activation.swf_version());
|
||||||
movie_clip
|
Some(FillStyle::Bitmap {
|
||||||
.drawing(activation.context.gc_context)
|
|
||||||
.set_fill_style(Some(FillStyle::Bitmap {
|
|
||||||
id,
|
id,
|
||||||
matrix: matrix.into(),
|
matrix: matrix.into(),
|
||||||
is_smoothed,
|
is_smoothed,
|
||||||
is_repeating,
|
is_repeating,
|
||||||
}));
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
movie_clip
|
None
|
||||||
.drawing(activation.context.gc_context)
|
};
|
||||||
.set_fill_style(None);
|
movie_clip
|
||||||
}
|
.drawing(activation.context.gc_context)
|
||||||
|
.set_fill_style(fill_style);
|
||||||
Ok(Value::Undefined)
|
Ok(Value::Undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ use crate::avm1::globals::date::Date;
|
||||||
use crate::avm1::globals::drop_shadow_filter::DropShadowFilter;
|
use crate::avm1::globals::drop_shadow_filter::DropShadowFilter;
|
||||||
use crate::avm1::globals::glow_filter::GlowFilter;
|
use crate::avm1::globals::glow_filter::GlowFilter;
|
||||||
use crate::avm1::object::array_object::ArrayObject;
|
use crate::avm1::object::array_object::ArrayObject;
|
||||||
use crate::avm1::object::bitmap_data::BitmapDataObject;
|
|
||||||
use crate::avm1::object::convolution_filter::ConvolutionFilterObject;
|
use crate::avm1::object::convolution_filter::ConvolutionFilterObject;
|
||||||
use crate::avm1::object::displacement_map_filter::DisplacementMapFilterObject;
|
use crate::avm1::object::displacement_map_filter::DisplacementMapFilterObject;
|
||||||
use crate::avm1::object::gradient_bevel_filter::GradientBevelFilterObject;
|
use crate::avm1::object::gradient_bevel_filter::GradientBevelFilterObject;
|
||||||
|
@ -21,6 +20,7 @@ use crate::avm1::object::value_object::ValueObject;
|
||||||
use crate::avm1::object::xml_node_object::XmlNodeObject;
|
use crate::avm1::object::xml_node_object::XmlNodeObject;
|
||||||
use crate::avm1::object::xml_object::XmlObject;
|
use crate::avm1::object::xml_object::XmlObject;
|
||||||
use crate::avm1::{Activation, Attribute, Error, ScriptObject, SoundObject, StageObject, Value};
|
use crate::avm1::{Activation, Attribute, Error, ScriptObject, SoundObject, StageObject, Value};
|
||||||
|
use crate::bitmap::bitmap_data::BitmapDataWrapper;
|
||||||
use crate::display_object::DisplayObject;
|
use crate::display_object::DisplayObject;
|
||||||
use crate::display_object::TDisplayObject;
|
use crate::display_object::TDisplayObject;
|
||||||
use crate::html::TextFormat;
|
use crate::html::TextFormat;
|
||||||
|
@ -32,7 +32,6 @@ use ruffle_macros::enum_trait_object;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
pub mod array_object;
|
pub mod array_object;
|
||||||
pub mod bitmap_data;
|
|
||||||
pub mod convolution_filter;
|
pub mod convolution_filter;
|
||||||
mod custom_object;
|
mod custom_object;
|
||||||
pub mod displacement_map_filter;
|
pub mod displacement_map_filter;
|
||||||
|
@ -61,6 +60,7 @@ pub enum NativeObject<'gc> {
|
||||||
ColorTransform(GcCell<'gc, ColorTransformObject>),
|
ColorTransform(GcCell<'gc, ColorTransformObject>),
|
||||||
TextFormat(GcCell<'gc, TextFormat>),
|
TextFormat(GcCell<'gc, TextFormat>),
|
||||||
NetStream(NetStream<'gc>),
|
NetStream(NetStream<'gc>),
|
||||||
|
BitmapData(BitmapDataWrapper<'gc>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents an object that can be directly interacted with by the AVM
|
/// Represents an object that can be directly interacted with by the AVM
|
||||||
|
@ -85,7 +85,6 @@ pub enum NativeObject<'gc> {
|
||||||
ConvolutionFilterObject(ConvolutionFilterObject<'gc>),
|
ConvolutionFilterObject(ConvolutionFilterObject<'gc>),
|
||||||
GradientBevelFilterObject(GradientBevelFilterObject<'gc>),
|
GradientBevelFilterObject(GradientBevelFilterObject<'gc>),
|
||||||
GradientGlowFilterObject(GradientGlowFilterObject<'gc>),
|
GradientGlowFilterObject(GradientGlowFilterObject<'gc>),
|
||||||
BitmapData(BitmapDataObject<'gc>),
|
|
||||||
}
|
}
|
||||||
)]
|
)]
|
||||||
pub trait TObject<'gc>: 'gc + Collect + Into<Object<'gc>> + Clone + Copy {
|
pub trait TObject<'gc>: 'gc + Collect + Into<Object<'gc>> + Clone + Copy {
|
||||||
|
@ -627,11 +626,6 @@ pub trait TObject<'gc>: 'gc + Collect + Into<Object<'gc>> + Clone + Copy {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the underlying `BitmapDataObject`, if it exists
|
|
||||||
fn as_bitmap_data_object(&self) -> Option<BitmapDataObject<'gc>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_ptr(&self) -> *const ObjectPtr;
|
fn as_ptr(&self) -> *const ObjectPtr;
|
||||||
|
|
||||||
/// Check if this object is in the prototype chain of the specified test object.
|
/// Check if this object is in the prototype chain of the specified test object.
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
use crate::avm1::{Object, ScriptObject, TObject};
|
|
||||||
use crate::context::UpdateContext;
|
|
||||||
use crate::impl_custom_object;
|
|
||||||
use gc_arena::{Collect, GcCell, MutationContext};
|
|
||||||
|
|
||||||
use crate::bitmap::bitmap_data::{BitmapData, BitmapDataWrapper};
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
/// A BitmapData
|
|
||||||
#[derive(Clone, Copy, Collect)]
|
|
||||||
#[collect(no_drop)]
|
|
||||||
pub struct BitmapDataObject<'gc>(GcCell<'gc, BitmapDataData<'gc>>);
|
|
||||||
|
|
||||||
#[derive(Clone, Collect)]
|
|
||||||
#[collect(no_drop)]
|
|
||||||
pub struct BitmapDataData<'gc> {
|
|
||||||
/// The underlying script object.
|
|
||||||
base: ScriptObject<'gc>,
|
|
||||||
data: BitmapDataWrapper<'gc>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for BitmapDataObject<'_> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
f.debug_struct("BitmapData")
|
|
||||||
.field("ptr", &self.0.as_ptr())
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'gc> BitmapDataObject<'gc> {
|
|
||||||
pub fn bitmap_data(&self) -> BitmapDataWrapper<'gc> {
|
|
||||||
self.0.read().data
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn empty_object(gc_context: MutationContext<'gc, '_>, proto: Object<'gc>) -> Self {
|
|
||||||
Self::with_bitmap_data(gc_context, proto, Default::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_bitmap_data(
|
|
||||||
gc_context: MutationContext<'gc, '_>,
|
|
||||||
proto: Object<'gc>,
|
|
||||||
bitmap_data: BitmapData<'gc>,
|
|
||||||
) -> Self {
|
|
||||||
Self(GcCell::allocate(
|
|
||||||
gc_context,
|
|
||||||
BitmapDataData {
|
|
||||||
base: ScriptObject::new(gc_context, Some(proto)),
|
|
||||||
data: BitmapDataWrapper::new(GcCell::allocate(gc_context, bitmap_data)),
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn width(&self) -> u32 {
|
|
||||||
self.0.read().data.width()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn height(&self) -> u32 {
|
|
||||||
self.0.read().data.height()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn transparency(&self) -> bool {
|
|
||||||
self.0.read().data.transparency()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn disposed(&self) -> bool {
|
|
||||||
self.0.read().data.disposed()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dispose(&self, context: &mut UpdateContext<'_, 'gc>) {
|
|
||||||
self.bitmap_data().dispose(context.gc_context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'gc> TObject<'gc> for BitmapDataObject<'gc> {
|
|
||||||
impl_custom_object!(base {
|
|
||||||
bare_object(as_bitmap_data_object -> BitmapDataObject::empty_object);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -55,7 +55,8 @@ pub fn init<'gc>(
|
||||||
.character_by_id(symbol_id)
|
.character_by_id(symbol_id)
|
||||||
.cloned()
|
.cloned()
|
||||||
{
|
{
|
||||||
let new_bitmap_data = fill_bitmap_data_from_symbol(activation, bitmap);
|
let new_bitmap_data =
|
||||||
|
fill_bitmap_data_from_symbol(activation.context.gc_context, bitmap);
|
||||||
BitmapDataObject::from_bitmap_data(
|
BitmapDataObject::from_bitmap_data(
|
||||||
activation,
|
activation,
|
||||||
new_bitmap_data,
|
new_bitmap_data,
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
use crate::avm2::activation::Activation;
|
use crate::avm2::activation::Activation;
|
||||||
use crate::avm2::error::{argument_error, make_error_2008, range_error};
|
use crate::avm2::error::{argument_error, make_error_2008, range_error};
|
||||||
use crate::avm2::filters::FilterAvm2Ext;
|
use crate::avm2::filters::FilterAvm2Ext;
|
||||||
|
pub use crate::avm2::object::bitmap_data_allocator;
|
||||||
use crate::avm2::object::{BitmapDataObject, ByteArrayObject, Object, TObject, VectorObject};
|
use crate::avm2::object::{BitmapDataObject, ByteArrayObject, Object, TObject, VectorObject};
|
||||||
|
use crate::avm2::parameters::{null_parameter_error, ParametersExt};
|
||||||
use crate::avm2::value::Value;
|
use crate::avm2::value::Value;
|
||||||
use crate::avm2::vector::VectorStorage;
|
use crate::avm2::vector::VectorStorage;
|
||||||
use crate::avm2::Error;
|
use crate::avm2::Error;
|
||||||
|
@ -14,34 +16,29 @@ use crate::bitmap::bitmap_data::{BitmapDataDrawError, IBitmapDrawable};
|
||||||
use crate::bitmap::{is_size_valid, operations};
|
use crate::bitmap::{is_size_valid, operations};
|
||||||
use crate::character::Character;
|
use crate::character::Character;
|
||||||
use crate::display_object::Bitmap;
|
use crate::display_object::Bitmap;
|
||||||
|
use crate::display_object::TDisplayObject;
|
||||||
use crate::swf::BlendMode;
|
use crate::swf::BlendMode;
|
||||||
use gc_arena::GcCell;
|
use gc_arena::{GcCell, MutationContext};
|
||||||
use ruffle_render::filters::Filter;
|
use ruffle_render::filters::Filter;
|
||||||
use ruffle_render::transform::Transform;
|
use ruffle_render::transform::Transform;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
pub use crate::avm2::object::bitmap_data_allocator;
|
|
||||||
use crate::avm2::parameters::{null_parameter_error, ParametersExt};
|
|
||||||
use crate::display_object::TDisplayObject;
|
|
||||||
|
|
||||||
/// Copy the static data from a given Bitmap into a new BitmapData.
|
/// Copy the static data from a given Bitmap into a new BitmapData.
|
||||||
///
|
///
|
||||||
/// `bd` is assumed to be an uninstantiated library symbol, associated with the
|
/// `bd` is assumed to be an uninstantiated library symbol, associated with the
|
||||||
/// class named by `name`.
|
/// class named by `name`.
|
||||||
pub fn fill_bitmap_data_from_symbol<'gc>(
|
pub fn fill_bitmap_data_from_symbol<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
gc_context: MutationContext<'gc, '_>,
|
||||||
bd: Bitmap<'gc>,
|
bitmap: Bitmap<'gc>,
|
||||||
) -> BitmapDataWrapper<'gc> {
|
) -> BitmapDataWrapper<'gc> {
|
||||||
let new_bitmap_data = GcCell::allocate(activation.context.gc_context, BitmapData::default());
|
let transparency = true;
|
||||||
new_bitmap_data
|
let bitmap_data = BitmapData::new_with_pixels(
|
||||||
.write(activation.context.gc_context)
|
bitmap.width().into(),
|
||||||
.set_pixels(
|
bitmap.height().into(),
|
||||||
bd.width().into(),
|
transparency,
|
||||||
bd.height().into(),
|
bitmap.bitmap_data().read().pixels().to_vec(),
|
||||||
true,
|
);
|
||||||
bd.bitmap_data().read().pixels().to_vec(),
|
BitmapDataWrapper::new(GcCell::allocate(gc_context, bitmap_data))
|
||||||
);
|
|
||||||
BitmapDataWrapper::new(new_bitmap_data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implements `flash.display.BitmapData`'s 'init' method (invoked from the AS3 constructor)
|
/// Implements `flash.display.BitmapData`'s 'init' method (invoked from the AS3 constructor)
|
||||||
|
@ -75,11 +72,8 @@ pub fn init<'gc>(
|
||||||
|
|
||||||
let new_bitmap_data = if let Some(Character::Bitmap(bitmap)) = character {
|
let new_bitmap_data = if let Some(Character::Bitmap(bitmap)) = character {
|
||||||
// Instantiating BitmapData from an Animate-style bitmap asset
|
// Instantiating BitmapData from an Animate-style bitmap asset
|
||||||
fill_bitmap_data_from_symbol(activation, bitmap)
|
fill_bitmap_data_from_symbol(activation.context.gc_context, bitmap)
|
||||||
} else {
|
} else {
|
||||||
let new_bitmap_data =
|
|
||||||
GcCell::allocate(activation.context.gc_context, BitmapData::default());
|
|
||||||
|
|
||||||
if character.is_some() {
|
if character.is_some() {
|
||||||
//TODO: Determine if mismatched symbols will still work as a
|
//TODO: Determine if mismatched symbols will still work as a
|
||||||
//regular BitmapData subclass, or if this should throw
|
//regular BitmapData subclass, or if this should throw
|
||||||
|
@ -92,7 +86,7 @@ pub fn init<'gc>(
|
||||||
let width = args.get_u32(activation, 0)?;
|
let width = args.get_u32(activation, 0)?;
|
||||||
let height = args.get_u32(activation, 1)?;
|
let height = args.get_u32(activation, 1)?;
|
||||||
let transparency = args.get_bool(2);
|
let transparency = args.get_bool(2);
|
||||||
let fill_color = args.get_u32(activation, 3)?;
|
let fill_color = args.get_i32(activation, 3)?;
|
||||||
|
|
||||||
if !is_size_valid(activation.context.swf.version(), width, height) {
|
if !is_size_valid(activation.context.swf.version(), width, height) {
|
||||||
return Err(Error::AvmError(argument_error(
|
return Err(Error::AvmError(argument_error(
|
||||||
|
@ -102,10 +96,11 @@ pub fn init<'gc>(
|
||||||
)?));
|
)?));
|
||||||
}
|
}
|
||||||
|
|
||||||
new_bitmap_data
|
let new_bitmap_data = BitmapData::new(width, height, transparency, fill_color);
|
||||||
.write(activation.context.gc_context)
|
BitmapDataWrapper::new(GcCell::allocate(
|
||||||
.init_pixels(width, height, transparency, fill_color as i32);
|
activation.context.gc_context,
|
||||||
BitmapDataWrapper::new(new_bitmap_data)
|
new_bitmap_data,
|
||||||
|
))
|
||||||
};
|
};
|
||||||
|
|
||||||
new_bitmap_data.init_object2(activation.context.gc_context, this);
|
new_bitmap_data.init_object2(activation.context.gc_context, this);
|
||||||
|
|
|
@ -199,7 +199,7 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Collect, Default)]
|
#[derive(Clone, Collect)]
|
||||||
#[collect(no_drop)]
|
#[collect(no_drop)]
|
||||||
pub struct BitmapData<'gc> {
|
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
|
||||||
|
@ -229,14 +229,15 @@ pub struct BitmapData<'gc> {
|
||||||
dirty_state: DirtyState,
|
dirty_state: DirtyState,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Collect, Default, Debug)]
|
#[derive(Clone, Collect, Debug)]
|
||||||
#[collect(require_static)]
|
#[collect(require_static)]
|
||||||
enum DirtyState {
|
enum DirtyState {
|
||||||
// Both the CPU and GPU pixels are up to date. We do not need to wait for any syncs to complete
|
// Both the CPU and GPU pixels are up to date. We do not need to wait for any syncs to complete
|
||||||
#[default]
|
|
||||||
Clean,
|
Clean,
|
||||||
|
|
||||||
// The CPU pixels have been modified, and need to be synced to the GPU via `update_dirty_texture`
|
// The CPU pixels have been modified, and need to be synced to the GPU via `update_dirty_texture`
|
||||||
CpuModified(PixelRegion),
|
CpuModified(PixelRegion),
|
||||||
|
|
||||||
// The GPU pixels have been modified, and need to be synced to the CPU via `BitmapDataWrapper::sync`
|
// The GPU pixels have been modified, and need to be synced to the CPU via `BitmapDataWrapper::sync`
|
||||||
GpuModified(Box<dyn SyncHandle>, PixelRegion),
|
GpuModified(Box<dyn SyncHandle>, PixelRegion),
|
||||||
}
|
}
|
||||||
|
@ -483,15 +484,20 @@ impl fmt::Debug for BitmapData<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'gc> BitmapData<'gc> {
|
impl<'gc> BitmapData<'gc> {
|
||||||
pub fn init_pixels(&mut self, width: u32, height: u32, transparency: bool, fill_color: i32) {
|
pub fn new(width: u32, height: u32, transparency: bool, fill_color: i32) -> Self {
|
||||||
self.width = width;
|
Self {
|
||||||
self.height = height;
|
pixels: vec![
|
||||||
self.transparency = transparency;
|
Color(fill_color).to_premultiplied_alpha(transparency);
|
||||||
self.pixels = vec![
|
width as usize * height as usize
|
||||||
Color(fill_color).to_premultiplied_alpha(self.transparency());
|
],
|
||||||
width as usize * height as usize
|
width,
|
||||||
];
|
height,
|
||||||
self.set_cpu_dirty(PixelRegion::for_whole_size(width, height));
|
transparency,
|
||||||
|
disposed: false,
|
||||||
|
bitmap_handle: None,
|
||||||
|
avm2_object: None,
|
||||||
|
dirty_state: DirtyState::Clean,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_pixels(
|
pub fn new_with_pixels(
|
||||||
|
@ -568,14 +574,6 @@ impl<'gc> BitmapData<'gc> {
|
||||||
&self.pixels
|
&self.pixels
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_pixels(&mut self, width: u32, height: u32, transparency: bool, pixels: Vec<Color>) {
|
|
||||||
self.width = width;
|
|
||||||
self.height = height;
|
|
||||||
self.transparency = transparency;
|
|
||||||
self.pixels = pixels;
|
|
||||||
self.set_cpu_dirty(PixelRegion::for_whole_size(width, height));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pixels_rgba(&self) -> Vec<u8> {
|
pub fn pixels_rgba(&self) -> Vec<u8> {
|
||||||
// TODO: This could have been implemented as follows:
|
// TODO: This could have been implemented as follows:
|
||||||
//
|
//
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::avm2::{
|
||||||
Activation as Avm2Activation, ClassObject as Avm2ClassObject, Object as Avm2Object,
|
Activation as Avm2Activation, ClassObject as Avm2ClassObject, Object as Avm2Object,
|
||||||
StageObject as Avm2StageObject, Value as Avm2Value,
|
StageObject as Avm2StageObject, Value as Avm2Value,
|
||||||
};
|
};
|
||||||
use crate::bitmap::bitmap_data::BitmapDataWrapper;
|
use crate::bitmap::bitmap_data::{BitmapData, BitmapDataWrapper};
|
||||||
use crate::context::{RenderContext, UpdateContext};
|
use crate::context::{RenderContext, UpdateContext};
|
||||||
use crate::display_object::{DisplayObjectBase, DisplayObjectPtr, TDisplayObject};
|
use crate::display_object::{DisplayObjectBase, DisplayObjectPtr, TDisplayObject};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -135,30 +135,24 @@ impl<'gc> Bitmap<'gc> {
|
||||||
) -> Result<Self, ruffle_render::error::Error> {
|
) -> Result<Self, ruffle_render::error::Error> {
|
||||||
let width = bitmap.width();
|
let width = bitmap.width();
|
||||||
let height = bitmap.height();
|
let height = bitmap.height();
|
||||||
|
let transparency = match bitmap.format() {
|
||||||
|
BitmapFormat::Rgba => true,
|
||||||
|
BitmapFormat::Rgb => false,
|
||||||
|
_ => unreachable!(
|
||||||
|
"Bitmap objects can only be constructed from RGB or RGBA source bitmaps"
|
||||||
|
),
|
||||||
|
};
|
||||||
let pixels: Vec<_> = bitmap
|
let pixels: Vec<_> = bitmap
|
||||||
.as_colors()
|
.as_colors()
|
||||||
.map(crate::bitmap::bitmap_data::Color::from)
|
.map(crate::bitmap::bitmap_data::Color::from)
|
||||||
.collect();
|
.collect();
|
||||||
let mut bitmap_data = crate::bitmap::bitmap_data::BitmapData::default();
|
let bitmap_data = BitmapData::new_with_pixels(width, height, transparency, pixels);
|
||||||
bitmap_data.set_pixels(
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
match bitmap.format() {
|
|
||||||
BitmapFormat::Rgba => true,
|
|
||||||
BitmapFormat::Rgb => false,
|
|
||||||
_ => unreachable!(
|
|
||||||
"Bitmap objects can only be constructed from RGB or RGBA source bitmaps"
|
|
||||||
),
|
|
||||||
},
|
|
||||||
pixels,
|
|
||||||
);
|
|
||||||
let bitmap_data = GcCell::allocate(context.gc_context, bitmap_data);
|
|
||||||
|
|
||||||
let smoothing = true;
|
let smoothing = true;
|
||||||
Ok(Self::new_with_bitmap_data(
|
Ok(Self::new_with_bitmap_data(
|
||||||
context,
|
context,
|
||||||
id,
|
id,
|
||||||
BitmapDataWrapper::new(bitmap_data),
|
BitmapDataWrapper::new(GcCell::allocate(context.gc_context, bitmap_data)),
|
||||||
smoothing,
|
smoothing,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -179,7 +173,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) -> GcCell<'gc, crate::bitmap::bitmap_data::BitmapData<'gc>> {
|
pub fn bitmap_data(self) -> GcCell<'gc, BitmapData<'gc>> {
|
||||||
self.0.read().bitmap_data.sync()
|
self.0.read().bitmap_data.sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,16 +5,16 @@ use crate::avm1::ExecutionReason;
|
||||||
use crate::avm1::{Activation, ActivationIdentifier};
|
use crate::avm1::{Activation, ActivationIdentifier};
|
||||||
use crate::avm1::{Object, SoundObject, TObject, Value};
|
use crate::avm1::{Object, SoundObject, TObject, Value};
|
||||||
use crate::avm2::bytearray::ByteArrayStorage;
|
use crate::avm2::bytearray::ByteArrayStorage;
|
||||||
use crate::avm2::object::ByteArrayObject;
|
use crate::avm2::object::{
|
||||||
use crate::avm2::object::EventObject as Avm2EventObject;
|
BitmapDataObject, ByteArrayObject, EventObject as Avm2EventObject, LoaderStream, TObject as _,
|
||||||
use crate::avm2::object::LoaderStream;
|
};
|
||||||
use crate::avm2::object::TObject as _;
|
|
||||||
use crate::avm2::{
|
use crate::avm2::{
|
||||||
Activation as Avm2Activation, Avm2, Domain as Avm2Domain, Object as Avm2Object,
|
Activation as Avm2Activation, Avm2, Domain as Avm2Domain, Object as Avm2Object,
|
||||||
Value as Avm2Value,
|
Value as Avm2Value,
|
||||||
};
|
};
|
||||||
use crate::backend::navigator::{OwnedFuture, Request};
|
use crate::backend::navigator::{OwnedFuture, Request};
|
||||||
use crate::bitmap::bitmap_data::Color;
|
use crate::bitmap::bitmap_data::Color;
|
||||||
|
use crate::bitmap::bitmap_data::{BitmapData, BitmapDataWrapper};
|
||||||
use crate::context::{ActionQueue, ActionType, UpdateContext};
|
use crate::context::{ActionQueue, ActionType, UpdateContext};
|
||||||
use crate::display_object::{
|
use crate::display_object::{
|
||||||
DisplayObject, TDisplayObject, TDisplayObjectContainer, TInteractiveObject,
|
DisplayObject, TDisplayObject, TDisplayObjectContainer, TInteractiveObject,
|
||||||
|
@ -28,7 +28,7 @@ use crate::string::AvmString;
|
||||||
use crate::tag_utils::SwfMovie;
|
use crate::tag_utils::SwfMovie;
|
||||||
use crate::vminterface::Instantiator;
|
use crate::vminterface::Instantiator;
|
||||||
use encoding_rs::UTF_8;
|
use encoding_rs::UTF_8;
|
||||||
use gc_arena::{Collect, CollectionContext};
|
use gc_arena::{Collect, CollectionContext, GcCell};
|
||||||
use generational_arena::{Arena, Index};
|
use generational_arena::{Arena, Index};
|
||||||
use ruffle_render::utils::{determine_jpeg_tag_format, JpegTagFormat};
|
use ruffle_render::utils::{determine_jpeg_tag_format, JpegTagFormat};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -1492,28 +1492,24 @@ impl<'gc> Loader<'gc> {
|
||||||
// since Bitmap and BitmapData never have AVM1-side objects.
|
// since Bitmap and BitmapData never have AVM1-side objects.
|
||||||
let bitmap = ruffle_render::utils::decode_define_bits_jpeg(data, None)?;
|
let bitmap = ruffle_render::utils::decode_define_bits_jpeg(data, None)?;
|
||||||
|
|
||||||
let bitmapdata_avm2 = activation
|
let transparency = true;
|
||||||
.avm2()
|
let bitmap_data = BitmapData::new_with_pixels(
|
||||||
.classes()
|
bitmap.width(),
|
||||||
.bitmapdata
|
bitmap.height(),
|
||||||
.construct(
|
transparency,
|
||||||
&mut activation,
|
bitmap.as_colors().map(Color::from).collect(),
|
||||||
&[bitmap.width().into(), bitmap.height().into(), true.into()],
|
);
|
||||||
)
|
let bitmapdata_wrapper = BitmapDataWrapper::new(GcCell::allocate(
|
||||||
.unwrap();
|
activation.context.gc_context,
|
||||||
|
bitmap_data,
|
||||||
let bitmapdata_wrapper = bitmapdata_avm2.as_bitmap_data().unwrap();
|
));
|
||||||
|
let bitmapdata_class = activation.context.avm2.classes().bitmapdata;
|
||||||
bitmapdata_wrapper
|
let bitmapdata_avm2 = BitmapDataObject::from_bitmap_data(
|
||||||
.overwrite_cpu_pixels_from_gpu(activation.context.gc_context)
|
&mut activation,
|
||||||
.0
|
bitmapdata_wrapper,
|
||||||
.write(activation.context.gc_context)
|
bitmapdata_class,
|
||||||
.set_pixels(
|
)
|
||||||
bitmap.width(),
|
.unwrap();
|
||||||
bitmap.height(),
|
|
||||||
true,
|
|
||||||
bitmap.as_colors().map(Color::from).collect(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let bitmap_avm2 = activation
|
let bitmap_avm2 = activation
|
||||||
.avm2()
|
.avm2()
|
||||||
|
|
Loading…
Reference in New Issue