avm1: Migrate `DisplacementMapFilter` to `NativeObject`

This commit is contained in:
relrelb 2023-04-07 19:56:07 +03:00 committed by relrelb
parent 420643b045
commit ee30646745
8 changed files with 374 additions and 464 deletions

View File

@ -26,7 +26,7 @@ pub(crate) mod context_menu;
pub(crate) mod context_menu_item;
pub mod convolution_filter;
pub(crate) mod date;
pub mod displacement_map_filter;
pub(crate) mod displacement_map_filter;
pub(crate) mod drop_shadow_filter;
pub(crate) mod error;
mod external_interface;
@ -499,8 +499,6 @@ pub struct SystemPrototypes<'gc> {
pub context_menu_item_constructor: Object<'gc>,
pub bitmap_filter: Object<'gc>,
pub bitmap_filter_constructor: Object<'gc>,
pub displacement_map_filter: Object<'gc>,
pub displacement_map_filter_constructor: Object<'gc>,
pub convolution_filter: Object<'gc>,
pub convolution_filter_constructor: Object<'gc>,
pub gradient_bevel_filter: Object<'gc>,
@ -508,7 +506,7 @@ pub struct SystemPrototypes<'gc> {
pub gradient_glow_filter: Object<'gc>,
pub gradient_glow_filter_constructor: Object<'gc>,
pub date_constructor: Object<'gc>,
pub bitmap_data_constructor: Object<'gc>,
pub bitmap_data: Object<'gc>,
pub video: Object<'gc>,
pub video_constructor: Object<'gc>,
}
@ -760,15 +758,8 @@ pub fn create_globals<'gc>(
let color_matrix_filter =
color_matrix_filter::create_constructor(context, bitmap_filter_proto, function_proto);
let displacement_map_filter_proto =
displacement_map_filter::create_proto(context, bitmap_filter_proto, function_proto);
let displacement_map_filter = FunctionObject::constructor(
gc_context,
Executable::Native(displacement_map_filter::constructor),
constructor_to_fn!(displacement_map_filter::constructor),
function_proto,
displacement_map_filter_proto,
);
let displacement_map_filter =
displacement_map_filter::create_constructor(context, bitmap_filter_proto, function_proto);
let convolution_filter_proto =
convolution_filter::create_proto(context, bitmap_filter_proto, function_proto);
@ -862,7 +853,8 @@ pub fn create_globals<'gc>(
Attribute::empty(),
);
let bitmap_data = bitmap_data::create_constructor(context, object_proto, function_proto);
let bitmap_data_proto = ScriptObject::new(context.gc_context, Some(object_proto));
let bitmap_data = bitmap_data::create_constructor(context, bitmap_data_proto, function_proto);
display.define_value(
gc_context,
@ -1118,8 +1110,6 @@ pub fn create_globals<'gc>(
context_menu_item_constructor: context_menu_item,
bitmap_filter: bitmap_filter_proto,
bitmap_filter_constructor: bitmap_filter,
displacement_map_filter: displacement_map_filter_proto,
displacement_map_filter_constructor: displacement_map_filter,
convolution_filter: convolution_filter_proto,
convolution_filter_constructor: convolution_filter,
gradient_bevel_filter: gradient_bevel_filter_proto,
@ -1127,7 +1117,7 @@ pub fn create_globals<'gc>(
gradient_glow_filter: gradient_glow_filter_proto,
gradient_glow_filter_constructor: gradient_glow_filter,
date_constructor: date,
bitmap_data_constructor: bitmap_data,
bitmap_data: bitmap_data_proto.into(),
video: video_proto,
video_constructor: video,
},

View File

@ -1417,18 +1417,17 @@ fn load_bitmap<'gc>(
pub fn create_constructor<'gc>(
context: &mut GcContext<'_, 'gc>,
proto: Object<'gc>,
proto: ScriptObject<'gc>,
fn_proto: Object<'gc>,
) -> Object<'gc> {
let bitmap_data_proto = ScriptObject::new(context.gc_context, Some(proto));
define_properties_on(PROTO_DECLS, context, bitmap_data_proto, fn_proto);
define_properties_on(PROTO_DECLS, context, proto, fn_proto);
let bitmap_data_constructor = FunctionObject::constructor(
context.gc_context,
Executable::Native(constructor),
constructor_to_fn!(constructor),
fn_proto,
bitmap_data_proto.into(),
proto.into(),
);
let object = bitmap_data_constructor.raw_script_object();
define_properties_on(OBJECT_DECLS, context, object, fn_proto);

