diff --git a/swf/src/read.rs b/swf/src/read.rs index eabc89f4b..589685d93 100644 --- a/swf/src/read.rs +++ b/swf/src/read.rs @@ -2122,23 +2122,14 @@ impl<'a> Reader<'a> { ratio: self.read_u8()?, }); } - let blur_x = self.read_fixed16()?; - let blur_y = self.read_fixed16()?; - let angle = self.read_fixed16()?; - let distance = self.read_fixed16()?; - let strength = self.read_fixed8()?; - let flags = self.read_u8()?; Ok(GradientFilter { colors: gradient_records, - blur_x, - blur_y, - angle, - distance, - strength, - is_inner: flags & 0b1000_0000 != 0, - is_knockout: flags & 0b0100_0000 != 0, - is_on_top: flags & 0b0001_0000 != 0, - num_passes: flags & 0b0000_1111, + blur_x: self.read_fixed16()?, + blur_y: self.read_fixed16()?, + angle: self.read_fixed16()?, + distance: self.read_fixed16()?, + strength: self.read_fixed8()?, + flags: GradientFilterFlags::from_bits_truncate(self.read_u8()?), }) } diff --git a/swf/src/test_data.rs b/swf/src/test_data.rs index 543e5b89e..3164ad5ce 100644 --- a/swf/src/test_data.rs +++ b/swf/src/test_data.rs @@ -2133,10 +2133,10 @@ pub fn tag_tests() -> Vec { angle: Fixed16::from_f64(0.7853851318359375), distance: Fixed16::from_f32(5.0), strength: Fixed8::ONE, - is_inner: true, - is_knockout: true, - is_on_top: false, - num_passes: 3, + flags: GradientFilterFlags::INNER_SHADOW + | GradientFilterFlags::KNOCKOUT + | GradientFilterFlags::COMPOSITE_SOURCE + | GradientFilterFlags::from_passes(3), })), Filter::GradientGlowFilter(Box::new(GradientFilter { colors: vec![ @@ -2164,10 +2164,9 @@ pub fn tag_tests() -> Vec { angle: Fixed16::from_f64(0.174530029296875), distance: Fixed16::from_f32(5.0), strength: Fixed8::from_f64(0.19921875), - is_inner: false, - is_knockout: false, - is_on_top: true, - num_passes: 1, + flags: GradientFilterFlags::COMPOSITE_SOURCE + | GradientFilterFlags::ON_TOP + | GradientFilterFlags::from_passes(1), })), Filter::BlurFilter(Box::new(BlurFilter { blur_x: Fixed16::from_f32(30.0), diff --git a/swf/src/types.rs b/swf/src/types.rs index bd17f5138..b0a8177bb 100644 --- a/swf/src/types.rs +++ b/swf/src/types.rs @@ -32,7 +32,7 @@ pub use convolution_filter::ConvolutionFilter; pub use drop_shadow_filter::{DropShadowFilter, DropShadowFilterFlags}; pub use fixed::{Fixed16, Fixed8}; pub use glow_filter::{GlowFilter, GlowFilterFlags}; -pub use gradient_filter::GradientFilter; +pub use gradient_filter::{GradientFilter, GradientFilterFlags}; pub use matrix::Matrix; pub use point::Point; pub use rectangle::Rectangle; diff --git a/swf/src/types/gradient_filter.rs b/swf/src/types/gradient_filter.rs index e4972f443..d3134d417 100644 --- a/swf/src/types/gradient_filter.rs +++ b/swf/src/types/gradient_filter.rs @@ -1,4 +1,5 @@ use crate::{Fixed16, Fixed8, GradientRecord}; +use bitflags::bitflags; #[derive(Clone, Debug, Eq, PartialEq)] pub struct GradientFilter { @@ -8,8 +9,46 @@ pub struct GradientFilter { pub angle: Fixed16, pub distance: Fixed16, pub strength: Fixed8, - pub is_inner: bool, - pub is_knockout: bool, - pub is_on_top: bool, - pub num_passes: u8, + pub flags: GradientFilterFlags, +} + +impl GradientFilter { + #[inline] + pub fn is_inner(&self) -> bool { + self.flags.contains(GradientFilterFlags::INNER_SHADOW) + } + + #[inline] + pub fn is_knockout(&self) -> bool { + self.flags.contains(GradientFilterFlags::KNOCKOUT) + } + + #[inline] + pub fn is_on_top(&self) -> bool { + self.flags.contains(GradientFilterFlags::ON_TOP) + } + + #[inline] + pub fn num_passes(&self) -> u8 { + (self.flags & GradientFilterFlags::PASSES).bits() + } +} + +bitflags! { + pub struct GradientFilterFlags: u8 { + const INNER_SHADOW = 1 << 7; + const KNOCKOUT = 1 << 6; + const COMPOSITE_SOURCE = 1 << 5; + const ON_TOP = 1 << 4; + const PASSES = 0b1111; + } +} + +impl GradientFilterFlags { + #[inline] + pub fn from_passes(num_passes: u8) -> Self { + let flags = Self::from_bits_truncate(num_passes); + debug_assert_eq!(flags & Self::PASSES, flags); + flags + } } diff --git a/swf/src/write.rs b/swf/src/write.rs index e2abe8d0a..454d4b50c 100644 --- a/swf/src/write.rs +++ b/swf/src/write.rs @@ -1817,12 +1817,7 @@ impl Writer { self.write_fixed16(filter.angle)?; self.write_fixed16(filter.distance)?; self.write_fixed8(filter.strength)?; - let mut bits = self.bits(); - bits.write_bit(filter.is_inner)?; - bits.write_bit(filter.is_knockout)?; - bits.write_bit(true)?; - bits.write_bit(filter.is_on_top)?; - bits.write_ubits(4, filter.num_passes.into())?; + self.write_u8(filter.flags.bits())?; Ok(()) }