address review: size operator budgets from drawn segments plus per-subpath overhead

This commit is contained in:
Dylan M. Taylor
2026-11-03 20:32:26 +00:00
parent 70d234d97a
commit e17a0e2dd5
2 changed files with 24 additions and 4 deletions
+9 -4
View File
@@ -448,11 +448,16 @@ struct Sample {
/// output keeps a short stack from multiplying a simple path into billions of points.
pub const MAX_OPERATOR_SEGMENTS: usize = 1 << 20;
/// `want` pieces (or copies) per input segment, reduced so the whole output stays within
/// [`MAX_OPERATOR_SEGMENTS`] (never below 1, so the input itself always passes through).
/// `want` pieces (or copies) per input segment, reduced so the whole output (segments times
/// pieces, plus per-subpath overhead) stays within [`MAX_OPERATOR_SEGMENTS`] (never below 1, so the input itself always passes through).
fn pieces_within_budget(paths: &[BezPath], want: usize) -> usize {
let segs: usize = paths.iter().map(|p| p.elements().len()).sum();
want.min(MAX_OPERATOR_SEGMENTS / segs.max(1)).max(1)
// Count what is subdivided (drawn segments) and keep room for each subpath's own MoveTo/Close.
let (mut segs, mut overhead) = (0usize, 0usize);
for sub in paths.iter().flat_map(subs) {
segs = segs.saturating_add(sub.segs.len());
overhead = overhead.saturating_add(2);
}
want.min(MAX_OPERATOR_SEGMENTS.saturating_sub(overhead) / segs.max(1)).max(1)
}
/// Split every segment into `m` pieces of equal arc length. Original vertices get the average of
+15
View File
@@ -438,3 +438,18 @@ fn stacked_expanding_operators_stay_within_the_segment_budget() {
// Within the budget nothing changes: 4 segments × 11 pieces.
assert_eq!(vertex_count(&zigzag(&[sq(0.0, 0.0, 100.0)], 1.0, 10.0, false)[0]), 44);
}
#[test]
fn many_short_open_paths_keep_their_requested_detail_within_the_budget() {
// 1000 open lines at 1000 ridges: 1,001,000 segments fit the budget, so nothing is reduced.
let lines: Vec<BezPath> = (0..1000)
.map(|i| {
let mut p = BezPath::new();
p.move_to((0.0, i as f64));
p.line_to((100.0, i as f64));
p
})
.collect();
let z = zigzag(&lines, 1.0, 1000.0, false);
assert!(z.iter().all(|q| q.elements().len() == 1 + 1001));
}