View File

@ -40,6 +40,11 @@ pub fn clone<'gc>(
NativeObject::ColorMatrixFilter(color_matrix_filter) => NativeObject::ColorMatrixFilter(
color_matrix_filter.duplicate(activation.context.gc_context),
),
NativeObject::DisplacementMapFilter(displacement_map_filter) => {
NativeObject::DisplacementMapFilter(
displacement_map_filter.duplicate(activation.context.gc_context),
)
}
_ => NativeObject::None,
};
if !matches!(native, NativeObject::None) {
@ -59,41 +64,6 @@ pub fn clone<'gc>(
return Ok(cloned.into());
}
if let Some(this) = this.as_displacement_map_filter_object() {
let proto = activation
.context
.avm1
.prototypes()
.displacement_map_filter_constructor;
let map_bitmap = this.get("mapBitmap", activation)?;
let map_point = this.get("mapPoint", activation)?;
let component_x = this.get("componentX", activation)?;
let component_y = this.get("componentY", activation)?;
let scale_x = this.get("scaleX", activation)?;
let scale_y = this.get("scaleY", activation)?;
let mode = this.get("mode", activation)?;
let color = this.get("color", activation)?;
let alpha = this.get("alpha", activation)?;
let cloned = proto.construct(
activation,
&[
map_bitmap,
map_point,
component_x,
component_y,
scale_x,
scale_y,
mode,
color,
alpha,
],
)?;
return Ok(cloned);
}
if let Some(this) = this.as_convolution_filter_object() {
let proto = activation
.context

View File

@ -1,311 +1,388 @@
//! flash.filters.DisplacementMapFilter object
use crate::avm1::activation::Activation;
use crate::avm1::clamp::Clamp;
use crate::avm1::error::Error;
use crate::avm1::object::displacement_map_filter::DisplacementMapFilterObject;
use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::object::NativeObject;
use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{Object, TObject, Value};
use crate::context::GcContext;
use crate::string::{AvmString, WStr};
use crate::avm1::{Activation, Error, Object, ScriptObject, TObject, Value};
use crate::bitmap::bitmap_data::BitmapDataWrapper;
use crate::context::{GcContext, UpdateContext};
use crate::string::{AvmString, FromWStr, WStr};
use gc_arena::{Collect, GcCell, MutationContext};
use std::convert::Infallible;
use std::fmt::Debug;
use swf::{Color, Point};
const PROTO_DECLS: &[Declaration] = declare_properties! {
"alpha" => property(alpha, set_alpha);
"color" => property(color, set_color);
"componentX" => property(component_x, set_component_x);
"componentY" => property(component_y, set_component_y);
"mapBitmap" => property(map_bitmap, set_map_bitmap);
"mapPoint" => property(map_point, set_map_point);
"mode" => property(mode, set_mode);
"scaleX" => property(scale_x, set_scale_x);
"scaleY" => property(scale_y, set_scale_y);
};
pub fn constructor<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
set_map_bitmap(activation, this, args.get(0..1).unwrap_or_default())?;
set_map_point(activation, this, args.get(1..2).unwrap_or_default())?;
set_component_x(activation, this, args.get(2..3).unwrap_or_default())?;
set_component_y(activation, this, args.get(3..4).unwrap_or_default())?;
set_scale_x(activation, this, args.get(4..5).unwrap_or_default())?;
set_scale_y(activation, this, args.get(5..6).unwrap_or_default())?;
set_mode(activation, this, args.get(6..7).unwrap_or_default())?;
set_color(activation, this, args.get(7..8).unwrap_or_default())?;
set_alpha(activation, this, args.get(8..9).unwrap_or_default())?;
Ok(this.into())
#[derive(Copy, Clone, Collect, Debug, Default)]
#[collect(require_static)]
enum Mode {
#[default]
Wrap,
Clamp,
Ignore,
Color,
}
pub fn alpha<'gc>(
_activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(filter) = this.as_displacement_map_filter_object() {
return Ok(filter.alpha().into());
impl From<Mode> for &'static WStr {
fn from(mode: Mode) -> &'static WStr {
match mode {
Mode::Wrap => WStr::from_units(b"wrap"),
Mode::Clamp => WStr::from_units(b"clamp"),
Mode::Ignore => WStr::from_units(b"ignore"),
Mode::Color => WStr::from_units(b"color"),
}
}
}
impl FromWStr for Mode {
type Err = Infallible;
fn from_wstr(s: &WStr) -> Result<Self, Self::Err> {
if s.eq_ignore_case(WStr::from_units(b"clamp")) {
Ok(Self::Clamp)
} else if s.eq_ignore_case(WStr::from_units(b"ignore")) {
Ok(Self::Ignore)
} else if s.eq_ignore_case(WStr::from_units(b"color")) {
Ok(Self::Color)
} else {
Ok(Self::Wrap)
}
}
}
#[derive(Clone, Collect, Debug, Default)]
#[collect(no_drop)]
struct DisplacementMapFilterData<'gc> {
map_bitmap: Option<BitmapDataWrapper<'gc>>,
#[collect(require_static)]
map_point: Point<i32>,
component_x: i32,
component_y: i32,
scale_x: f32,
scale_y: f32,
mode: Mode,
#[collect(require_static)]
color: Color,
}
#[derive(Clone, Debug, Collect)]
#[collect(no_drop)]
#[repr(transparent)]
pub struct DisplacementMapFilter<'gc>(GcCell<'gc, DisplacementMapFilterData<'gc>>);
impl<'gc> DisplacementMapFilter<'gc> {
fn new(activation: &mut Activation<'_, 'gc>, args: &[Value<'gc>]) -> Result<Self, Error<'gc>> {
let displacement_map_filter = Self(GcCell::allocate(
activation.context.gc_context,
Default::default(),
));
displacement_map_filter.set_map_bitmap(activation, args.get(0))?;
displacement_map_filter.set_map_point(activation, args.get(1))?;
displacement_map_filter.set_component_x(activation, args.get(2))?;
displacement_map_filter.set_component_y(activation, args.get(3))?;
displacement_map_filter.set_scale_x(activation, args.get(4))?;
displacement_map_filter.set_scale_y(activation, args.get(5))?;
displacement_map_filter.set_mode(activation, args.get(6))?;
displacement_map_filter.set_color(activation, args.get(7))?;
displacement_map_filter.set_alpha(activation, args.get(8))?;
Ok(displacement_map_filter)
}
Ok(Value::Undefined)
}
pub fn set_alpha<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let alpha = args
.get(0)
.unwrap_or(&0.into())
.coerce_to_f64(activation)
.map(|x| x.clamp_also_nan(0.0, 1.0))?;
if let Some(filter) = this.as_displacement_map_filter_object() {
filter.set_alpha(activation.context.gc_context, alpha);
pub(crate) fn duplicate(&self, gc_context: MutationContext<'gc, '_>) -> Self {
Self(GcCell::allocate(gc_context, self.0.read().clone()))
}
Ok(Value::Undefined)
}
pub fn color<'gc>(
_activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(object) = this.as_displacement_map_filter_object() {
return Ok(object.color().into());
}
Ok(Value::Undefined)
}
pub fn set_color<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let color = args
.get(0)
.unwrap_or(&0x000000.into())
.coerce_to_u32(activation)?;
if let Some(object) = this.as_displacement_map_filter_object() {
object.set_color(activation.context.gc_context, color & 0xFFFFFF);
}
Ok(Value::Undefined)
}
pub fn component_x<'gc>(
_activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(object) = this.as_displacement_map_filter_object() {
return Ok(object.component_x().into());
}
Ok(Value::Undefined)
}
pub fn set_component_x<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let component = args.get(0).unwrap_or(&0.into()).coerce_to_i32(activation)?;
if let Some(object) = this.as_displacement_map_filter_object() {
object.set_component_x(activation.context.gc_context, component);
}
Ok(Value::Undefined)
}
pub fn component_y<'gc>(
_activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(object) = this.as_displacement_map_filter_object() {
return Ok(object.component_y().into());
}
Ok(Value::Undefined)
}
pub fn set_component_y<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let component = args.get(0).unwrap_or(&0.into()).coerce_to_i32(activation)?;
if let Some(object) = this.as_displacement_map_filter_object() {
object.set_component_y(activation.context.gc_context, component);
}
Ok(Value::Undefined)
}
pub fn map_bitmap<'gc>(
_activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(object) = this.as_displacement_map_filter_object() {
if let Some(map_bitmap) = object.map_bitmap() {
return Ok(map_bitmap.into());
fn map_bitmap(&self, context: &mut UpdateContext<'_, 'gc>) -> Option<Object<'gc>> {
if let Some(map_bitmap) = self.0.read().map_bitmap {
let proto = context.avm1.prototypes().bitmap_data;
let result = ScriptObject::new(context.gc_context, Some(proto));
result.set_native(context.gc_context, NativeObject::BitmapData(map_bitmap));
Some(result.into())
} else {
None
}
}
Ok(Value::Undefined)
}
pub fn set_map_bitmap<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(object) = this.as_displacement_map_filter_object() {
if let [Value::Object(map_bitmap), ..] = args {
if let NativeObject::BitmapData(_) = map_bitmap.native() {
object.set_map_bitmap(activation.context.gc_context, Some(*map_bitmap));
fn set_map_bitmap(
&self,
activation: &mut Activation<'_, 'gc>,
value: Option<&Value<'gc>>,
) -> Result<(), Error<'gc>> {
if let Some(Value::Object(object)) = value {
if let NativeObject::BitmapData(bitmap_data) = object.native() {
self.0.write(activation.context.gc_context).map_bitmap = Some(bitmap_data);
}
}
Ok(())
}
Ok(Value::Undefined)
}
pub fn map_point<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(object) = this.as_displacement_map_filter_object() {
let (x, y) = object.map_point();
let proto = activation.context.avm1.prototypes().point_constructor;
let point = proto.construct(activation, &[x.into(), y.into()])?;
return Ok(point);
fn map_point(&self, activation: &mut Activation<'_, 'gc>) -> Result<Value<'gc>, Error<'gc>> {
let map_point = self.0.read().map_point;
let args = &[map_point.x.into(), map_point.y.into()];
let constructor = activation.context.avm1.prototypes().point_constructor;
constructor.construct(activation, args)
}
Ok(Value::Undefined)
fn set_map_point(
&self,
activation: &mut Activation<'_, 'gc>,
value: Option<&Value<'gc>>,
) -> Result<(), Error<'gc>> {
if let Some(Value::Object(object)) = value {
if let Some(x) = object.get_local_stored("x", activation) {
let x = x.coerce_to_f64(activation)?.clamp_to_i32();
if let Some(y) = object.get_local_stored("y", activation) {
let y = y.coerce_to_f64(activation)?.clamp_to_i32();
self.0.write(activation.context.gc_context).map_point = Point::new(x, y);
}
}
}
Ok(())
}
fn component_x(&self) -> i32 {
self.0.read().component_x
}
fn set_component_x(
&self,
activation: &mut Activation<'_, 'gc>,
value: Option<&Value<'gc>>,
) -> Result<(), Error<'gc>> {
if let Some(value) = value {
let component_x = value.coerce_to_i32(activation)?;
self.0.write(activation.context.gc_context).component_x = component_x;
}
Ok(())
}
fn component_y(&self) -> i32 {
self.0.read().component_y
}
fn set_component_y(
&self,
activation: &mut Activation<'_, 'gc>,
value: Option<&Value<'gc>>,
) -> Result<(), Error<'gc>> {
if let Some(value) = value {
let component_y = value.coerce_to_i32(activation)?;
self.0.write(activation.context.gc_context).component_y = component_y;
}
Ok(())
}
fn scale_x(&self) -> f32 {
self.0.read().scale_x
}
fn set_scale_x(
&self,
activation: &mut Activation<'_, 'gc>,
value: Option<&Value<'gc>>,
) -> Result<(), Error<'gc>> {
if let Some(value) = value {
const MAX: f64 = u16::MAX as f64;
const MIN: f64 = -MAX;
let scale_x = value.coerce_to_f64(activation)?.clamp_also_nan(MIN, MAX);
self.0.write(activation.context.gc_context).scale_x = scale_x as f32;
}
Ok(())
}
fn scale_y(&self) -> f32 {
self.0.read().scale_y
}
fn set_scale_y(
&self,
activation: &mut Activation<'_, 'gc>,
value: Option<&Value<'gc>>,
) -> Result<(), Error<'gc>> {
if let Some(value) = value {
const MAX: f64 = u16::MAX as f64;
const MIN: f64 = -MAX;
let scale_y = value.coerce_to_f64(activation)?.clamp_also_nan(MIN, MAX);
self.0.write(activation.context.gc_context).scale_y = scale_y as f32;
}
Ok(())
}
fn mode(&self) -> Mode {
self.0.read().mode
}
fn set_mode(
&self,
activation: &mut Activation<'_, 'gc>,
value: Option<&Value<'gc>>,
) -> Result<(), Error<'gc>> {
if let Some(value) = value {
let mode = value.coerce_to_string(activation)?.parse().unwrap();
self.0.write(activation.context.gc_context).mode = mode;
}
Ok(())
}
fn color(&self) -> Color {
self.0.read().color.clone()
}
fn set_color(
&self,
activation: &mut Activation<'_, 'gc>,
value: Option<&Value<'gc>>,
) -> Result<(), Error<'gc>> {
if let Some(value) = value {
let color = Color::from_rgb(value.coerce_to_u32(activation)?, u8::MAX);
self.0.write(activation.context.gc_context).color = color;
}
Ok(())
}
fn set_alpha(
&self,
activation: &mut Activation<'_, 'gc>,
value: Option<&Value<'gc>>,
) -> Result<(), Error<'gc>> {
if let Some(value) = value {
let alpha = value.coerce_to_f64(activation)?.clamp_also_nan(0.0, 1.0);
self.0.write(activation.context.gc_context).color.a = (alpha * 255.0) as u8;
}
Ok(())
}
}
pub fn set_map_point<'gc>(
macro_rules! displacement_map_filter_method {
($index:literal) => {
|activation, this, args| method(activation, this, args, $index)
};
}
const PROTO_DECLS: &[Declaration] = declare_properties! {
"mapBitmap" => property(displacement_map_filter_method!(1), displacement_map_filter_method!(2));
"mapPoint" => property(displacement_map_filter_method!(3), displacement_map_filter_method!(4));
"componentX" => property(displacement_map_filter_method!(5), displacement_map_filter_method!(6));
"componentY" => property(displacement_map_filter_method!(7), displacement_map_filter_method!(8));
"scaleX" => property(displacement_map_filter_method!(9), displacement_map_filter_method!(10));
"scaleY" => property(displacement_map_filter_method!(11), displacement_map_filter_method!(12));
"mode" => property(displacement_map_filter_method!(13), displacement_map_filter_method!(14));
"color" => property(displacement_map_filter_method!(15), displacement_map_filter_method!(16));
"alpha" => property(displacement_map_filter_method!(17), displacement_map_filter_method!(18));
};
fn method<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
index: u8,
) -> Result<Value<'gc>, Error<'gc>> {
let obj = args
.get(0)
.unwrap_or(&Value::Undefined)
.coerce_to_object(activation);
const CONSTRUCTOR: u8 = 0;
const GET_MAP_BITMAP: u8 = 1;
const SET_MAP_BITMAP: u8 = 2;
const GET_MAP_POINT: u8 = 3;
const SET_MAP_POINT: u8 = 4;
const GET_COMPONENT_X: u8 = 5;
const SET_COMPONENT_X: u8 = 6;
const GET_COMPONENT_Y: u8 = 7;
const SET_COMPONENT_Y: u8 = 8;
const GET_SCALE_X: u8 = 9;
const SET_SCALE_X: u8 = 10;
const GET_SCALE_Y: u8 = 11;
const SET_SCALE_Y: u8 = 12;
const GET_MODE: u8 = 13;
const SET_MODE: u8 = 14;
const GET_COLOR: u8 = 15;
const SET_COLOR: u8 = 16;
const GET_ALPHA: u8 = 17;
const SET_ALPHA: u8 = 18;
let x = obj.get("x", activation)?.coerce_to_i32(activation)?;
let y = obj.get("y", activation)?.coerce_to_i32(activation)?;
if let Some(object) = this.as_displacement_map_filter_object() {
object.set_map_point(activation.context.gc_context, (x, y));
if index == CONSTRUCTOR {
let displacement_map_filter = DisplacementMapFilter::new(activation, args)?;
this.set_native(
activation.context.gc_context,
NativeObject::DisplacementMapFilter(displacement_map_filter),
);
return Ok(this.into());
}
Ok(Value::Undefined)
let this = match this.native() {
NativeObject::DisplacementMapFilter(displacement_map_filter) => displacement_map_filter,
_ => return Ok(Value::Undefined),
};
Ok(match index {
GET_MAP_BITMAP => this
.map_bitmap(&mut activation.context)
.map_or(Value::Undefined, Value::from),
SET_MAP_BITMAP => {
this.set_map_bitmap(activation, args.get(0))?;
Value::Undefined
}
GET_MAP_POINT => this.map_point(activation)?,
SET_MAP_POINT => {
this.set_map_point(activation, args.get(0))?;
Value::Undefined
}
GET_COMPONENT_X => this.component_x().into(),
SET_COMPONENT_X => {
this.set_component_x(activation, args.get(0))?;
Value::Undefined
}
GET_COMPONENT_Y => this.component_y().into(),
SET_COMPONENT_Y => {
this.set_component_y(activation, args.get(0))?;
Value::Undefined
}
GET_SCALE_X => this.scale_x().into(),
SET_SCALE_X => {
this.set_scale_x(activation, args.get(0))?;
Value::Undefined
}
GET_SCALE_Y => this.scale_y().into(),
SET_SCALE_Y => {
this.set_scale_y(activation, args.get(0))?;
Value::Undefined
}
GET_MODE => {
let mode: &WStr = this.mode().into();
AvmString::from(mode).into()
}
SET_MODE => {
this.set_mode(activation, args.get(0))?;
Value::Undefined
}
GET_COLOR => this.color().to_rgb().into(),
SET_COLOR => {
this.set_color(activation, args.get(0))?;
Value::Undefined
}
GET_ALPHA => (this.color().a as f64 / 255.0).into(),
SET_ALPHA => {
this.set_alpha(activation, args.get(0))?;
Value::Undefined
}
_ => Value::Undefined,
})
}
pub fn mode<'gc>(
_activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(object) = this.as_displacement_map_filter_object() {
let mode: &WStr = object.mode().into();
return Ok(AvmString::from(mode).into());
}
Ok(Value::Undefined)
}
pub fn set_mode<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let mode = args
.get(0)
.unwrap_or(&"wrap".into())
.coerce_to_string(activation)?;
if let Some(object) = this.as_displacement_map_filter_object() {
object.set_mode(activation.context.gc_context, mode.as_wstr().into());
}
Ok(Value::Undefined)
}
pub fn scale_x<'gc>(
_activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(object) = this.as_displacement_map_filter_object() {
return Ok(object.scale_x().into());
}
Ok(Value::Undefined)
}
pub fn set_scale_x<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let scale = args.get(0).unwrap_or(&0.into()).coerce_to_f64(activation)?;
if let Some(object) = this.as_displacement_map_filter_object() {
object.set_scale_x(activation.context.gc_context, scale);
}
Ok(Value::Undefined)
}
pub fn scale_y<'gc>(
_activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(object) = this.as_displacement_map_filter_object() {
return Ok(object.scale_y().into());
}
Ok(Value::Undefined)
}
pub fn set_scale_y<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let scale = args.get(0).unwrap_or(&0.into()).coerce_to_f64(activation)?;
if let Some(object) = this.as_displacement_map_filter_object() {
object.set_scale_y(activation.context.gc_context, scale);
}
Ok(Value::Undefined)
}
pub fn create_proto<'gc>(
pub fn create_constructor<'gc>(
context: &mut GcContext<'_, 'gc>,
proto: Object<'gc>,
fn_proto: Object<'gc>,
) -> Object<'gc> {
let filter = DisplacementMapFilterObject::empty_object(context.gc_context, proto);
let object = filter.raw_script_object();
define_properties_on(PROTO_DECLS, context, object, fn_proto);
filter.into()
let displacement_map_filter_proto = ScriptObject::new(context.gc_context, Some(proto));
define_properties_on(
PROTO_DECLS,
context,
displacement_map_filter_proto,
fn_proto,
);
FunctionObject::constructor(
context.gc_context,
Executable::Native(displacement_map_filter_method!(0)),
constructor_to_fn!(displacement_map_filter_method!(0)),
fn_proto,
displacement_map_filter_proto.into(),
)
}

