From 77d1f8901f2b1cc08f4eaaa794e75d9cebe2c7bd Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Fri, 23 Oct 2026 04:36:31 +0000 Subject: [PATCH] Stop DXF hatch source-handle loop at first missing handle Fixes #3590 Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/cad/src/import/entity.rs | 4 +++- crates/cad/src/import/tests.rs | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/crates/cad/src/import/entity.rs b/crates/cad/src/import/entity.rs index d11d6a35c..f24f05596 100644 --- a/crates/cad/src/import/entity.rs +++ b/crates/cad/src/import/entity.rs @@ -536,7 +536,9 @@ fn boundary(c: &mut Cursor<'_, '_>) -> Option { // The boundary objects it was made from. if let Some(n) = c.count(97) { for _ in 0..n { - c.opt(330); + if c.opt(330).is_none() { + break; + } } } Some(bp) diff --git a/crates/cad/src/import/tests.rs b/crates/cad/src/import/tests.rs index b22fdc4df..4845e8d2a 100644 --- a/crates/cad/src/import/tests.rs +++ b/crates/cad/src/import/tests.rs @@ -380,6 +380,27 @@ fn solid_hatches_fill_and_pattern_hatches_outline() { assert!(square.appearance.fill().is_some_and(|f| !f.paint.is_none())); } +#[test] +fn hatch_declaring_many_absent_source_handles_parses_quickly() { + let base = hatch("1"); + let at = |code: i32, from: usize| from + base[from..].iter().position(|p| p.0 == code).unwrap(); + let first = at(92, 0); + let end = at(97, first) + 1; + let mut boundary = base[first..end].to_vec(); + *boundary.last_mut().unwrap() = (97, "10000000"); + let n = 300; + let mut e: Vec<(i32, &'static str)> = base[..first].to_vec(); + e[at(91, 0)] = (91, "300"); + for _ in 0..n { + e.extend_from_slice(&boundary); + } + e.extend_from_slice(&base[end..]); + let start = std::time::Instant::now(); + let r = open(&entities(&e), &points()); + assert!(start.elapsed() < std::time::Duration::from_millis(400), "took {:?}", start.elapsed()); + assert_eq!(r.document.layers[0].children().unwrap().len(), 1, "{:?}", r.warnings); +} + /// A solid hatch: a loop of a line and a spline edge (`fit` its fit data, if any), followed by /// `source` (the loop's source-object count and handles), and a square hole. fn spline_edged_hatch(fit: &[(i32, &'static str)], source: &[(i32, &'static str)]) -> Vec<(i32, &'static str)> {