avm1: Migrate `ColorTransform` to `NativeObject`
This commit is contained in:
parent
ceb877c55f
commit
898ccfba5d
|
@ -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;
|
||||
|
|
|
@ -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,16 +585,9 @@ 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);
|
||||
|
||||
let color_transform = args
|
||||
.get(1)
|
||||
.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
|
||||
|
@ -610,14 +602,16 @@ pub fn color_transform<'gc>(
|
|||
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() {
|
||||
let color_transform = match ColorTransformObject::cast(*color_transform) {
|
||||
Some(color_transform) => color_transform.read().clone(),
|
||||
None => return Ok((-3).into()),
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue