mirror of
https://github.com/storytold/cadcraft.git
synced 2026-11-03 17:18:01 -06:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cfd67ba61 | ||
|
|
578da3ba9c | ||
|
|
e29c2f80a4 |
@@ -333,7 +333,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).
|
||||
|
||||
@@ -299,7 +299,9 @@ pub(super) fn acad_table(tags: &[Tag], table_cells_left: &mut usize) -> Table {
|
||||
// Large declared sizes must be backed by cell records (no allocation from a bare count).
|
||||
let n_cells = tail.iter().filter(|x| x.code == 171).count();
|
||||
let declared = rows.saturating_mul(cols);
|
||||
if declared > MAX_CELLS || (declared > 10_000 && n_cells < declared) {
|
||||
// A table with no rows or no columns has no cells: keep neither dimension, so its row heights
|
||||
// and column widths (allocated per dimension, outside the cell budget) are not allocated.
|
||||
if declared == 0 || declared > MAX_CELLS || (declared > 10_000 && n_cells < declared) {
|
||||
rows = 0;
|
||||
cols = 0;
|
||||
}
|
||||
|
||||
@@ -337,6 +337,42 @@ 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]);
|
||||
}
|
||||
|
||||
/// A table declaring 10 000 rows and no columns (or the reverse) is read as an empty table.
|
||||
#[test]
|
||||
fn table_with_an_empty_dimension_allocates_nothing() {
|
||||
for (rows, cols) in [(10_000, 0), (0, 10_000)] {
|
||||
let t = format!("0\nSECTION\n2\nENTITIES\n0\nACAD_TABLE\n100\nAcDbTable\n91\n{rows}\n92\n{cols}\n0\nENDSEC\n0\nEOF\n");
|
||||
let d = read(t.as_bytes(), "t.dxf").unwrap();
|
||||
let tables: Vec<_> = d.model.iter().filter_map(|e| if let EntityKind::Table(t) = &e.kind { Some(t) } else { None }).collect();
|
||||
assert_eq!(tables.len(), 1, "the table is read");
|
||||
for t in tables {
|
||||
assert!(t.row_heights.is_empty() && t.col_widths.is_empty() && t.cells.is_empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Many distinct layer, linetype and style names (in the tables and on entities) read in linear
|
||||
/// time, with the duplicate rules kept: first LTYPE wins, last STYLE wins, layers case-insensitive.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user