mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-25 10:17:02 -06:00
Art in a sublayer is now selected as objects (clicks, marquee, Select All, the Select menu), sublayers select in their own colour, and hidden, locked or template sublayers block clicks. Layer Options gain Preview (per-layer outline) and Dim Images. New and fixed layer.* commands for the Layers panel: setCurrent and highlight (rows at any depth), selectAll, move (reparent with cycle and nesting checks, Alt copies), delete/duplicate rows, merge, flatten, collect, release to layers, reverse, template, hide/outline/lock others and their show/preview/unlock all, locate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
69 lines
2.7 KiB
Rust
69 lines
2.7 KiB
Rust
//! Layer Options on screen: Preview off draws a layer in outline, Dim Images fades its images;
|
||
//! exports (which leave templates out) draw both as they are.
|
||
|
||
use vectorcraft_color::{Color, Paint};
|
||
use vectorcraft_doc::{Appearance, ImageBlob, ImageObject, Node, NodeId, NodeKind};
|
||
use vectorcraft_geom::shapes;
|
||
|
||
use super::*;
|
||
|
||
/// A red square (10..40) and a 30×30 red image at (50, 10), on one layer set up by `layer`.
|
||
fn doc(layer: impl FnOnce(&mut NodeKind)) -> Document {
|
||
let mut d = Document::new(100.0, 100.0);
|
||
let img = image::RgbaImage::from_pixel(30, 30, image::Rgba([255, 0, 0, 255]));
|
||
let mut png = vec![];
|
||
img.write_to(&mut std::io::Cursor::new(&mut png), image::ImageFormat::Png).unwrap();
|
||
d.images.insert("red".into(), ImageBlob::new("image/png", png));
|
||
let l = d.layers[0].id;
|
||
let red = Appearance::basic(Paint::solid(Color::rgb(1.0, 0.0, 0.0)), Paint::None, 0.0);
|
||
let sq = Node::path(d.alloc_id(), shapes::rectangle(Rect::new(10.0, 10.0, 40.0, 40.0)), red);
|
||
d.insert(Some(l), 0, sq).unwrap();
|
||
let mut im = Node::new(
|
||
NodeId(0),
|
||
NodeKind::Image(ImageObject {
|
||
key: "red".into(),
|
||
width: 30,
|
||
height: 30,
|
||
xf: Affine::translate((50.0, 10.0)),
|
||
link: None,
|
||
placement: Default::default(),
|
||
}),
|
||
);
|
||
im.id = d.alloc_id();
|
||
d.insert(Some(l), 9, im).unwrap();
|
||
layer(&mut d.node_mut(l).unwrap().kind);
|
||
d
|
||
}
|
||
|
||
fn render(d: &Document, export: bool) -> Rendered {
|
||
let opts = RenderOptions { background: Some([255, 255, 255, 255]), skip_templates: export, ..Default::default() };
|
||
Renderer::new().render(d, 100, 100, Affine::IDENTITY, &opts)
|
||
}
|
||
|
||
#[test]
|
||
fn preview_off_draws_the_layer_in_outline_on_screen_only() {
|
||
let d = doc(|k| {
|
||
if let NodeKind::Layer { preview, .. } = k {
|
||
*preview = false;
|
||
}
|
||
});
|
||
assert_eq!(render(&d, false).pixel(25, 25), [255, 255, 255, 255], "no fill in outline");
|
||
assert_eq!(render(&d, true).pixel(25, 25), [255, 0, 0, 255], "exports draw it as it is");
|
||
}
|
||
|
||
#[test]
|
||
fn dim_images_fades_only_the_images() {
|
||
let plain = render(&doc(|_| {}), false);
|
||
assert_eq!(plain.pixel(65, 25), [255, 0, 0, 255]);
|
||
let d = doc(|k| {
|
||
if let NodeKind::Layer { dim_images, .. } = k {
|
||
*dim_images = Some(50);
|
||
}
|
||
});
|
||
let img = render(&d, false);
|
||
let [r, g, b, _] = img.pixel(65, 25);
|
||
assert!(r == 255 && (120..=135).contains(&g) && g == b, "half way to white: {:?}", img.pixel(65, 25));
|
||
assert_eq!(img.pixel(25, 25), [255, 0, 0, 255], "vector art stays");
|
||
assert_eq!(render(&d, true).pixel(65, 25), [255, 0, 0, 255], "exports are not dimmed");
|
||
}
|