From 080f2c4c8d82f9d8ac0c934fc63e747841bd3e45 Mon Sep 17 00:00:00 2001 From: bfenty Date: Wed, 7 Oct 2026 16:45:59 -0500 Subject: [PATCH] fix(algo): gallery colour injection covers Colored Pencil and Neon Glow (#709) (#805) uses_colours() derived from the params notation, but Colored Pencil (paper tint from the background) and Neon Glow (foreground mixed over background) read the colours in their pixel code without listing them. The single-filter commands therefore skipped colour injection and both filters always ran with the default white/black regardless of the session colours, while filter.filterGallery honoured them. Add the two filters to uses_colours() at the source, so the command injection, the gallery dialog note, and smart-filter re-renders all agree. Adds regression tests: filter.gallery.coloredPencil and filter.gallery.neonGlow output must change with the session background (both identical on main). Co-authored-by: Brandon Fenty --- crates/algo/src/artistic.rs | 7 ++++-- crates/engine/tests/gallery_colours.rs | 33 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 crates/engine/tests/gallery_colours.rs diff --git a/crates/algo/src/artistic.rs b/crates/algo/src/artistic.rs index 5aab3564..42660914 100644 --- a/crates/algo/src/artistic.rs +++ b/crates/algo/src/artistic.rs @@ -147,9 +147,12 @@ impl GalleryFilter { out } - /// Whether the filter reads the foreground / background colours. + /// Whether the filter reads the foreground / background colours. Derived + /// from the params notation, plus the filters whose pixel code reads the + /// colours without listing them (issue #709): Colored Pencil uses the + /// background as paper tint, Neon Glow mixes foreground over background. pub fn uses_colours(self) -> bool { - self.params_doc().contains("\"foreground\"") || self.params_doc().contains("\"background\"") + matches!(self, Self::ColoredPencil | Self::NeonGlow) || self.params_doc().contains("\"foreground\"") || self.params_doc().contains("\"background\"") } } diff --git a/crates/engine/tests/gallery_colours.rs b/crates/engine/tests/gallery_colours.rs new file mode 100644 index 00000000..d1561e8a --- /dev/null +++ b/crates/engine/tests/gallery_colours.rs @@ -0,0 +1,33 @@ +//! Regression tests for issue #709: the single-filter gallery commands must +//! record the session foreground/background colours for every filter that +//! reads them. Colored Pencil (background) and Neon Glow (both) read the +//! colours in their pixel code but omit them from their params notation, so +//! the injection was skipped and they always ran with the defaults. +use photocraft_engine::Session; +use serde_json::json; + +fn px(s: &mut Session, x: i32, y: i32) -> Vec { + serde_json::from_value(s.execute("document.pixel", json!({"x": x, "y": y})).unwrap()).unwrap() +} + +fn image(s: &mut Session) -> Vec { + (0..16).flat_map(|y| (0..16).map(move |x| (x, y))).flat_map(|(x, y)| px(s, x, y)).collect() +} + +fn one(filter: &str, bg: &str) -> Vec { + let mut s = Session::new(); + s.execute("file.new", json!({"width": 16, "height": 16, "background": "#808080"})).unwrap(); + s.execute("tools.setColors", json!({"background": bg})).unwrap(); + s.execute(&format!("filter.gallery.{filter}"), json!({})).unwrap(); + image(&mut s) +} + +#[test] +fn colored_pencil_honours_session_background() { + assert_ne!(one("coloredPencil", "#ffffff"), one("coloredPencil", "#0000ff"), "filter.gallery.coloredPencil must honour the session background"); +} + +#[test] +fn neon_glow_honours_session_background() { + assert_ne!(one("neonGlow", "#ffffff"), one("neonGlow", "#0000ff"), "filter.gallery.neonGlow must honour the session background"); +}