Eraser on a locked-transparency layer paints the background colour (#15) (#19)

The Background layer has locked transparency, so the eraser couldn't remove
opacity and appeared to do nothing. Like Photoshop, erasing a locked-
transparency layer now paints the background colour instead. New test.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas 2026-10-04 01:25:23 -04:00 committed by GitHub
parent 09c987f1a8
commit b7cac05f69
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 22 additions and 0 deletions

View File

@ -167,6 +167,12 @@ fn stroke_with(s: &mut Session, p: &Value, label: &str, brush: BrushSettings, pt
let sel = doc.selection.clone();
let (surf, lock) = crate::channel_cmds::target_surface(doc, id, p)?;
let mut brush = brush;
// Erasing a layer with locked transparency (e.g. the Background) can't remove opacity, so
// it paints the background colour instead (Photoshop). `gray` targets are handled above.
if brush.erase && lock {
brush.erase = false;
brush.color = bg;
}
if auto_erase {
// Pencil Auto Erase: starting on foreground-coloured pixels paints the background colour.
let c = surf.rgba(pts[0].x.floor() as i32, pts[0].y.floor() as i32);

View File

@ -226,3 +226,19 @@ fn brush_blend_mode_multiply() {
let n = rgba(&s2, 20, 20);
assert!(n[2] > 0.9 && n[0] < 0.1, "normal paints blue: {n:?}");
}
#[test]
fn eraser_on_background_layer_paints_the_background_colour() {
// Issue #15: erasing the Background layer (locked transparency) must paint the background
// colour, not silently do nothing (opacity can't be removed there).
let mut s = Session::new();
s.execute("file.new", json!({"width": 20, "height": 20, "background": "white"})).unwrap();
s.execute("tools.setColors", json!({"background": "#ff0000"})).unwrap();
s.execute("paint.stroke", json!({"points": [[2, 10], [18, 10]], "size": 8, "erase": true, "brush": {"hardness": 1.0}})).unwrap();
let st = s.active().unwrap();
let c = st.doc.layers[0].surface().unwrap().rgba(10, 10);
assert!(c[0] > 0.9 && c[1] < 0.1 && c[2] < 0.1 && c[3] > 0.99, "erased to opaque background red: {c:?}");
// A corner the stroke didn't touch stays white.
let w = st.doc.layers[0].surface().unwrap().rgba(10, 2);
assert!(w[0] > 0.9 && w[1] > 0.9 && w[2] > 0.9, "untouched stays white: {w:?}");
}