From 31b0a5ae76c8bc6aba3288246bb32fd8df41639c Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Wed, 20 May 2020 10:53:12 +0200 Subject: [PATCH] avm1: Implement gradient matrix types --- core/src/avm1/globals/matrix.rs | 46 +++++++++++++++++++++++++++++ core/src/avm1/globals/movie_clip.rs | 44 ++------------------------- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/core/src/avm1/globals/matrix.rs b/core/src/avm1/globals/matrix.rs index ebdc4ce89..ac679ab1f 100644 --- a/core/src/avm1/globals/matrix.rs +++ b/core/src/avm1/globals/matrix.rs @@ -16,6 +16,50 @@ pub fn value_to_matrix<'gc>( object_to_matrix(value.as_object()?, avm, context) } +pub fn gradient_object_to_matrix<'gc>( + object: Object<'gc>, + avm: &mut Avm1<'gc>, + context: &mut UpdateContext<'_, 'gc, '_>, +) -> Result { + if object + .get("matrixType", avm, context)? + .resolve(avm, context)? + .coerce_to_string(avm, context)? + == "box" + { + let width = object + .get("w", avm, context)? + .resolve(avm, context)? + .as_number(avm, context)?; + let height = object + .get("h", avm, context)? + .resolve(avm, context)? + .as_number(avm, context)?; + let rotation = object + .get("r", avm, context)? + .resolve(avm, context)? + .as_number(avm, context)?; + let tx = object + .get("x", avm, context)? + .resolve(avm, context)? + .as_number(avm, context)?; + let ty = object + .get("y", avm, context)? + .resolve(avm, context)? + .as_number(avm, context)?; + Ok(Matrix::create_gradient_box( + width as f32, + height as f32, + rotation as f32, + Twips::from_pixels(tx), + Twips::from_pixels(ty), + )) + } else { + // TODO: You can apparently pass a 3x3 matrix here. Did anybody actually? How does it work? + object_to_matrix(object, avm, context) + } +} + pub fn object_to_matrix<'gc>( object: Object<'gc>, avm: &mut Avm1<'gc>, @@ -53,6 +97,8 @@ pub fn object_to_matrix<'gc>( Ok(Matrix { a, b, c, d, tx, ty }) } +// We'll need this soon! +#[allow(dead_code)] pub fn matrix_to_object<'gc>( matrix: Matrix, avm: &mut Avm1<'gc>, diff --git a/core/src/avm1/globals/movie_clip.rs b/core/src/avm1/globals/movie_clip.rs index d3cb8175e..8a9388985 100644 --- a/core/src/avm1/globals/movie_clip.rs +++ b/core/src/avm1/globals/movie_clip.rs @@ -1,6 +1,7 @@ //! MovieClip prototype use crate::avm1::globals::display_object::{self, AVM_DEPTH_BIAS, AVM_MAX_DEPTH}; +use crate::avm1::globals::matrix::gradient_object_to_matrix; use crate::avm1::property::Attribute::*; use crate::avm1::return_value::ReturnValue; use crate::avm1::{Avm1, Error, Object, ScriptObject, TObject, UpdateContext, Value}; @@ -12,7 +13,7 @@ use crate::tag_utils::SwfSlice; use gc_arena::MutationContext; use swf::{ FillStyle, Gradient, GradientInterpolation, GradientRecord, GradientSpread, LineCapStyle, - LineJoinStyle, LineStyle, Matrix, Twips, + LineJoinStyle, LineStyle, Twips, }; /// Implements `MovieClip` @@ -279,46 +280,7 @@ fn begin_gradient_fill<'gc>( color: Color::from_rgb(rgb, (alpha / 100.0 * 255.0) as u8), }); } - let matrix = if matrix_object - .get("matrixType", avm, context)? - .resolve(avm, context)? - .coerce_to_string(avm, context)? - == "box" - { - let width = matrix_object - .get("w", avm, context)? - .resolve(avm, context)? - .as_number(avm, context)?; - let height = matrix_object - .get("h", avm, context)? - .resolve(avm, context)? - .as_number(avm, context)?; - let tx = matrix_object - .get("x", avm, context)? - .resolve(avm, context)? - .as_number(avm, context)? - + width / 2.0; - let ty = matrix_object - .get("y", avm, context)? - .resolve(avm, context)? - .as_number(avm, context)? - + height / 2.0; - // TODO: This is wrong, doesn't account for rotations. - Matrix { - tx: Twips::from_pixels(tx), - ty: Twips::from_pixels(ty), - a: width as f32 / 1638.4, - d: height as f32 / 1638.4, - b: 0.0, - c: 0.0, - } - } else { - log::warn!( - "beginGradientFill() received unsupported matrix object {:?}", - matrix_object - ); - return Ok(Value::Undefined.into()); - }; + let matrix = gradient_object_to_matrix(matrix_object, avm, context)?; let spread = match args .get(5) .and_then(|v| v.clone().coerce_to_string(avm, context).ok())