mirror of
https://github.com/storytold/cadcraft.git
synced 2026-11-04 09:30:41 -06:00
fix(io): sort each space once when a DXF has several SORTENTSTABLEs for it
Every SORTENTSTABLE rebuilt its whole entity store, so many small tables naming one large space made import quadratic. Each space is now sorted once, by the last table naming it, which already decided its order.
This commit is contained in:
@@ -314,7 +314,17 @@ pub(super) fn apply_sortents(
|
||||
paper_for: &HashMap<String, String>,
|
||||
first_layout: &str,
|
||||
) {
|
||||
for (owner, map) in tables {
|
||||
// Each sort rebuilds its whole space, so a space named by many tables is sorted once, by the
|
||||
// last of them (which decided its order anyway); repeated tables made import quadratic.
|
||||
let target = |owner: &String| {
|
||||
let up = brs.get(owner)?.to_ascii_uppercase();
|
||||
Some(if up.starts_with("*PAPER_SPACE") { paper_for.get(&up).cloned().unwrap_or_else(|| first_layout.to_string()) + "\0paper" } else { up })
|
||||
};
|
||||
let last: HashMap<String, usize> = tables.iter().enumerate().filter_map(|(i, (owner, _))| Some((target(owner)?, i))).collect();
|
||||
for (i, (owner, map)) in tables.iter().enumerate() {
|
||||
if target(owner).and_then(|t| last.get(&t)) != Some(&i) {
|
||||
continue;
|
||||
}
|
||||
let Some(name) = brs.get(owner) else { continue };
|
||||
let up = name.to_ascii_uppercase();
|
||||
// A sort handle of 0 draws last (ezdxf `reorder`, which notes AutoCAD defines it, undocumented).
|
||||
|
||||
@@ -337,6 +337,28 @@ fn entity_transparency_roundtrips_as_group_440() {
|
||||
assert_eq!(d.model.iter().map(|e| e.common.transparency).collect::<Vec<_>>(), [Transparency::ByLayer, Transparency::Percent(90)]);
|
||||
}
|
||||
|
||||
/// Several SORTENTSTABLEs for one space sort it once, in the last table's order.
|
||||
#[test]
|
||||
fn repeated_sortents_tables_use_the_last() {
|
||||
let table =
|
||||
|a: u32, b: u32| format!("0\nSORTENTSTABLE\n5\n{:X}\n100\nAcDbSortentsTable\n330\n1F\n331\nA\n5\n{a:X}\n331\nB\n5\n{b:X}\n", 0x100 + a);
|
||||
let mut t = String::from(
|
||||
"0\nSECTION\n2\nTABLES\n0\nTABLE\n2\nBLOCK_RECORD\n0\nBLOCK_RECORD\n5\n1F\n2\n*Model_Space\n0\nENDTAB\n0\nENDSEC\n\
|
||||
0\nSECTION\n2\nENTITIES\n0\nLINE\n5\nA\n330\n1F\n10\n0\n20\n0\n11\n1\n21\n1\n0\nLINE\n5\nB\n330\n1F\n10\n0\n20\n0\n11\n2\n21\n2\n0\nENDSEC\n\
|
||||
0\nSECTION\n2\nOBJECTS\n0\nDICTIONARY\n5\nC\n",
|
||||
);
|
||||
for _ in 0..1000 {
|
||||
t.push_str(&table(2, 1));
|
||||
}
|
||||
t.push_str(&table(1, 2));
|
||||
t.push_str("0\nENDSEC\n0\nEOF\n");
|
||||
let d = read(t.as_bytes(), "s.dxf").unwrap();
|
||||
assert_eq!(d.model.iter().map(|e| e.handle.0).collect::<Vec<_>>(), [0xA, 0xB]);
|
||||
let reversed = t.replacen(&table(1, 2), &table(2, 1), 1);
|
||||
let d = read(reversed.as_bytes(), "s.dxf").unwrap();
|
||||
assert_eq!(d.model.iter().map(|e| e.handle.0).collect::<Vec<_>>(), [0xB, 0xA]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hostile_dxf_does_not_panic() {
|
||||
for t in [
|
||||
|
||||
Reference in New Issue
Block a user