Geometry: measurement allows a capped arc's control points past the cap

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Trevor BrownandClaude Fable 5.1 committed 2026-11-02 03:50:41 -05:00
1 parent 5f89b05b74
commit a6e7920b24
2 files changed
+25 -6

No files matched your search

+9 -4
View File
@@ -8,11 +8,16 @@ pub const FLATTEN_TOL: f64 = 0.05;
/// The most flattened points a path is measured with; longer paths are refused.
pub const MAX_SAMPLES: usize = 40_000;
/// Every coordinate is finite and of a sane magnitude: within [`crate::MAX_COORD`], the cap the
/// shape builders hold their sizes, radii and angles to (inclusive, so a path built at the cap
/// still measures).
/// How far out a measured coordinate may lie. The shape builders hold their sizes, radii and
/// angles to [`crate::MAX_COORD`], so a path built at the cap has its points there and the
/// control points of its curves a little past them (the cubics approximating an arc reach past
/// the arc's box by up to about a tenth of the radius). Half as much again keeps every built path
/// measurable and still refuses the absurd.
pub const MAX_MEASURED_COORD: f64 = crate::MAX_COORD * 1.5;
/// Every coordinate is finite and of a sane magnitude (within [`MAX_MEASURED_COORD`]).
pub fn finite_path(path: &BezPath) -> bool {
let ok = |p: &Point| p.x.is_finite() && p.y.is_finite() && p.x.abs() <= crate::MAX_COORD && p.y.abs() <= crate::MAX_COORD;
let ok = |p: &Point| p.x.is_finite() && p.y.is_finite() && p.x.abs() <= MAX_MEASURED_COORD && p.y.abs() <= MAX_MEASURED_COORD;
path.elements().iter().all(|el| match el {
PathEl::MoveTo(p) | PathEl::LineTo(p) => ok(p),
PathEl::QuadTo(a, b) => ok(a) && ok(b),
+16 -2
View File
@@ -68,11 +68,25 @@ fn paths_at_the_cap_still_measure() {
line.move_to(Point::new(-MAX_COORD, 0.0));
line.line_to(Point::new(MAX_COORD, -MAX_COORD));
assert!(polylines(&line).is_some(), "a line between the cap's corners measures");
// A curve at the cap: the cubics approximating the arc have control points past the cap, and
// the path still measures.
let arc = ellipse(MAX_COORD, 1.0, -0.15, 0.2, 0.0);
let reach = arc
.elements()
.iter()
.flat_map(|el| match el {
kurbo::PathEl::CurveTo(a, b, _) => vec![a.x, b.x],
_ => vec![],
})
.fold(0.0, f64::max);
assert!(reach > MAX_COORD, "a control point lies past the cap: {reach}");
assert!(finite_path(&arc));
assert!(polylines(&arc).is_some(), "an arc at the cap measures");
let mut past = BezPath::new();
past.move_to(Point::new(0.0, 0.0));
past.line_to(Point::new(MAX_COORD + 1.0, 0.0));
past.line_to(Point::new(2.0 * MAX_COORD, 0.0));
assert!(!finite_path(&past));
assert!(polylines(&past).is_none(), "a coordinate past the cap is refused");
assert!(polylines(&past).is_none(), "a coordinate well past the cap is refused");
}
#[test]