Bound SVG arc segment count for huge radii

Fixes #2128

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
NetterSilver
2026-10-24 14:43:44 +02:00
co-authored by Claude Haiku 5.5
parent eb5108786b
commit dbe92141d2
+11 -1
View File
@@ -227,7 +227,11 @@ fn segment(l: &mut Lex, c: u8, base: Vec2, p: &mut BezPath, cur: &mut Point, las
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)),
Some(a) => {
// Scale tolerance with the radius so the segment count stays bounded.
let tol = 0.1_f64.max(a.radii.x.max(a.radii.y) * 1e-4);
a.to_cubic_beziers(tol, |c1, c2, end| p.curve_to(c1, c2, end))
}
None => p.line_to(e),
}
*cur = e;
@@ -261,6 +265,12 @@ mod tests {
use super::*;
use kurbo::PathEl;
#[test]
fn huge_arc_radius_stays_bounded() {
let p = parse_path_data("M0 0A1e36 1e36 0 1 1 1e30 0");
assert!(p.elements().len() < 1000, "got {} elements", p.elements().len());
}
#[test]
fn commands() {
let p = parse_path_data("M10,10 L20,10 h10 v10 H10 z m5 5 l1-1.5.5.5e1 C 0 0 1 1 2 2 s3 3 4 4 Q1 1 2 2 t3 3 A5 5 0 0 1 20 20 a5 5 0 1010 0");