From de1865997870da672770de0448c2d13d0bb91045 Mon Sep 17 00:00:00 2001 From: Marco Arnulfo Date: Fri, 23 Oct 2026 17:14:51 +0200 Subject: [PATCH] Pictures: Set Transparent Color refuses a spot that is already transparent (#1217) --- crates/engine/src/cmd/recolor.rs | 5 +++++ crates/engine/src/tests.rs | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/crates/engine/src/cmd/recolor.rs b/crates/engine/src/cmd/recolor.rs index 7f2c5afb..a1a83166 100644 --- a/crates/engine/src/cmd/recolor.rs +++ b/crates/engine/src/cmd/recolor.rs @@ -179,6 +179,11 @@ fn picture_pixel_at(s: &Session, p: &Value, at: &Value) -> Result<(ShapeId, Rgba let px = ((u * f64::from(w)) as u32).min(w.saturating_sub(1)); let py = ((v * f64::from(h)) as u32).min(h.saturating_sub(1)); let Some(c) = img.get_pixel_checked(px, py) else { continue }; + // A transparent pixel keeps a colour nobody sees (often black): clearing it would clear + // that colour where it is drawn. + if c[3] == 0 { + return Err(bad(CMD, "that spot of the picture is already transparent")); + } return Ok((id, Rgba::rgb(c[0], c[1], c[2]))); } Err(bad(CMD, "the point is not on a selected picture")) diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 525fdf73..0d043fc5 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -2380,6 +2380,15 @@ fn transparent_color_at_a_point_takes_the_pictures_own_pixel_there() { // Beside the picture there is no colour to take, and nothing changes. assert!(s.execute("picture.transparentColor", &json!({"ids": [id], "at": [50, 50]})).is_err()); assert_eq!(clear(&s), Some(blue)); + // A spot that is already transparent hides a colour (black here, as in most PNGs): taking it + // would clear the black drawn elsewhere in the picture. + let img = image::RgbaImage::from_fn(4, 2, |x, _| if x < 2 { image::Rgba([0, 0, 0, 0]) } else { image::Rgba([0, 0, 0, 255]) }); + let mut png = vec![]; + image::DynamicImage::ImageRgba8(img).write_to(&mut std::io::Cursor::new(&mut png), image::ImageFormat::Png).unwrap(); + let logo = + s.execute("insert.picture", &json!({"data": cmd::base64_encode(&png), "name": "b.png", "rect": [100, 400, 400, 200]})).unwrap()["id"].clone(); + assert!(s.execute("picture.transparentColor", &json!({"ids": [logo], "at": [150, 500]})).is_err()); + s.execute("picture.transparentColor", &json!({"ids": [logo], "at": [450, 500]})).unwrap(); } #[test]