View File

@ -6,11 +6,11 @@ use crate::avm1::globals::blur_filter::BlurFilter;
use crate::avm1::globals::color_matrix_filter::ColorMatrixFilter;
use crate::avm1::globals::color_transform::ColorTransformObject;
use crate::avm1::globals::date::Date;
use crate::avm1::globals::displacement_map_filter::DisplacementMapFilter;
use crate::avm1::globals::drop_shadow_filter::DropShadowFilter;
use crate::avm1::globals::glow_filter::GlowFilter;
use crate::avm1::object::array_object::ArrayObject;
use crate::avm1::object::convolution_filter::ConvolutionFilterObject;
use crate::avm1::object::displacement_map_filter::DisplacementMapFilterObject;
use crate::avm1::object::gradient_bevel_filter::GradientBevelFilterObject;
use crate::avm1::object::gradient_glow_filter::GradientGlowFilterObject;
use crate::avm1::object::shared_object::SharedObject;
@ -34,7 +34,6 @@ use std::fmt::Debug;
pub mod array_object;
pub mod convolution_filter;
mod custom_object;
pub mod displacement_map_filter;
pub mod gradient_bevel_filter;
pub mod gradient_glow_filter;
pub mod script_object;
@ -57,6 +56,7 @@ pub enum NativeObject<'gc> {
GlowFilter(GlowFilter<'gc>),
DropShadowFilter(DropShadowFilter<'gc>),
ColorMatrixFilter(ColorMatrixFilter<'gc>),
DisplacementMapFilter(DisplacementMapFilter<'gc>),
ColorTransform(GcCell<'gc, ColorTransformObject>),
TextFormat(GcCell<'gc, TextFormat>),
NetStream(NetStream<'gc>),
@ -81,7 +81,6 @@ pub enum NativeObject<'gc> {
FunctionObject(FunctionObject<'gc>),
SharedObject(SharedObject<'gc>),
TransformObject(TransformObject<'gc>),
DisplacementMapFilterObject(DisplacementMapFilterObject<'gc>),
ConvolutionFilterObject(ConvolutionFilterObject<'gc>),
GradientBevelFilterObject(GradientBevelFilterObject<'gc>),
GradientGlowFilterObject(GradientGlowFilterObject<'gc>),
@ -606,11 +605,6 @@ pub trait TObject<'gc>: 'gc + Collect + Into<Object<'gc>> + Clone + Copy {
None
}
/// Get the underlying `DisplacementMapFilterObject`, if it exists
fn as_displacement_map_filter_object(&self) -> Option<DisplacementMapFilterObject<'gc>> {
None
}
/// Get the underlying `ConvolutionFilterObject`, if it exists
fn as_convolution_filter_object(&self) -> Option<ConvolutionFilterObject<'gc>> {
None

View File

@ -1,119 +0,0 @@
use crate::add_field_accessors;
use crate::avm1::{Object, ScriptObject, TObject};
use crate::impl_custom_object;
use crate::string::WStr;
use gc_arena::{Collect, GcCell, MutationContext};
use std::fmt;
#[derive(Debug, Clone, Copy, Collect)]
#[collect(no_drop)]
pub enum DisplacementMapFilterMode {
Wrap,
Clamp,
Ignore,
Color,
}
impl<'a> From<&'a WStr> for DisplacementMapFilterMode {
fn from(v: &'a WStr) -> DisplacementMapFilterMode {
if v == b"clamp" {
DisplacementMapFilterMode::Clamp
} else if v == b"ignore" {
DisplacementMapFilterMode::Ignore
} else if v == b"color" {
DisplacementMapFilterMode::Color
} else {
DisplacementMapFilterMode::Wrap
}
}
}
impl From<DisplacementMapFilterMode> for &'static WStr {
fn from(v: DisplacementMapFilterMode) -> Self {
let s: &[u8] = match v {
DisplacementMapFilterMode::Wrap => b"wrap",
DisplacementMapFilterMode::Clamp => b"clamp",
DisplacementMapFilterMode::Ignore => b"ignore",
DisplacementMapFilterMode::Color => b"color",
};
WStr::from_units(s)
}
}
/// A DisplacementMapFilter
#[derive(Clone, Copy, Collect)]
#[collect(no_drop)]
pub struct DisplacementMapFilterObject<'gc>(GcCell<'gc, DisplacementMapFilterData<'gc>>);
#[derive(Clone, Collect)]
#[collect(no_drop)]
pub struct DisplacementMapFilterData<'gc> {
/// The underlying script object.
base: ScriptObject<'gc>,
alpha: f64,
color: u32,
component_x: i32,
component_y: i32,
map_bitmap: Option<Object<'gc>>,
map_point: (i32, i32),
mode: DisplacementMapFilterMode,
scale_x: f64,
scale_y: f64,
}
impl fmt::Debug for DisplacementMapFilterObject<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let this = self.0.read();
f.debug_struct("DisplacementMapFilter")
.field("alpha", &this.alpha)
.field("color", &this.color)
.field("componentX", &this.component_x)
.field("componentY", &this.component_y)
.field("mapBitmap", &this.map_bitmap)
.field("mapPoint", &this.map_point)
.field("mode", &this.mode)
.field("scaleX", &this.scale_x)
.field("scaleY", &this.scale_y)
.finish()
}
}
impl<'gc> DisplacementMapFilterObject<'gc> {
add_field_accessors!(
[set_alpha, alpha, alpha, f64],
[set_color, color, color, u32],
[set_component_x, component_x, component_x, i32],
[set_component_y, component_y, component_y, i32],
[set_map_bitmap, map_bitmap, map_bitmap, Option<Object<'gc>>],
[set_map_point, map_point, map_point, (i32, i32)],
[set_mode, mode, mode, DisplacementMapFilterMode],
[set_scale_x, scale_x, scale_x, f64],
[set_scale_y, scale_y, scale_y, f64],
);
pub fn empty_object(gc_context: MutationContext<'gc, '_>, proto: Object<'gc>) -> Self {
DisplacementMapFilterObject(GcCell::allocate(
gc_context,
DisplacementMapFilterData {
base: ScriptObject::new(gc_context, Some(proto)),
alpha: 0.0,
color: 0,
component_x: 0,
component_y: 0,
map_bitmap: None,
map_point: (0, 0),
mode: DisplacementMapFilterMode::Wrap,
scale_x: 0.0,
scale_y: 0.0,
},
))
}
}
impl<'gc> TObject<'gc> for DisplacementMapFilterObject<'gc> {
impl_custom_object!(base {
bare_object(as_displacement_map_filter_object -> DisplacementMapFilterObject::empty_object);
});
}

View File

@ -1,11 +1,11 @@
use crate::avm2::{Object as Avm2Object, Value as Avm2Value};
use crate::display_object::{DisplayObject, TDisplayObject};
use bitflags::bitflags;
use core::fmt;
use gc_arena::Collect;
use ruffle_render::backend::RenderBackend;
use ruffle_render::bitmap::{Bitmap, BitmapFormat, BitmapHandle, PixelRegion, SyncHandle};
use ruffle_wstr::WStr;
use std::fmt::Debug;
use std::ops::Range;
use swf::{Rectangle, Twips};
use tracing::instrument;
@ -253,8 +253,6 @@ mod wrapper {
use super::{copy_pixels_to_bitmapdata, BitmapData, DirtyState};
#[derive(Collect, Copy, Clone)]
#[collect(no_drop)]
/// A wrapper type that ensures that we always wait for a pending
/// GPU -> CPU sync to complete (using `sync_handle`) before accessing
/// the CPU-side pixels.
@ -283,7 +281,8 @@ mod wrapper {
///
/// Note that we also perform CPU-GPU syncs from `BitmapData.update_dirty_texture` when `dirty` is set.
/// `sync_handle` and `dirty` can never be set at the same time - we can only have one of them set, or none of them set.
///
#[derive(Copy, Clone, Collect, Debug)]
#[collect(no_drop)]
pub struct BitmapDataWrapper<'gc>(GcCell<'gc, BitmapData<'gc>>);
impl<'gc> BitmapDataWrapper<'gc> {
@ -470,8 +469,8 @@ mod wrapper {
pub use wrapper::BitmapDataWrapper;
impl fmt::Debug for BitmapData<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl std::fmt::Debug for BitmapData<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BitmapData")
.field("dirty_state", &self.dirty_state)
.field("width", &self.width)

View File

@ -1,7 +1,7 @@
/// An RGBA (red, green, blue, alpha) color.
///
/// All components are stored as [`u8`] and have a color range of 0-255.
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Color {
/// The red component value.
pub r: u8,