avm1: Migrate `ColorTransform` to `NativeObject`

This commit is contained in:
relrelb 2022-09-24 09:40:48 +03:00 committed by relrelb
parent ceb877c55f
commit 898ccfba5d
6 changed files with 225 additions and 349 deletions

View File

@ -21,7 +21,7 @@ pub(crate) mod boolean;
pub(crate) mod button;
mod color;
pub mod color_matrix_filter;
mod color_transform;
pub(crate) mod color_transform;
pub(crate) mod context_menu;
pub(crate) mod context_menu_item;
pub mod convolution_filter;

View File

@ -1,12 +1,11 @@
//! flash.display.BitmapData object
use super::{color_transform::object_to_color_transform, matrix::object_to_matrix};
use crate::avm1::activation::Activation;
use crate::avm1::error::Error;
use super::matrix::object_to_matrix;
use crate::avm1::function::{Executable, FunctionObject};
use crate::avm1::globals::color_transform::ColorTransformObject;
use crate::avm1::object::bitmap_data::BitmapDataObject;
use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{Object, TObject, Value};
use crate::avm1::{Activation, Error, Object, TObject, Value};
use crate::avm_error;
use crate::bitmap::bitmap_data::IBitmapDrawable;
use crate::bitmap::bitmap_data::{BitmapData, ChannelOptions, Color};
@ -503,8 +502,8 @@ pub fn draw<'gc>(
let color_transform = args
.get(2)
.map(|o| o.coerce_to_object(activation))
.and_then(|o| object_to_color_transform(o, activation).ok())
.and_then(|v| ColorTransformObject::cast(*v))
.map(|color_transform| color_transform.read().clone().into())
.unwrap_or_default();
if args.get(3).is_some() {
@ -586,38 +585,33 @@ pub fn color_transform<'gc>(
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(bitmap_data) = this.as_bitmap_data_object() {
if !bitmap_data.disposed() {
let rectangle = args
.get(0)
.unwrap_or(&Value::Undefined)
.coerce_to_object(activation);
if let [rectangle, color_transform, ..] = args {
// TODO: Re-use `object_to_rectangle` in `movie_clip.rs`.
let rectangle = rectangle.coerce_to_object(activation);
let x = rectangle.get("x", activation)?.coerce_to_f64(activation)? as i32;
let y = rectangle.get("y", activation)?.coerce_to_f64(activation)? as i32;
let width = rectangle
.get("width", activation)?
.coerce_to_f64(activation)? as i32;
let height = rectangle
.get("height", activation)?
.coerce_to_f64(activation)? as i32;
let color_transform = args
.get(1)
.unwrap_or(&Value::Undefined)
.coerce_to_object(activation);
let x_min = x.max(0) as u32;
let x_max = (x + width) as u32;
let y_min = y.max(0) as u32;
let y_max = (y + height) as u32;
let x = rectangle.get("x", activation)?.coerce_to_f64(activation)? as i32;
let y = rectangle.get("y", activation)?.coerce_to_f64(activation)? as i32;
let width = rectangle
.get("width", activation)?
.coerce_to_f64(activation)? as i32;
let height = rectangle
.get("height", activation)?
.coerce_to_f64(activation)? as i32;
let color_transform = match ColorTransformObject::cast(*color_transform) {
Some(color_transform) => color_transform.read().clone(),
None => return Ok((-3).into()),
};
let x_min = x.max(0) as u32;
let x_max = (x + width) as u32;
let y_min = y.max(0) as u32;
let y_max = (y + height) as u32;
if let Some(color_transform) = color_transform.as_color_transform_object() {
bitmap_data
.bitmap_data()
.write(activation.context.gc_context)
.color_transform(x_min, y_min, x_max, y_max, color_transform.into());
}
return Ok(Value::Undefined);
}
}

View File

@ -1,15 +1,85 @@
//! flash.geom.ColorTransform object
use crate::avm1::activation::Activation;
use crate::avm1::error::Error;
use crate::avm1::object::color_transform_object::ColorTransformObject;
use crate::avm1::object::NativeObject;
use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{Object, TObject, Value};
use crate::avm1::{Activation, Error, Object, ScriptObject, TObject, Value};
use crate::string::AvmString;
use gc_arena::MutationContext;
use gc_arena::{Collect, GcCell, MutationContext};
use ruffle_render::color_transform::ColorTransform;
use swf::Fixed8;
#[derive(Clone, Debug, Collect)]
#[collect(require_static)]
pub struct ColorTransformObject {
red_multiplier: f64,
green_multiplier: f64,
blue_multiplier: f64,
alpha_multiplier: f64,
red_offset: f64,
green_offset: f64,
blue_offset: f64,
alpha_offset: f64,
}
impl<'gc> ColorTransformObject {
pub const IDENTITY: Self = Self {
red_multiplier: 1.0,
green_multiplier: 1.0,
blue_multiplier: 1.0,
alpha_multiplier: 1.0,
red_offset: 0.0,
green_offset: 0.0,
blue_offset: 0.0,
alpha_offset: 0.0,
};
pub fn construct(
activation: &mut Activation<'_, 'gc, '_>,
color_transform: ColorTransform,
) -> Result<Value<'gc>, Error<'gc>> {
let args = [
color_transform.r_mult.to_f64().into(),
color_transform.g_mult.to_f64().into(),
color_transform.b_mult.to_f64().into(),
color_transform.a_mult.to_f64().into(),
color_transform.r_add.into(),
color_transform.g_add.into(),
color_transform.b_add.into(),
color_transform.a_add.into(),
];
let constructor = activation
.context
.avm1
.prototypes()
.color_transform_constructor;
constructor.construct(activation, &args)
}
pub fn cast(value: Value<'gc>) -> Option<GcCell<'gc, Self>> {
if let Value::Object(object) = value {
if let NativeObject::ColorTransform(color_transform) = object.native() {
return Some(color_transform);
}
}
None
}
}
impl From<ColorTransformObject> for ColorTransform {
fn from(object: ColorTransformObject) -> Self {
Self {
r_mult: Fixed8::from_f64(object.red_multiplier),
g_mult: Fixed8::from_f64(object.green_multiplier),
b_mult: Fixed8::from_f64(object.blue_multiplier),
a_mult: Fixed8::from_f64(object.alpha_multiplier),
r_add: object.red_offset as i16,
g_add: object.green_offset as i16,
b_add: object.blue_offset as i16,
a_add: object.alpha_offset as i16,
}
}
}
const PROTO_DECLS: &[Declaration] = declare_properties! {
"alphaMultiplier" => property(get_alpha_multiplier, set_alpha_multiplier);
"redMultiplier" => property(get_red_multiplier, set_red_multiplier);
@ -29,188 +99,125 @@ pub fn constructor<'gc>(
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let red_multiplier = args.get(0).unwrap_or(&1.into()).coerce_to_f64(activation)?;
let green_multiplier = args.get(1).unwrap_or(&1.into()).coerce_to_f64(activation)?;
let blue_multiplier = args.get(2).unwrap_or(&1.into()).coerce_to_f64(activation)?;
let alpha_multiplier = args.get(3).unwrap_or(&1.into()).coerce_to_f64(activation)?;
let red_offset = args.get(4).unwrap_or(&0.into()).coerce_to_f64(activation)?;
let green_offset = args.get(5).unwrap_or(&0.into()).coerce_to_f64(activation)?;
let blue_offset = args.get(6).unwrap_or(&0.into()).coerce_to_f64(activation)?;
let alpha_offset = args.get(7).unwrap_or(&0.into()).coerce_to_f64(activation)?;
if let Some(ct) = this.as_color_transform_object() {
ct.set_red_multiplier(activation.context.gc_context, red_multiplier);
ct.set_green_multiplier(activation.context.gc_context, green_multiplier);
ct.set_blue_multiplier(activation.context.gc_context, blue_multiplier);
ct.set_alpha_multiplier(activation.context.gc_context, alpha_multiplier);
ct.set_red_offset(activation.context.gc_context, red_offset);
ct.set_green_offset(activation.context.gc_context, green_offset);
ct.set_blue_offset(activation.context.gc_context, blue_offset);
ct.set_alpha_offset(activation.context.gc_context, alpha_offset);
}
let color_transform = match args {
_ if args.len() >= 8 => {
let mut values = [0.0; 8];
for (arg, value) in args.iter().zip(&mut values) {
*value = arg.coerce_to_f64(activation)?;
}
let [red_multiplier, green_multiplier, blue_multiplier, alpha_multiplier, red_offset, green_offset, blue_offset, alpha_offset] =
values;
ColorTransformObject {
red_multiplier,
green_multiplier,
blue_multiplier,
alpha_multiplier,
red_offset,
green_offset,
blue_offset,
alpha_offset,
}
}
[color_transform] => {
if let Some(color_transform) = ColorTransformObject::cast(*color_transform) {
color_transform.read().clone()
} else {
ColorTransformObject::IDENTITY
}
}
_ => ColorTransformObject::IDENTITY,
};
this.set_native(
activation.context.gc_context,
NativeObject::ColorTransform(GcCell::allocate(
activation.context.gc_context,
color_transform,
)),
);
Ok(this.into())
}
pub fn object_to_color_transform<'gc>(
object: Object<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<ColorTransform, Error<'gc>> {
let red_multiplier = object
.get("redMultiplier", activation)?
.coerce_to_f64(activation)?;
let green_multiplier = object
.get("greenMultiplier", activation)?
.coerce_to_f64(activation)?;
let blue_multiplier = object
.get("blueMultiplier", activation)?
.coerce_to_f64(activation)?;
let alpha_multiplier = object
.get("alphaMultiplier", activation)?
.coerce_to_f64(activation)?;
let red_offset = object
.get("redOffset", activation)?
.coerce_to_i16(activation)?;
let green_offset = object
.get("greenOffset", activation)?
.coerce_to_i16(activation)?;
let blue_offset = object
.get("blueOffset", activation)?
.coerce_to_i16(activation)?;
let alpha_offset = object
.get("alphaOffset", activation)?
.coerce_to_i16(activation)?;
Ok(ColorTransform {
r_mult: Fixed8::from_f64(red_multiplier),
g_mult: Fixed8::from_f64(green_multiplier),
b_mult: Fixed8::from_f64(blue_multiplier),
a_mult: Fixed8::from_f64(alpha_multiplier),
r_add: red_offset,
g_add: green_offset,
b_add: blue_offset,
a_add: alpha_offset,
})
}
pub fn color_transform_to_object<'gc>(
color_transform: ColorTransform,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<Value<'gc>, Error<'gc>> {
let args = [
color_transform.r_mult.to_f64().into(),
color_transform.g_mult.to_f64().into(),
color_transform.b_mult.to_f64().into(),
color_transform.a_mult.to_f64().into(),
color_transform.r_add.into(),
color_transform.g_add.into(),
color_transform.b_add.into(),
color_transform.a_add.into(),
];
let constructor = activation
.context
.avm1
.prototypes()
.color_transform_constructor;
let object = constructor.construct(activation, &args)?;
Ok(object)
}
pub fn get_rgb<'gc>(
fn get_rgb<'gc>(
_activation: &mut Activation<'_, 'gc, '_>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(ct) = this.as_color_transform_object() {
let rgb = ((ct.red_offset() as u32) << 16)
| ((ct.green_offset() as u32) << 8)
| (ct.blue_offset() as u32);
if let Some(color_transform) = ColorTransformObject::cast(this.into()) {
let color_transform = color_transform.read();
let rgb = ((color_transform.red_offset as i32) << 16)
| ((color_transform.green_offset as i32) << 8)
| (color_transform.blue_offset as i32);
Ok(rgb.into())
} else {
Ok(Value::Undefined)
}
}
pub fn set_rgb<'gc>(
fn set_rgb<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let new_rgb = args
.get(0)
.unwrap_or(&Value::Undefined)
.coerce_to_u32(activation)?;
let [b, g, r, _] = new_rgb.to_le_bytes();
if let Some(ct) = this.as_color_transform_object() {
ct.set_red_offset(activation.context.gc_context, r.into());
ct.set_green_offset(activation.context.gc_context, g.into());
ct.set_blue_offset(activation.context.gc_context, b.into());
ct.set_red_multiplier(activation.context.gc_context, 0.0);
ct.set_green_multiplier(activation.context.gc_context, 0.0);
ct.set_blue_multiplier(activation.context.gc_context, 0.0);
if let Some(color_transform) = ColorTransformObject::cast(this.into()) {
if let [rgb, ..] = args {
let rgb = rgb.coerce_to_u32(activation)?;
let [b, g, r, _] = rgb.to_le_bytes();
let mut color_transform = color_transform.write(activation.context.gc_context);
color_transform.red_multiplier = 0.0;
color_transform.green_multiplier = 0.0;
color_transform.blue_multiplier = 0.0;
color_transform.red_offset = r.into();
color_transform.green_offset = g.into();
color_transform.blue_offset = b.into();
}
}
Ok(Value::Undefined)
}
macro_rules! color_transform_value_accessor {
($([$get_ident: ident, $ident: ident, $set_ident: ident],)*) => {
($([$field: ident, $getter: ident, $setter: ident],)*) => {
$(
pub fn $set_ident<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let new_val = args
.get(0)
.unwrap_or(&Value::Undefined)
.coerce_to_f64(activation)?;
if let Some(ct) = this.as_color_transform_object() {
ct.$set_ident(activation.context.gc_context, new_val);
}
Ok(Value::Undefined.into())
}
pub fn $get_ident<'gc>(
fn $getter<'gc>(
_activation: &mut Activation<'_, 'gc, '_>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(ct) = this.as_color_transform_object() {
Ok(ct.$ident().into())
if let Some(color_transform) = ColorTransformObject::cast(this.into()) {
Ok(color_transform.read().$field.into())
} else {
Ok(Value::Undefined)
}
}
fn $setter<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(color_transform) = ColorTransformObject::cast(this.into()) {
if let [value, ..] = args {
let value = value.coerce_to_f64(activation)?;
color_transform.write(activation.context.gc_context).$field = value;
}
}
Ok(Value::Undefined.into())
}
)*
}
}
color_transform_value_accessor!(
[get_red_multiplier, red_multiplier, set_red_multiplier],
[get_green_multiplier, green_multiplier, set_green_multiplier],
[get_blue_multiplier, blue_multiplier, set_blue_multiplier],
[get_alpha_multiplier, alpha_multiplier, set_alpha_multiplier],
[get_red_offset, red_offset, set_red_offset],
[get_green_offset, green_offset, set_green_offset],
[get_blue_offset, blue_offset, set_blue_offset],
[get_alpha_offset, alpha_offset, set_alpha_offset],
[red_multiplier, get_red_multiplier, set_red_multiplier],
[green_multiplier, get_green_multiplier, set_green_multiplier],
[blue_multiplier, get_blue_multiplier, set_blue_multiplier],
[alpha_multiplier, get_alpha_multiplier, set_alpha_multiplier],
[red_offset, get_red_offset, set_red_offset],
[green_offset, get_green_offset, set_green_offset],
[blue_offset, get_blue_offset, set_blue_offset],
[alpha_offset, get_alpha_offset, set_alpha_offset],
);
pub fn create_proto<'gc>(
gc_context: MutationContext<'gc, '_>,
proto: Object<'gc>,
fn_proto: Object<'gc>,
) -> Object<'gc> {
let color_transform_object =
ColorTransformObject::empty_color_transform_object(gc_context, Some(proto));
let object = color_transform_object.as_script_object().unwrap();
define_properties_on(PROTO_DECLS, gc_context, object, fn_proto);
color_transform_object.into()
}
fn to_string<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
this: Object<'gc>,
@ -233,43 +240,39 @@ fn to_string<'gc>(
fn concat<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
this: Object<'gc>,
_args: &[Value<'gc>],
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
// Without an arg, does nothing
if let Some(arg) = _args.get(0) {
// If given an invalid var, return undefined
if arg == &Value::Undefined {
return Ok(Value::Undefined);
}
let other = arg.coerce_to_object(activation);
if let (Some(other_ct), Some(this_ct)) = (
other.as_color_transform_object(),
this.as_color_transform_object(),
if let [other, ..] = args {
let (this, other) = match (
ColorTransformObject::cast(this.into()),
ColorTransformObject::cast(*other),
) {
let red_multiplier = other_ct.red_multiplier() * this_ct.red_multiplier();
let green_multiplier = other_ct.green_multiplier() * this_ct.green_multiplier();
let blue_multiplier = other_ct.blue_multiplier() * this_ct.blue_multiplier();
let alpha_multiplier = other_ct.alpha_multiplier() * this_ct.alpha_multiplier();
let red_offset =
(other_ct.red_offset() * this_ct.red_multiplier()) + this_ct.red_offset();
let green_offset =
(other_ct.green_offset() * this_ct.green_multiplier()) + this_ct.green_offset();
let blue_offset =
(other_ct.blue_offset() * this_ct.blue_multiplier()) + this_ct.blue_offset();
let alpha_offset =
(other_ct.alpha_offset() * this_ct.alpha_multiplier()) + this_ct.alpha_offset();
(Some(this), Some(other)) => (this, other.read().clone()),
_ => return Ok(Value::Undefined),
};
this_ct.set_red_multiplier(activation.context.gc_context, red_multiplier);
this_ct.set_green_multiplier(activation.context.gc_context, green_multiplier);
this_ct.set_blue_multiplier(activation.context.gc_context, blue_multiplier);
this_ct.set_alpha_multiplier(activation.context.gc_context, alpha_multiplier);
this_ct.set_red_offset(activation.context.gc_context, red_offset);
this_ct.set_green_offset(activation.context.gc_context, green_offset);
this_ct.set_blue_offset(activation.context.gc_context, blue_offset);
this_ct.set_alpha_offset(activation.context.gc_context, alpha_offset);
}
let mut this = this.write(activation.context.gc_context);
*this = ColorTransformObject {
red_multiplier: other.red_multiplier * this.red_multiplier,
green_multiplier: other.green_multiplier * this.green_multiplier,
blue_multiplier: other.blue_multiplier * this.blue_multiplier,
alpha_multiplier: other.alpha_multiplier * this.alpha_multiplier,
red_offset: (other.red_offset * this.red_multiplier) + this.red_offset,
green_offset: (other.green_offset * this.green_multiplier) + this.green_offset,
blue_offset: (other.blue_offset * this.blue_multiplier) + this.blue_offset,
alpha_offset: (other.alpha_offset * this.alpha_multiplier) + this.alpha_offset,
};
}
Ok(Value::Undefined)
}
pub fn create_proto<'gc>(
gc_context: MutationContext<'gc, '_>,
proto: Object<'gc>,
fn_proto: Object<'gc>,
) -> Object<'gc> {
let object = ScriptObject::new(gc_context, Some(proto));
define_properties_on(PROTO_DECLS, gc_context, object, fn_proto);
object.into()
}

