avm1: Implement gradient matrix types

This commit is contained in:
Nathan Adams 2020-05-20 10:53:12 +02:00
parent 5098eb079d
commit 31b0a5ae76
2 changed files with 49 additions and 41 deletions

View File

@ -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<Matrix, Error> {
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>,

View File

@ -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())