Image Tools: geometry effects keep a color mask

An image with a geometry effect (Transform, for example) is drawn from a
copy of the image, and that copy now keeps the image's color mask. The
canvas and outputs show the masked pixels, and Expand Appearance keeps
the mask on the image it makes.

Test: a_transform_effect_keeps_the_mask.
This commit is contained in:
dotCooCoo
2026-11-12 07:26:48 -08:00
parent 2911958414
commit 63a36fec51
2 changed files with 22 additions and 1 deletions
+5 -1
View File
@@ -548,7 +548,11 @@ fn as_art_opts(
let mut art = match &n.kind {
NodeKind::Image(im) => {
let frame = shapes::rectangle(Rect::new(0.0, 0.0, im.width as f64, im.height as f64)).transformed(im.xf);
let image = Node::new(n.id, n.kind.clone());
let mut image = Node::new(n.id, n.kind.clone());
// The image keeps its color mask, so it shows its masked pixels.
if let Some(m) = &n.extras().color_mask {
image.extras_mut().color_mask = Some(m.clone());
}
let clipped = || {
let mut clip = Node::path(n.id, frame.clone(), Appearance::default());
if let NodeKind::Path { clipping, .. } = &mut clip.kind {
@@ -657,6 +657,23 @@ fn an_envelope_warp_draws_the_masked_pixels() {
assert!(drawn_at(doc(&s), red)[3] > 0, "the red block");
}
/// A geometry effect draws the image's masked pixels, and Expand Appearance keeps the mask on the
/// image it makes.
#[test]
fn a_transform_effect_keeps_the_mask() {
let (mut s, id) = open(&framed());
s.execute(COLOR_MASK, &hide_white()).unwrap();
let moved = |p: vectorcraft_geom::Point| vectorcraft_geom::Point::new(p.x + 30.0, p.y);
let (white, red) = (moved(pixel_at(doc(&s), id, 1, 1)), moved(pixel_at(doc(&s), id, 4, 4)));
s.execute("effect.apply", &json!({"ids": [id.0], "effect": "distort.transform", "params": {"moveH": 30}})).unwrap();
assert_eq!(drawn_at(doc(&s), white)[3], 0, "the hidden white");
assert_eq!(drawn_at(doc(&s), red), RED, "the red block");
s.execute("effect.expandAppearance", &json!({})).unwrap();
let mut masks = vec![];
doc(&s).walk(|n| masks.extend(Document::color_mask_of(n).cloned()));
assert_eq!(masks.len(), 1, "the expanded image keeps its mask");
}
/// A pattern whose tile holds a masked image counts as one with a see-through image, so outputs
/// without transparency expand it before they flatten.
#[test]