View File

@ -1,11 +1,10 @@
//! flash.geom.Transform
use crate::avm1::activation::Activation;
use crate::avm1::error::Error;
use crate::avm1::globals::{color_transform, matrix};
use crate::avm1::globals::color_transform::ColorTransformObject;
use crate::avm1::globals::matrix::{matrix_to_object, object_to_matrix};
use crate::avm1::object::transform_object::TransformObject;
use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{Object, TObject, Value};
use crate::avm1::{Activation, Error, Object, TObject, Value};
use crate::display_object::{MovieClip, TDisplayObject};
use gc_arena::MutationContext;
@ -85,8 +84,7 @@ fn concatenated_color_transform<'gc>(
color_transform = *display_object.base().color_transform() * color_transform;
node = display_object.parent();
}
let color_transform = color_transform::color_transform_to_object(color_transform, activation)?;
Ok(color_transform)
ColorTransformObject::construct(activation, color_transform)
}
fn concatenated_matrix<'gc>(
@ -95,7 +93,7 @@ fn concatenated_matrix<'gc>(
) -> Result<Value<'gc>, Error<'gc>> {
// Testing shows that 'concatenatedMatrix' does *not* include the 'scrollRect' translation
// for the object itself, but *does* include the 'scrollRect' translation for ancestors.
let matrix = matrix::matrix_to_object(
let matrix = matrix_to_object(
clip.local_to_global_matrix_without_own_scroll_rect(),
activation,
)?;
@ -106,9 +104,7 @@ fn color_transform<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
clip: MovieClip<'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
let color_transform =
color_transform::color_transform_to_object(*clip.base().color_transform(), activation)?;
Ok(color_transform)
ColorTransformObject::construct(activation, *clip.base().color_transform())
}
fn set_color_transform<'gc>(
@ -116,12 +112,12 @@ fn set_color_transform<'gc>(
clip: MovieClip<'gc>,
value: Value<'gc>,
) -> Result<(), Error<'gc>> {
let as_color_transform = value.coerce_to_object(activation);
// Set only occurs for an object with actual ColorTransform data.
if as_color_transform.as_color_transform_object().is_some() {
let swf_color_transform =
color_transform::object_to_color_transform(as_color_transform, activation)?;
clip.set_color_transform(activation.context.gc_context, swf_color_transform);
if let Some(color_transform) = ColorTransformObject::cast(value) {
clip.set_color_transform(
activation.context.gc_context,
color_transform.read().clone().into(),
);
clip.set_transformed_by_script(activation.context.gc_context, true);
}
@ -132,7 +128,7 @@ fn matrix<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
clip: MovieClip<'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
let matrix = matrix::matrix_to_object(*clip.base().matrix(), activation)?;
let matrix = matrix_to_object(*clip.base().matrix(), activation)?;
Ok(matrix)
}
@ -147,7 +143,7 @@ fn set_matrix<'gc>(
.iter()
.all(|p| as_matrix.has_own_property(activation, (*p).into()));
if is_matrix {
let swf_matrix = matrix::object_to_matrix(as_matrix, activation)?;
let swf_matrix = object_to_matrix(as_matrix, activation)?;
clip.set_matrix(activation.context.gc_context, swf_matrix);
clip.set_transformed_by_script(activation.context.gc_context, true);
}

