Draw a line to the end point of degenerate SVG arcs

Found while testing crates/svg/src/pathdata.rs:228-233

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
NetterSilver
2026-10-23 00:30:59 +00:00
co-authored by Claude Haiku 5.5
parent 0871135a6b
commit 58fbda40b4
+22 -3
View File
@@ -226,9 +226,16 @@ fn segment(l: &mut Lex, c: u8, base: Vec2, p: &mut BezPath, cur: &mut Point, las
let sweep = l.flag()?;
let e = pt(l)?;
let arc = SvgArc { from: *cur, to: e, radii: Vec2::new(rx, ry), x_rotation: rot.to_radians(), large_arc: large, sweep };
match kurbo::Arc::from_svg_arc(&arc) {
Some(a) => a.to_cubic_beziers(0.1, |c1, c2, end| p.curve_to(c1, c2, end)),
None => p.line_to(e),
let mut last_end = None;
if let Some(a) = kurbo::Arc::from_svg_arc(&arc) {
a.to_cubic_beziers(0.1, |c1, c2, end| {
p.curve_to(c1, c2, end);
last_end = Some(end);
});
}
// Degenerate arcs (e.g. huge radii) may emit nothing or stop short of the end point.
if last_end.is_none_or(|q| (q - e).hypot() > 1e-3 * (1.0 + e.to_vec2().hypot())) {
p.line_to(e);
}
*cur = e;
*last_cubic = None;
@@ -294,6 +301,18 @@ mod tests {
assert!(parse_path_data("M0 0 L10 0 z 9 9").elements().len() <= 4);
}
#[test]
fn huge_radius_arc_still_reaches_end_point() {
for d in ["M0 0 A1e20 1e20 0 0 1 10 0 L10 10", "M0 0 A1e20 1e20 0 1 1 10 0 L10 10", "M0 0 a1e20 1e20 0 0 1 10 0 L10 10"] {
let p = parse_path_data(d);
let reaches = p.elements().iter().any(|e| match e {
PathEl::LineTo(q) | PathEl::CurveTo(_, _, q) => (q.x - 10.0).abs() < 1e-6 && q.y.abs() < 1e-6,
_ => false,
});
assert!(reaches, "{d}: {:?}", p.elements());
}
}
#[test]
fn number_lists() {
assert_eq!(numbers("0 0,100 50"), vec![0.0, 0.0, 100.0, 50.0]);