From 58fbda40b4a8e9662bacab1b95d718c45096bb7b Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Fri, 23 Oct 2026 00:30:59 +0000 Subject: [PATCH] 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 Co-Authored-By: Claude Opus 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/svg/src/pathdata.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/crates/svg/src/pathdata.rs b/crates/svg/src/pathdata.rs index c8fa7f67f..eb947373f 100644 --- a/crates/svg/src/pathdata.rs +++ b/crates/svg/src/pathdata.rs @@ -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]);