From 17bacb9a63a4f2bc4d31c2a73d81fbfaf56a1990 Mon Sep 17 00:00:00 2001 From: Joseph Anglada Date: Fri, 23 Oct 2026 10:31:56 -0400 Subject: [PATCH] picture.corrections: a tiny sharpen value no longer panics in the blur (#3646) (#3830) Co-authored-by: Claude Sonnet 5.5 --- crates/engine/src/cmd/objects.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/cmd/objects.rs b/crates/engine/src/cmd/objects.rs index febd55660..66498178c 100644 --- a/crates/engine/src/cmd/objects.rs +++ b/crates/engine/src/cmd/objects.rs @@ -130,7 +130,8 @@ pub fn specs() -> Vec { } if sharpen > 0.0 { img = img.unsharpen(1.0 + sharpen / 50.0, 2); - } else if sharpen < 0.0 { + } else if sharpen < 0.0 && (-sharpen / 25.0).is_normal() { + // `blur` asserts on a subnormal width. img = img.blur(-sharpen / 25.0); } img @@ -2010,6 +2011,17 @@ mod tests { assert!(s.run("picture.crop", &json!({"left": 0.1})).is_err()); } + /// A `sharpen` too small to be a normal blur width must not reach the blur, which asserts on it. + #[test] + fn a_tiny_sharpen_value_does_not_panic() { + let mut s = Session::new(wordcraft_doc::Document::new()); + let data = super::super::insert::base64_encode(&png(20, 10)); + s.run("insert.picture", &json!({"data": data})).unwrap(); + for sharpen in [-1e-40_f64, -1e-45, -1e-38, 1e-40, -1e-30, 0.0, -0.5] { + s.run("picture.corrections", &json!({"sharpen": sharpen})).unwrap_or_else(|e| panic!("sharpen {sharpen}: {e:?}")); + } + } + /// Transparency is absolute from the original pixels: 80% then 0% is opaque again /// (it used to stay faded), and repeating a value is idempotent. Corrections and color /// re-set the same way: brightness 0 and saturation 100 restore the original.