mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-28 11:47:21 -06:00
Merge pull request #3754 from Silvertree2010/fix/3595-audit-dxf-import-paper-layouts-a
Fix quadratic paper layout de-duplication in DXF import
This commit is contained in:
@@ -423,6 +423,7 @@ fn font_family(g: &[Pair<'_>]) -> String {
|
||||
/// objects but with paper-space art has one paper layout.
|
||||
fn layouts(objects: &[Record<'_>], block_records: &HashMap<String, String>, entities: &[Record<'_>]) -> Vec<LayoutDef> {
|
||||
let mut paper: Vec<(i64, LayoutDef)> = vec![];
|
||||
let mut seen = std::collections::HashSet::new();
|
||||
for r in objects.iter().filter(|r| r.kind == "LAYOUT") {
|
||||
// The layout's own groups follow its subclass marker.
|
||||
let own = r.g.iter().position(|p| p.code == 100 && p.value.trim() == "AcDbLayout").and_then(|i| r.g.get(i + 1..)).unwrap_or(&[]);
|
||||
@@ -432,7 +433,7 @@ fn layouts(objects: &[Record<'_>], block_records: &HashMap<String, String>, enti
|
||||
continue;
|
||||
}
|
||||
let Some(block) = block else { continue };
|
||||
if !paper.iter().any(|(_, l)| l.name.eq_ignore_ascii_case(name)) {
|
||||
if seen.insert(name.to_ascii_lowercase()) {
|
||||
paper.push((own.int_or(71, i64::MAX), LayoutDef { name: name.to_string(), block: Some(block) }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1061,3 +1061,32 @@ fn entities_extruded_along_minus_z_are_mirrored() {
|
||||
let b = bounds(&leaves(&doc)[0]);
|
||||
assert!((b.center().x + 50.0).abs() < 1e-6, "the centre's x is mirrored: {b:?}");
|
||||
}
|
||||
|
||||
/// A drawing with one paper block record (handle `A`) and a LAYOUT object per name.
|
||||
fn with_layouts(names: &[String]) -> Vec<u8> {
|
||||
let mut s = String::from(
|
||||
" 0\nSECTION\n 2\nTABLES\n 0\nTABLE\n 2\nBLOCK_RECORD\n 0\nBLOCK_RECORD\n 5\nA\n 2\n*Paper_Space\n 0\nENDTAB\n 0\nENDSEC\n 0\nSECTION\n 2\nOBJECTS\n",
|
||||
);
|
||||
for n in names {
|
||||
s.push_str(&format!(" 0\nLAYOUT\n100\nAcDbLayout\n 1\n{n}\n330\nA\n"));
|
||||
}
|
||||
s.push_str(" 0\nENDSEC\n 0\nEOF\n");
|
||||
s.into_bytes()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn many_paper_layouts_are_read_in_linear_time() {
|
||||
let names: Vec<String> = (0..100_000).map(|i| format!("L{i}")).collect();
|
||||
let bytes = with_layouts(&names);
|
||||
let t = std::time::Instant::now();
|
||||
let info = info(&bytes).unwrap();
|
||||
assert_eq!(info.layouts.len(), names.len() + 1);
|
||||
assert!(t.elapsed() < std::time::Duration::from_secs(5), "layout de-duplication is quadratic: {:?}", t.elapsed());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn paper_layout_names_are_unique_ignoring_case() {
|
||||
let names = ["Layout1", "LAYOUT1", "Other"].map(String::from);
|
||||
let info = info(&with_layouts(&names)).unwrap();
|
||||
assert_eq!(info.layouts, ["Model", "Layout1", "Other"]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user