mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-25 02:07:09 -06:00
Rarely set fields move into one optional boxed NodeExtras, and large NodeKind payloads (images, live shapes, blends, envelopes) are boxed. Every object, and every undo step that copies it, shrinks: a 50k-path move keeps ~24.5 MB per step instead of ~40 MB. Files stay byte-identical (Node keeps its flat JSON through a borrowed Serialize and a from-wire Deserialize, no flatten), and loading is slightly faster. Undo and redo reuse their step's size estimate instead of walking the document again (8.3 -> 5.6 ms for a 50k-path move). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VmMmc1J8XeNLxhRihWv9cc # Conflicts: # crates/engine/src/cmd/graph.rs # crates/svg/src/export.rs
32 lines
1.5 KiB
Rust
32 lines
1.5 KiB
Rust
//! Document Setup options the renderer honours.
|
||
|
||
use vectorcraft_doc::{Document, ImageBlob, ImageObject, Node, NodeKind};
|
||
|
||
use super::*;
|
||
|
||
fn doc_with_red_image() -> Document {
|
||
let mut d = Document::new(40.0, 40.0);
|
||
let mut png = Vec::new();
|
||
image::RgbaImage::from_pixel(4, 4, image::Rgba([255, 0, 0, 255])).write_to(&mut std::io::Cursor::new(&mut png), image::ImageFormat::Png).unwrap();
|
||
d.images.insert("red".into(), ImageBlob::new("image/png", png));
|
||
let (id, layer) = (d.alloc_id(), d.layers[0].id);
|
||
let im = ImageObject { key: "red".into(), width: 40, height: 40, xf: Affine::IDENTITY, link: None, placement: Default::default() };
|
||
d.insert(Some(layer), 0, Node::new(id, NodeKind::Image(Box::new(im)))).unwrap();
|
||
d
|
||
}
|
||
|
||
#[test]
|
||
fn outline_mode_draws_images_in_grey_only_when_the_setup_asks() {
|
||
let mut d = doc_with_red_image();
|
||
let outline = RenderOptions { outline: true, ..Default::default() };
|
||
let centre = |d: &Document| Renderer::new().render(d, 40, 40, Affine::IDENTITY, &outline).pixel(20, 20);
|
||
assert_eq!(centre(&d)[3], 0, "outline mode draws only the image frame");
|
||
d.setup.outline_images = true;
|
||
let [r, g, b, a] = centre(&d);
|
||
// Red's luma (0.2126 × 255 ≈ 54) in every channel.
|
||
assert_eq!(a, 255);
|
||
assert!(r == g && g == b && (50..=58).contains(&r), "{:?}", [r, g, b]);
|
||
// Preview mode keeps the colours.
|
||
assert_eq!(Renderer::new().render(&d, 40, 40, Affine::IDENTITY, &RenderOptions::default()).pixel(20, 20), [255, 0, 0, 255]);
|
||
}
|