mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-26 10:47:11 -06:00
Arrowheads, width-profile outlines and dashed line outlines now come from vectorcraft_effects::stroke (stroke_pieces, line_outline, width_outline), used by the canvas and PDF export alike; the renderer caches profile outlines too. Width profiles are a doc-level catalogue (WidthProfile::PRESETS, preset, preset_id, id_of) shared by stroke.set and the Stroke panel; stroke.set rejects unknown profile ids and its params doc lists the arrowhead names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
48 lines
1.9 KiB
Rust
48 lines
1.9 KiB
Rust
//! Stroke geometry from the Stroke panel's commands (`cmd/stroke.rs`): the width-profile presets.
|
|
|
|
use serde_json::json;
|
|
use vectorcraft_doc::{StrokeLayer, WidthProfile};
|
|
|
|
use super::*;
|
|
|
|
fn session_with_line() -> (Session, NodeId) {
|
|
let mut s = Session::new();
|
|
s.execute("file.new", &json!({"width": 200, "height": 200})).unwrap();
|
|
let r = s.execute("shape.line", &json!({"x1": 10, "y1": 100, "x2": 150, "y2": 100})).unwrap();
|
|
(s, NodeId(r["id"].as_u64().unwrap()))
|
|
}
|
|
|
|
fn stroke(s: &Session, id: NodeId) -> StrokeLayer {
|
|
s.doc().unwrap().doc.node(id).unwrap().appearance.stroke().unwrap().clone()
|
|
}
|
|
|
|
#[test]
|
|
fn profiles_come_from_the_preset_catalogue() {
|
|
let (mut s, id) = session_with_line();
|
|
for p in WidthProfile::PRESETS {
|
|
s.execute("stroke.set", &json!({"profile": p.id})).unwrap();
|
|
let st = stroke(&s, id);
|
|
assert_eq!(WidthProfile::id_of(st.profile.as_ref()), p.id);
|
|
}
|
|
assert!(stroke(&s, id).profile.is_some());
|
|
s.execute("stroke.set", &json!({"profile": "uniform"})).unwrap();
|
|
assert!(stroke(&s, id).profile.is_none(), "uniform is the plain stroke");
|
|
assert!(s.execute("stroke.set", &json!({"profile": "zigzag"})).is_err());
|
|
// The params doc (what agents read) lists every preset.
|
|
let spec = command_specs().iter().find(|c| c.id == "stroke.set").unwrap();
|
|
for p in WidthProfile::PRESETS {
|
|
assert!(spec.params.contains(&format!("\"{}\"", p.id)), "{}", p.id);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn profiles_survive_the_native_format() {
|
|
let (mut s, id) = session_with_line();
|
|
s.execute("stroke.set", &json!({"startArrow": "CircleOpen", "endArrow": "Arrow", "profile": "taperEnd"})).unwrap();
|
|
let doc = &s.doc().unwrap().doc;
|
|
let back = vectorcraft_format::load(&vectorcraft_format::save(doc, false)).unwrap();
|
|
let st = back.node(id).unwrap().appearance.stroke().unwrap().clone();
|
|
assert_eq!(st, stroke(&s, id));
|
|
assert_eq!(WidthProfile::id_of(st.profile.as_ref()), "taperEnd");
|
|
}
|