From c9656c429e4d44d06f3eec667d02daa0636cc46e Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Thu, 23 Feb 2023 03:06:30 +0100 Subject: [PATCH] render: Add Filter::DropShadowFilter --- core/src/avm2/filters.rs | 83 +++++++++++++++++++++++++++++++++++++++- render/src/filters.rs | 52 +++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/core/src/avm2/filters.rs b/core/src/avm2/filters.rs index 9c43bf171..adfb11a25 100644 --- a/core/src/avm2/filters.rs +++ b/core/src/avm2/filters.rs @@ -1,6 +1,6 @@ use ruffle_render::filters::{ BevelFilter, BevelFilterType, BlurFilter, ColorMatrixFilter, ConvolutionFilter, - DisplacementMapFilter, DisplacementMapFilterMode, Filter, + DisplacementMapFilter, DisplacementMapFilterMode, DropShadowFilter, Filter, }; use swf::Color; @@ -49,6 +49,11 @@ impl FilterAvm2Ext for Filter { return DisplacementMapFilter::from_avm2_object(activation, object); } + let drop_shadow_filter = activation.avm2().classes().dropshadowfilter; + if object.is_of_type(drop_shadow_filter, activation) { + return DropShadowFilter::from_avm2_object(activation, object); + } + Err(Error::AvmError(type_error( activation, &format!( @@ -68,6 +73,7 @@ impl FilterAvm2Ext for Filter { Filter::ColorMatrixFilter(filter) => filter.as_avm2_object(activation), Filter::ConvolutionFilter(filter) => filter.as_avm2_object(activation), Filter::DisplacementMapFilter(filter) => filter.as_avm2_object(activation), + Filter::DropShadowFilter(filter) => filter.as_avm2_object(activation), } } } @@ -428,3 +434,78 @@ impl FilterAvm2Ext for DisplacementMapFilter { ) } } + +impl FilterAvm2Ext for DropShadowFilter { + fn from_avm2_object<'gc>( + activation: &mut Activation<'_, 'gc>, + object: Object<'gc>, + ) -> Result> { + let alpha = object + .get_public_property("alpha", activation)? + .coerce_to_number(activation)?; + let angle = object + .get_public_property("angle", activation)? + .coerce_to_number(activation)?; + let blur_x = object + .get_public_property("blurX", activation)? + .coerce_to_number(activation)?; + let blur_y = object + .get_public_property("blurY", activation)? + .coerce_to_number(activation)?; + let color = object + .get_public_property("color", activation)? + .coerce_to_u32(activation)?; + let distance = object + .get_public_property("distance", activation)? + .coerce_to_number(activation)?; + let hide_object = object + .get_public_property("hideObject", activation)? + .coerce_to_boolean(); + let inner = object + .get_public_property("inner", activation)? + .coerce_to_boolean(); + let knockout = object + .get_public_property("knockout", activation)? + .coerce_to_boolean(); + let quality = object + .get_public_property("quality", activation)? + .coerce_to_u32(activation)?; + let strength = object + .get_public_property("strength", activation)? + .coerce_to_u32(activation)?; + Ok(Filter::DropShadowFilter(DropShadowFilter { + color: Color::from_rgb(color, (alpha * 255.0) as u8), + angle: angle as f32, + blur_x: blur_x as f32, + blur_y: blur_y as f32, + distance: distance as f32, + hide_object, + inner, + knockout, + strength: strength.clamp(0, 255) as u8, + quality: quality.clamp(1, 15) as u8, + })) + } + + fn as_avm2_object<'gc>( + &self, + activation: &mut Activation<'_, 'gc>, + ) -> Result, Error<'gc>> { + activation.avm2().classes().dropshadowfilter.construct( + activation, + &[ + self.distance.into(), + self.angle.into(), + self.color.to_rgb().into(), + (f64::from(self.color.a) / 255.0).into(), + self.blur_x.into(), + self.blur_y.into(), + self.strength.into(), + self.quality.into(), + self.inner.into(), + self.knockout.into(), + self.hide_object.into(), + ], + ) + } +} diff --git a/render/src/filters.rs b/render/src/filters.rs index 590155054..396dc0f5a 100644 --- a/render/src/filters.rs +++ b/render/src/filters.rs @@ -8,6 +8,7 @@ pub enum Filter { ColorMatrixFilter(ColorMatrixFilter), ConvolutionFilter(ConvolutionFilter), DisplacementMapFilter(DisplacementMapFilter), + DropShadowFilter(DropShadowFilter), } impl Default for Filter { @@ -219,3 +220,54 @@ impl Default for DisplacementMapFilter { } } } + +#[derive(Debug, Clone)] +pub struct DropShadowFilter { + pub color: Color, + pub angle: f32, + pub blur_x: f32, + pub blur_y: f32, + pub distance: f32, + pub hide_object: bool, + pub inner: bool, + pub knockout: bool, + pub quality: u8, + pub strength: u8, +} + +impl From for DropShadowFilter { + fn from(value: swf::DropShadowFilter) -> Self { + let inner = value.is_inner(); + let knockout = value.is_knockout(); + let quality = value.num_passes(); + DropShadowFilter { + color: value.color, + angle: value.angle.to_f32(), + blur_x: value.blur_x.to_f32(), + blur_y: value.blur_y.to_f32(), + distance: value.distance.to_f32(), + hide_object: false, + inner, + knockout, + quality, + strength: (value.strength.to_f32() * 255.0) as u8, + } + } +} + +impl Default for DropShadowFilter { + fn default() -> Self { + Self { + color: Color::from_rgba(0), + angle: 45.0, + blur_x: 4.0, + blur_y: 4.0, + distance: 4.0, + hide_object: false, + inner: false, + knockout: false, + quality: 1, + strength: 1, + } + } +}