vectorcraft/crates/engine/src/tests_strokereach.rs

77 lines
3.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! Visual bounds and clicks take in the whole stroke: arrowheads, outside alignment, width
//! profiles (through the Selection tool and the commands that use visual bounds).
use serde_json::json;
use vectorcraft_tools::{PointerEvent, PointerKind};
use super::*;
fn session() -> Session {
let mut s = Session::new();
s.execute("file.new", &json!({"width": 400, "height": 400})).unwrap();
s
}
fn id_of(v: &serde_json::Value) -> NodeId {
NodeId(v["id"].as_u64().unwrap())
}
/// Click with the Selection tool at (x, y) on a 100% view: what is selected afterwards.
fn click(s: &mut Session, x: f64, y: f64) -> Vec<NodeId> {
let v = ViewInfo::default();
s.select_tool("selection", v).unwrap();
for k in [PointerKind::Down, PointerKind::Up] {
s.pointer(&PointerEvent::new(k, x, y), v).unwrap();
}
s.active().unwrap().selection.objects.clone()
}
/// The artboard after Fit to Selected Art (which fits the selection's visual bounds).
fn fitted(s: &mut Session) -> vectorcraft_geom::Rect {
s.execute("artboard.fitToSelection", &json!({})).unwrap();
s.doc().unwrap().doc.artboards[0].rect
}
#[test]
fn a_300_percent_arrowhead_grows_the_visual_bounds() {
let mut s = session();
s.execute("shape.line", &json!({"x1": 100, "y1": 200, "x2": 300, "y2": 200})).unwrap();
s.execute("stroke.set", &json!({"weight": 2, "join": "round", "endArrow": "Triangle"})).unwrap();
let plain = fitted(&mut s);
s.execute("stroke.setAdvanced", &json!({"arrowScale": [100, 300]})).unwrap();
let big = fitted(&mut s);
// The 24 pt head reaches past the end and 12 pt to each side of the line.
assert!(big.x1 > plain.x1 + 15.0 && big.y1 >= 212.0 && big.y0 <= 188.0, "{plain:?} → {big:?}");
assert_eq!(big.x0, plain.x0, "the start has no head");
}
#[test]
fn a_click_outside_an_outside_stroke_selects_it() {
let mut s = session();
let r = id_of(&s.execute("shape.rectangle", &json!({"x": 100, "y": 100, "width": 200, "height": 200})).unwrap());
s.execute("paint.setFill", &json!({"none": true})).unwrap();
s.execute("stroke.set", &json!({"weight": 20, "align": "outside"})).unwrap();
s.execute("select.none", &json!({})).unwrap();
// 0.8 × the weight outside the path: past where a centred stroke (plus the tolerance) reaches.
assert_eq!(click(&mut s, 84.0, 200.0), [r]);
s.execute("select.none", &json!({})).unwrap();
assert!(click(&mut s, 116.0, 200.0).is_empty(), "nothing paints inside");
s.execute("stroke.set", &json!({"ids": [r.0], "align": "center"})).unwrap();
s.execute("select.none", &json!({})).unwrap();
assert!(click(&mut s, 84.0, 200.0).is_empty(), "a centred stroke doesn't reach");
}
#[test]
fn a_click_at_the_lens_maximum_selects_its_stroke() {
let mut s = session();
let l = id_of(&s.execute("shape.line", &json!({"x1": 100, "y1": 200, "x2": 300, "y2": 200})).unwrap());
s.execute("stroke.set", &json!({"weight": 20, "profile": "lens"})).unwrap();
s.execute("select.none", &json!({})).unwrap();
assert_eq!(click(&mut s, 200.0, 209.0), [l], "the widest point");
s.execute("select.none", &json!({})).unwrap();
assert!(click(&mut s, 110.0, 209.0).is_empty(), "the thin end");
// Fitted bounds take the profile in too.
s.execute("select.set", &json!({"ids": [l.0]})).unwrap();
assert_eq!(fitted(&mut s).y1, 210.0);
}