View File

@ -1,14 +1,12 @@
//! Object trait to expose objects to AVM
use crate::avm1::activation::Activation;
use crate::avm1::error::Error;
use crate::avm1::function::{Executable, ExecutionName, ExecutionReason, FunctionObject};
use crate::avm1::globals::color_transform::ColorTransformObject;
use crate::avm1::object::array_object::ArrayObject;
use crate::avm1::object::bevel_filter::BevelFilterObject;
use crate::avm1::object::bitmap_data::BitmapDataObject;
use crate::avm1::object::blur_filter::BlurFilterObject;
use crate::avm1::object::color_matrix_filter::ColorMatrixFilterObject;
use crate::avm1::object::color_transform_object::ColorTransformObject;
use crate::avm1::object::convolution_filter::ConvolutionFilterObject;
use crate::avm1::object::date_object::DateObject;
use crate::avm1::object::displacement_map_filter::DisplacementMapFilterObject;
@ -22,8 +20,7 @@ use crate::avm1::object::transform_object::TransformObject;
use crate::avm1::object::value_object::ValueObject;
use crate::avm1::object::xml_node_object::XmlNodeObject;
use crate::avm1::object::xml_object::XmlObject;
use crate::avm1::property::Attribute;
use crate::avm1::{ScriptObject, SoundObject, StageObject, Value};
use crate::avm1::{Activation, Attribute, Error, ScriptObject, SoundObject, StageObject, Value};
use crate::display_object::DisplayObject;
use crate::html::TextFormat;
use crate::string::AvmString;
@ -37,7 +34,6 @@ pub mod bevel_filter;
pub mod bitmap_data;
pub mod blur_filter;
pub mod color_matrix_filter;
pub mod color_transform_object;
pub mod convolution_filter;
mod custom_object;
pub mod date_object;
@ -60,6 +56,7 @@ pub mod xml_object;
#[collect(no_drop)]
pub enum NativeObject<'gc> {
None,
ColorTransform(GcCell<'gc, ColorTransformObject>),
TextFormat(GcCell<'gc, TextFormat>),
}
@ -80,7 +77,6 @@ pub enum NativeObject<'gc> {
ValueObject(ValueObject<'gc>),
FunctionObject(FunctionObject<'gc>),
SharedObject(SharedObject<'gc>),
ColorTransformObject(ColorTransformObject<'gc>),
TransformObject(TransformObject<'gc>),
BlurFilterObject(BlurFilterObject<'gc>),
BevelFilterObject(BevelFilterObject<'gc>),
@ -562,11 +558,6 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
None
}
/// Get the underlying `ColorTransformObject`, if it exists
fn as_color_transform_object(&self) -> Option<ColorTransformObject<'gc>> {
None
}
/// Get the underlying `TransformObject`, if it exists
fn as_transform_object(&self) -> Option<TransformObject<'gc>> {
None

View File

@ -1,108 +0,0 @@
use crate::add_field_accessors;
use crate::avm1::{Object, ScriptObject, TObject};
use crate::impl_custom_object;
use gc_arena::{Collect, GcCell, MutationContext};
use ruffle_render::color_transform::ColorTransform;
use std::fmt;
use swf::Fixed8;
/// A ColorTransform
#[derive(Clone, Copy, Collect)]
#[collect(no_drop)]
pub struct ColorTransformObject<'gc>(GcCell<'gc, ColorTransformData<'gc>>);
#[derive(Clone, Collect)]
#[collect(no_drop)]
pub struct ColorTransformData<'gc> {
/// The underlying script object.
base: ScriptObject<'gc>,
red_multiplier: f64,
green_multiplier: f64,
blue_multiplier: f64,
alpha_multiplier: f64,
red_offset: f64,
green_offset: f64,
blue_offset: f64,
alpha_offset: f64,
}
impl fmt::Debug for ColorTransformObject<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let this = self.0.read();
f.debug_struct("ColorTransform")
.field("redMultiplier", &this.red_multiplier)
.field("greenMultiplier", &this.green_multiplier)
.field("blueMultiplier", &this.blue_multiplier)
.field("alphaMultiplier", &this.alpha_multiplier)
.field("redOffset", &this.red_offset)
.field("greenOffset", &this.green_offset)
.field("blueOffset", &this.blue_offset)
.field("alphaOffset", &this.alpha_offset)
.finish()
}
}
impl<'gc> ColorTransformObject<'gc> {
pub fn empty_color_transform_object(
gc_context: MutationContext<'gc, '_>,
proto: Option<Object<'gc>>,
) -> Self {
ColorTransformObject(GcCell::allocate(
gc_context,
ColorTransformData {
base: ScriptObject::new(gc_context, proto),
red_multiplier: 0.0,
green_multiplier: 0.0,
blue_multiplier: 0.0,
alpha_multiplier: 0.0,
red_offset: 0.0,
green_offset: 0.0,
blue_offset: 0.0,
alpha_offset: 0.0,
},
))
}
add_field_accessors!(
[set_red_multiplier, red_multiplier, red_multiplier, f64],
[
set_green_multiplier,
green_multiplier,
green_multiplier,
f64
],
[set_blue_multiplier, blue_multiplier, blue_multiplier, f64],
[
set_alpha_multiplier,
alpha_multiplier,
alpha_multiplier,
f64
],
[set_red_offset, red_offset, red_offset, f64],
[set_green_offset, green_offset, green_offset, f64],
[set_blue_offset, blue_offset, blue_offset, f64],
[set_alpha_offset, alpha_offset, alpha_offset, f64],
);
}
impl<'gc> TObject<'gc> for ColorTransformObject<'gc> {
impl_custom_object!(base {
bare_object(as_color_transform_object -> ColorTransformObject::empty_color_transform_object);
});
}
impl From<ColorTransformObject<'_>> for ColorTransform {
fn from(object: ColorTransformObject) -> Self {
Self {
r_mult: Fixed8::from_f64(object.red_multiplier()),
g_mult: Fixed8::from_f64(object.green_multiplier()),
b_mult: Fixed8::from_f64(object.blue_multiplier()),
a_mult: Fixed8::from_f64(object.alpha_multiplier()),
r_add: object.red_offset() as i16,
g_add: object.green_offset() as i16,
b_add: object.blue_offset() as i16,
a_add: object.alpha_offset() as i16,
}
}
}