mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-29 04:17:11 -06:00
* fix(algo): Path Blur clamps per-path speeds (#708) filter.blurGallery.pathBlur clamps the scalar speed to 0..500, but each entry of the documented paths array was deserialized without any clamp. The halo takes the maximum speed and computes Radius(v.max(0.0).ceil() as i32 + 1): a large finite speed saturates the float-to-int cast to i32::MAX and the + 1 overflows, so the command dies in a caught panic (and wraps to a negative halo with overflow checks off). Clamp each entry speed to the same 0..500 the scalar path uses, right where the params are built. * Path Blur test: drop an unused before-sample (a flat background can't change under blur) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Brandon Fenty <bfenty@users.noreply.github.com> Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
38 lines
1.7 KiB
Rust
38 lines
1.7 KiB
Rust
//! Regression tests for issue #708: `filter.blurGallery.pathBlur` clamps the
|
|
//! scalar `speed`, but each entry of the documented `paths` array is
|
|
//! deserialized without a clamp. A huge finite speed saturates the
|
|
//! float-to-i32 cast in the halo and the `+ 1` overflows, which the dispatch
|
|
//! turns into an internal-error panic. The command must clamp like the scalar
|
|
//! path does and blur normally.
|
|
|
|
use photocraft_engine::Session;
|
|
use serde_json::json;
|
|
|
|
fn path_blur(speed: f64) -> Result<serde_json::Value, photocraft_engine::EngineError> {
|
|
let mut s = Session::new();
|
|
s.execute("file.new", json!({"width": 16, "height": 16, "background": "#808080"})).unwrap();
|
|
s.execute("filter.blurGallery.pathBlur", json!({"paths": [{"points": [[0.2, 0.5], [0.8, 0.5]], "speed": speed}]}))
|
|
}
|
|
|
|
#[test]
|
|
fn path_blur_huge_entry_speed_does_not_panic() {
|
|
// On main this comes back as a caught panic ("internal error" style)
|
|
// from overflow in the halo radius. After the clamp it must succeed.
|
|
let r = path_blur(1.0e20);
|
|
assert!(r.is_ok(), "huge entry speed must clamp, got error: {r:?}");
|
|
}
|
|
|
|
#[test]
|
|
fn path_blur_negative_entry_speed_does_not_panic() {
|
|
let r = path_blur(-1.0e20);
|
|
assert!(r.is_ok(), "huge negative entry speed must clamp, got error: {r:?}");
|
|
}
|
|
|
|
#[test]
|
|
fn path_blur_normal_entry_speed_still_blurs() {
|
|
// Control: a documented in-range speed keeps working.
|
|
let mut s = Session::new();
|
|
s.execute("file.new", json!({"width": 16, "height": 16, "background": "#808080"})).unwrap();
|
|
s.execute("filter.blurGallery.pathBlur", json!({"paths": [{"points": [[0.2, 0.5], [0.8, 0.5]], "speed": 120.0}]})).expect("in-range speed must succeed");
|
|
}
|