mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 12:13:19 +00:00
#1280: PathData::bounds closes a NaN anchor as kurbo does; the perf row names what it times
Follow-up to CodeRabbit's review of #5778. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
committed by
bflatastic
co-authored by
Claude Opus 5.5
parent
b13335d188
commit
c1f7e4ed6d
@@ -214,12 +214,13 @@ fn pointing(n: usize, rows: &mut Vec<(String, f64)>) -> Result<(), String> {
|
||||
format!("smart guide targets in view ({n} paths)"),
|
||||
median_ms(5, || drop(vectorcraft_engine::tools::guides::Targets::collect(&doc, &[], Some(view_rect)))),
|
||||
));
|
||||
// Shift-clicking one more object into a selection of half the document.
|
||||
// Adding one more object to a selection of half the document: the command a shift-click ends
|
||||
// in, without the pointer handling and hit test before it.
|
||||
let ids: Vec<u64> = doc.layers[0].children().map(|c| c.iter().map(|n| n.id.0).collect()).unwrap_or_default();
|
||||
s.execute("select.set", &json!({"ids": ids[..ids.len() / 2]})).map_err(err)?;
|
||||
let mut k = ids.len() / 2;
|
||||
rows.push((
|
||||
format!("shift-click into a {}-object selection", ids.len() / 2),
|
||||
format!("select.toggle in a {}-object selection", ids.len() / 2),
|
||||
median_ms(5, || {
|
||||
k += 1;
|
||||
let _ = s.execute("select.toggle", &json!({"id": ids[k % ids.len()]}));
|
||||
|
||||
+18
-1
@@ -562,13 +562,21 @@ impl PathData {
|
||||
}
|
||||
let mut bbox: Option<Rect> = None;
|
||||
for sp in &self.subpaths {
|
||||
// (a closed subpath's last segment ends on its first anchor: its `ClosePath` adds no line)
|
||||
for i in 0..sp.segment_count() {
|
||||
let c = sp.segment(i);
|
||||
// `to_bezpath_into` writes a line where neither handle is out, else a cubic.
|
||||
let seg = segment_bounds(if sp.segment_is_line(i) { PathSeg::Line(kurbo::Line::new(c.p0, c.p3)) } else { PathSeg::Cubic(c) });
|
||||
bbox = Some(bbox.map_or(seg, |bb| bb.union(seg)));
|
||||
}
|
||||
// A closed subpath's last segment ends on its first anchor, so its `ClosePath` adds no
|
||||
// line, unless that anchor is NaN: it then differs from itself, and kurbo closes with one.
|
||||
if sp.closed
|
||||
&& let Some(a) = sp.anchors.first()
|
||||
&& (a.p.x.is_nan() || a.p.y.is_nan())
|
||||
{
|
||||
let seg = segment_bounds(PathSeg::Line(kurbo::Line::new(a.p, a.p)));
|
||||
bbox = Some(bbox.map_or(seg, |bb| bb.union(seg)));
|
||||
}
|
||||
}
|
||||
Some(bbox.unwrap_or_default())
|
||||
}
|
||||
@@ -764,6 +772,15 @@ mod tests {
|
||||
let lone = PathData::new(vec![SubPath::polyline(&[Point::new(5.0, 5.0)], false), SubPath::polyline(&[Point::new(9.0, 1.0)], true)]);
|
||||
assert_eq!(lone.bounds(), Some(Rect::ZERO));
|
||||
assert_eq!(bits(lone.bounds()), bits(reference(&lone)));
|
||||
// A NaN anchor differs from itself: kurbo closes such a subpath with a line of its own.
|
||||
let nan = Point::new(f64::NAN, 1.0);
|
||||
let closed = |pts: &[Point]| SubPath::polyline(pts, true);
|
||||
for pd in [
|
||||
PathData::new(vec![closed(&[nan]), closed(&[Point::new(5.0, 5.0)])]),
|
||||
PathData::new(vec![closed(&[nan, Point::new(3.0, 4.0), Point::new(6.0, 1.0)])]),
|
||||
] {
|
||||
assert_eq!(bits(pd.bounds()), bits(reference(&pd)));
|
||||
}
|
||||
}
|
||||
|
||||
fn square() -> PathData {
|
||||
|
||||
Reference in New Issue
Block a user