From 88a9c74ee0df8ebb86f156e5ff6ddbcf08141851 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Mon, 10 Jun 2024 16:39:25 +0200 Subject: [PATCH] swf: Fix blur scaling in filters The blur of 1.0 is invariant, so that it should be preserved when scaling. Using `blur * scale` also scales the invariant, which is wrong. Tests show that `(blur - 1) * scale + 1` matches FP's behavior. --- swf/src/types/bevel_filter.rs | 4 ++-- swf/src/types/blur_filter.rs | 9 +++++++-- swf/src/types/drop_shadow_filter.rs | 4 ++-- swf/src/types/glow_filter.rs | 4 ++-- swf/src/types/gradient_filter.rs | 4 ++-- .../output.expected.png | Bin 11563 -> 4822 bytes 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/swf/src/types/bevel_filter.rs b/swf/src/types/bevel_filter.rs index 2a2a6bf66..7bdc8e506 100644 --- a/swf/src/types/bevel_filter.rs +++ b/swf/src/types/bevel_filter.rs @@ -35,8 +35,8 @@ impl BevelFilter { } pub fn scale(&mut self, x: f32, y: f32) { - self.blur_x *= Fixed16::from_f32(x); - self.blur_y *= Fixed16::from_f32(y); + self.blur_x = BlurFilter::scale_blur(self.blur_x, x); + self.blur_y = BlurFilter::scale_blur(self.blur_y, y); self.distance *= Fixed16::from_f32(y); } diff --git a/swf/src/types/blur_filter.rs b/swf/src/types/blur_filter.rs index 223a5c90e..cbadaa40f 100644 --- a/swf/src/types/blur_filter.rs +++ b/swf/src/types/blur_filter.rs @@ -23,8 +23,8 @@ impl BlurFilter { } pub fn scale(&mut self, x: f32, y: f32) { - self.blur_x *= Fixed16::from_f32(x); - self.blur_y *= Fixed16::from_f32(y); + self.blur_x = Self::scale_blur(self.blur_x, x); + self.blur_y = Self::scale_blur(self.blur_y, y); } pub fn impotent(&self) -> bool { @@ -42,6 +42,11 @@ impl BlurFilter { y_max: source_rect.y_max + y, } } + + #[inline] + pub(crate) fn scale_blur(blur: Fixed16, factor: f32) -> Fixed16 { + (blur - Fixed16::ONE) * Fixed16::from_f32(factor) + Fixed16::ONE + } } bitflags! { diff --git a/swf/src/types/drop_shadow_filter.rs b/swf/src/types/drop_shadow_filter.rs index 8181ae0c8..304359cee 100644 --- a/swf/src/types/drop_shadow_filter.rs +++ b/swf/src/types/drop_shadow_filter.rs @@ -37,8 +37,8 @@ impl DropShadowFilter { } pub fn scale(&mut self, x: f32, y: f32) { - self.blur_x *= Fixed16::from_f32(x); - self.blur_y *= Fixed16::from_f32(y); + self.blur_x = BlurFilter::scale_blur(self.blur_x, x); + self.blur_y = BlurFilter::scale_blur(self.blur_y, y); self.distance *= Fixed16::from_f32(y); } diff --git a/swf/src/types/glow_filter.rs b/swf/src/types/glow_filter.rs index 9bb9fed5b..d64913d8a 100644 --- a/swf/src/types/glow_filter.rs +++ b/swf/src/types/glow_filter.rs @@ -32,8 +32,8 @@ impl GlowFilter { } pub fn scale(&mut self, x: f32, y: f32) { - self.blur_x *= Fixed16::from_f32(x); - self.blur_y *= Fixed16::from_f32(y); + self.blur_x = BlurFilter::scale_blur(self.blur_x, x); + self.blur_y = BlurFilter::scale_blur(self.blur_y, y); } pub fn calculate_dest_rect(&self, source_rect: Rectangle) -> Rectangle { diff --git a/swf/src/types/gradient_filter.rs b/swf/src/types/gradient_filter.rs index cc3119efa..766da60d9 100644 --- a/swf/src/types/gradient_filter.rs +++ b/swf/src/types/gradient_filter.rs @@ -34,8 +34,8 @@ impl GradientFilter { } pub fn scale(&mut self, x: f32, y: f32) { - self.blur_x *= Fixed16::from_f32(x); - self.blur_y *= Fixed16::from_f32(y); + self.blur_x = BlurFilter::scale_blur(self.blur_x, x); + self.blur_y = BlurFilter::scale_blur(self.blur_y, y); self.distance *= Fixed16::from_f32(y); } diff --git a/tests/tests/swfs/visual/filters/blur_scales_with_screen/output.expected.png b/tests/tests/swfs/visual/filters/blur_scales_with_screen/output.expected.png index 586e9af6a4f8306fd70900b43304abac10505ddf..ff566e04c9b8a491087d095497c67273f73eb1d7 100644 GIT binary patch literal 4822 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 S*+KhNDlQJ^>{*|Eb?u*u8;B(U literal 11563 zcmeHNX;_q3maZyFq$(hxK$=YlS*k^7gD3^^#0XNd35lW>OEeaWs8BJW(n-uBn+s8B z2%sPn#RW8IX`z@$%#$c+2rdLSph$NfqmG1;o}?#{@re^t^PYRZV$+#_Gk*pPzpcKy z_uO;dbM8Ioy@d;3jkJ-w$VDQNO>~qxUL+Ei(0?mSJjpq)x+W6&{T!_hTk?+h-@X@@ zctwBg6|LA=U-fyUTAh}brdf)AZ_~fW*Zw#DZK9?V5~!E7w1^0G!ROUg@{ZWFgtxQb ze*3i!>N0lanKw_Idsu%AhZWneEKOLR-MKX3Y5$@o{;Yn>oN4^o@`00)57>M4$9^9; zx{Th#%jYLo&~Nd@lkP(s__L*^%}WLw{mWRRV>%rTDbpR}%RAdo8($t@y{6$^$7-Nw zOW3_6uYL3H&5n9`=cUt8%LcZ%RG4gahNf$lt~x{W$ba@?=M}Ix&}%Cm zRuJ1((B*EAyX1UavOlS-4nQ}JlXbRjhk!wtD?2hm2O^c8IwqkX@ zP1SXmMoWE|k`5W8ud5)bhzYh%5e2ErCAFbG3+3e!J36rI)OqwYGs&k!W(O5nR+x6` z3?xyPc5hAKTAMmqoh&(jT^_rwRMG={R}%;YawSV-F}d+I4o4@(Ld^jP~?`(2*9Jo$0>6+MZyC(DVn8#|YpjzqiXN}+;HlWxnGkLRB=^SZ;j!<4D8 zq$mnsE7UocmYVt({d&ID(iPUCfw$VV+HDh?k90M32c@`|T@^(4nmUd||LH(~4gIGh zGxxuc;CWUh?s>pd&CgpFDIpY>+uGv!ACkP$Qe|XaOuiOJelI8{bJjI%Qi8)aZA|?6q@as2gJqK z^lMf5UvBTQX4ZDMhu6fC+!Bu(2iTGDHvs&t3Mbq(&%!6TCAh`^!e*QPz~dUj8y7d* z9GiH&8yD&0`U9;ko}+!=O_QuGuKnO2=O0I~tqt%≤btaHR)L4>1>+x{X>I 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