Merge pull request #6391 from dotCooCoo/fix/empty-contours-profile-limit

3D: a profile's empty contours count toward its point limit
This commit is contained in:
BFlat
2026-11-10 11:46:48 +07:00
committed by GitHub
2 changed files with 17 additions and 2 deletions
+6 -2
View File
@@ -480,10 +480,10 @@ pub fn revolve_curve_samples<'a>(paths: impl IntoIterator<Item = &'a PathData>,
let (mut anchors, mut contours, mut lines, mut curves, mut caps) = (0usize, 0usize, 0usize, 0usize, 0usize);
for sp in paths.into_iter().flat_map(|p| &p.subpaths) {
anchors = anchors.saturating_add(sp.anchors.len());
if anchors > MAX_PROFILE_POINTS {
contours += 1;
if anchors > MAX_PROFILE_POINTS || contours > MAX_PROFILE_POINTS {
return Err(TOO_COMPLEX_PROFILE.into());
}
contours += 1;
let segments = if sp.closed { sp.anchors.len() } else { sp.anchors.len().saturating_sub(1) };
for i in 0..segments {
if sp.segment_is_line(i) {
@@ -551,6 +551,10 @@ struct HoleSearch {
impl HoleSearch {
fn new(path: &PathData, rule: FillRule) -> Result<Self, String> {
// Each contour takes a profile point, as in `revolve_curve_samples`.
if path.subpaths.len() > MAX_PROFILE_POINTS {
return Err(TOO_COMPLEX_PROFILE.into());
}
let contours: Vec<(BezPath, Rect, Option<i32>)> = path
.subpaths
.iter()
@@ -68,6 +68,17 @@ fn too_many_anchors_are_refused_as_a_profile() {
assert_eq!(refused, TOO_COMPLEX_PROFILE);
}
#[test]
fn every_contour_takes_a_point_even_an_empty_one() {
// Contours of one anchor and of none, with no segment between them.
let lone = |i: usize| SubPath::new(if i.is_multiple_of(2) { vec![] } else { vec![Anchor::corner(Point::new(100.0, i as f64))] }, false);
let path = PathData::new((0..=MAX_PROFILE_POINTS).map(lone).collect());
assert_eq!(revolve_curve_samples([&path], Revolve::default()), Err(TOO_COMPLEX_PROFILE.to_string()));
assert_eq!(hole_segments(&path, FillRule::NonZero), Err(TOO_COMPLEX_PROFILE.to_string()), "before any contour is built");
let given = Revolve { curve_samples: Some(CURVE_SAMPLES), ..Revolve::default() };
assert_eq!(revolve_mesh(&path, FillRule::NonZero, path.bounds().unwrap(), given).map(|_| ()), Err(TOO_COMPLEX_PROFILE.to_string()));
}
#[test]
fn a_profile_at_the_point_limit_is_taken_and_one_past_it_is_refused() {
let straight = |anchors: usize| {