mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-10 12:21:54 +00:00
3D: a profile's empty contours count toward its point limit
revolve_curve_samples counted a profile's contours but never compared the count with the limit, so a profile made only of empty or one-anchor subpaths passed, although each contour takes one profile point. HoleSearch::new then built one entry for each subpath without a limit, and mesh export skips revolve_curve_samples when curve_samples is given. Both now refuse a profile with more than 16,384 contours as too complex.
This commit is contained in:
@@ -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| {
|
||||
|
||||
Reference in New Issue
Block a user