From c81590a76c0aa9c3f4fb44efbe3a08cc9aa13b23 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 05:54:42 -0500 Subject: [PATCH] Use shared IDML row and column geometry --- Cargo.lock | 36 ++++++++++++++++----------------- Cargo.toml | 4 ++-- crates/idml/src/import/table.rs | 25 ++++++++++++----------- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 810e0cc4b..c3fc33245 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1242,10 +1242,10 @@ dependencies = [ [[package]] name = "craft-idml" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=1e7f088b8#1e7f088b80670ad9ec6a2a3a714d40ded01f8c01" +source = "git+https://github.com/storytold/craft-libs?rev=a4496eabf#a4496eabf80b753ce4d4e5f6a635628869711f75" dependencies = [ - "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=1e7f088b8)", - "craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=1e7f088b8)", + "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=a4496eabf)", + "craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=a4496eabf)", "thiserror 2.0.21", ] @@ -1644,15 +1644,6 @@ dependencies = [ "thiserror 2.0.21", ] -[[package]] -name = "craft-xml" -version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=1e7f088b8#1e7f088b80670ad9ec6a2a3a714d40ded01f8c01" -dependencies = [ - "quick-xml 0.41.0", - "thiserror 2.0.21", -] - [[package]] name = "craft-xml" version = "0.1.0" @@ -1671,6 +1662,15 @@ dependencies = [ "thiserror 2.0.21", ] +[[package]] +name = "craft-xml" +version = "0.1.0" +source = "git+https://github.com/storytold/craft-libs?rev=a4496eabf#a4496eabf80b753ce4d4e5f6a635628869711f75" +dependencies = [ + "quick-xml 0.41.0", + "thiserror 2.0.21", +] + [[package]] name = "craft-xml" version = "0.1.0" @@ -1730,7 +1730,7 @@ dependencies = [ [[package]] name = "craft-zip" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=1e7f088b8#1e7f088b80670ad9ec6a2a3a714d40ded01f8c01" +source = "git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551#8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551" dependencies = [ "flate2", "thiserror 2.0.21", @@ -1740,7 +1740,7 @@ dependencies = [ [[package]] name = "craft-zip" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551#8abfa9d0f14bafbfc3449fc552ffeafb9ca6a551" +source = "git+https://github.com/storytold/craft-libs?rev=a4496eabf#a4496eabf80b753ce4d4e5f6a635628869711f75" dependencies = [ "flate2", "thiserror 2.0.21", @@ -2021,7 +2021,7 @@ dependencies = [ "craft-prepress", "craft-print", "craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cc23ffd4d26f3074808e2187d332564817624f8f)", - "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=1e7f088b8)", + "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=a4496eabf)", "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=f23b0f33f0d00b157476533a43cbbcfd901aa1f1)", "designcraft-color", "designcraft-compose", @@ -2103,9 +2103,9 @@ name = "designcraft-idml" version = "0.20.1" dependencies = [ "craft-file-formats", - "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=1e7f088b8)", + "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=a4496eabf)", "craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cc23ffd4d26f3074808e2187d332564817624f8f)", - "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=1e7f088b8)", + "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=a4496eabf)", "designcraft-color", "designcraft-compose", "designcraft-doc", @@ -2222,7 +2222,7 @@ version = "0.20.1" dependencies = [ "craft-docx", "craft-file-formats", - "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=1e7f088b8)", + "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=a4496eabf)", "craft-rtf", "craft-wordmodel", "craft-xlsx", diff --git a/Cargo.toml b/Cargo.toml index 1bf172ae0..c5d16c191 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,10 +16,10 @@ craft-pdf = { git = "https://github.com/storytold/craft-libs", rev = "4052591363 craft-designcraft-format = { git = "https://github.com/storytold/craft-libs", rev = "19692b6190465671e41967c75d0cd4c439d0c84c", version = "=0.1.0" } craft-eps = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" } craft-epub = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" } -craft-idml = { git = "https://github.com/storytold/craft-libs", rev = "1e7f088b8", version = "=0.1.0" } +craft-idml = { git = "https://github.com/storytold/craft-libs", rev = "a4496eabf", version = "=0.1.0" } craft-indd = { git = "https://github.com/storytold/craft-libs", rev = "47bf5650b0d503b97bfb5e841746c4957897d11f", version = "=0.1.0" } craft-svg = { git = "https://github.com/storytold/craft-libs", rev = "cc23ffd4d26f3074808e2187d332564817624f8f", version = "=0.1.0", features = ["tree-render", "tree-text"] } -craft-xml = { git = "https://github.com/storytold/craft-libs", rev = "1e7f088b8", version = "=0.1.0" } +craft-xml = { git = "https://github.com/storytold/craft-libs", rev = "a4496eabf", version = "=0.1.0" } craft-xml-dtd = { package = "craft-xml", git = "https://github.com/storytold/craft-libs", rev = "f23b0f33f0d00b157476533a43cbbcfd901aa1f1", version = "=0.1.0" } craft-rtf = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" } craft-xlsx = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" } diff --git a/crates/idml/src/import/table.rs b/crates/idml/src/import/table.rs index 95efc8357..4c41fe885 100644 --- a/crates/idml/src/import/table.rs +++ b/crates/idml/src/import/table.rs @@ -56,8 +56,7 @@ impl<'r> Importer<'r> { /// ``: rows, columns and cells (cell `Name` is `column:row`). pub(super) fn table(&mut self, e: &El) -> Option
{ let table_options = craft_idml::model::Values::of(&crate::xml::to_craft(e)).table_options(); - let rows: Vec<&El> = e.find_all("Row").collect(); - let cols: Vec<&El> = e.find_all("Column").collect(); + let layout = craft_idml::model::TableLayout::from_el(&crate::xml::to_craft(e)); // A file's row and column counts are its claim, and a table of them is allocated whole: a // story holding one `
` with 5,000 of each asked for 25M cells, around 34 GB, which // aborts the process instead of failing (#1583). What is read is clamped, and the rest of @@ -66,7 +65,7 @@ impl<'r> Importer<'r> { // // Reserved before `Table::new`, so a cell's own story cannot spend the budget this table // is counting on. - let Some((nr, nc, over_budget)) = budgeted_size(rows.len().max(1), cols.len().max(1), self.table_cells) else { + let Some((nr, nc, over_budget)) = budgeted_size(layout.rows.len().max(1), layout.columns.len().max(1), self.table_cells) else { // Said once: the file that reaches this is the one with millions of tables in it. if !self.table_budget_spent { self.table_budget_spent = true; @@ -77,13 +76,15 @@ impl<'r> Importer<'r> { return None; }; self.table_cells = self.table_cells.saturating_add(nr.saturating_mul(nc)); - if nr < rows.len() || nc < cols.len() { + if nr < layout.rows.len() || nc < layout.columns.len() { let why = if over_budget { "more than the tables in one file can hold between them" } else { "more than a table can hold" }; self.table_warnings += 1; match self.table_warnings.cmp(&MAX_TABLE_WARNINGS) { - std::cmp::Ordering::Less => { - self.warnings.push(format!("a table of {} rows and {} columns was read as {nr} x {nc}: {why}", rows.len(), cols.len())) - } + std::cmp::Ordering::Less => self.warnings.push(format!( + "a table of {} rows and {} columns was read as {nr} x {nc}: {why}", + layout.rows.len(), + layout.columns.len() + )), std::cmp::Ordering::Equal => { self.warnings.push(format!("more than {MAX_TABLE_WARNINGS} tables were read smaller than this file claims")) } @@ -91,8 +92,8 @@ impl<'r> Importer<'r> { } } let id = self.alloc(); - let rows = &rows[..nr.min(rows.len())]; - let cols = &cols[..nc.min(cols.len())]; + let rows = &layout.rows[..nr.min(layout.rows.len())]; + let cols = &layout.columns[..nc.min(layout.columns.len())]; let mut t = Table::new(id, nr, nc, 0, 0, 0.0); t.options.direction = if table_options.direction.as_deref() == Some("RightToLeftDirection") { designcraft_doc::TextDirection::RightToLeft @@ -100,12 +101,12 @@ impl<'r> Importer<'r> { designcraft_doc::TextDirection::LeftToRight }; for (r, re) in rows.iter().enumerate() { - let auto = re.boolean("AutoGrow").unwrap_or(true); + let auto = re.auto_grow().unwrap_or(true); t.rows[r].mode = if auto { RowHeightMode::AtLeast } else { RowHeightMode::Exactly }; - t.rows[r].height = if auto { re.num("MinimumHeight").unwrap_or(3.0) } else { re.num("SingleRowHeight").unwrap_or(12.0) }; + t.rows[r].height = if auto { re.minimum_height().unwrap_or(3.0) } else { re.single_row_height().unwrap_or(12.0) }; } for (c, ce) in cols.iter().enumerate() { - t.columns[c].width = ce.num("SingleColumnWidth").unwrap_or(72.0).max(3.0); + t.columns[c].width = ce.single_column_width().unwrap_or(72.0).max(3.0); } let h = table_options.header_rows.unwrap_or(0.0) as usize; let f = table_options.footer_rows.unwrap_or(0.0) as usize;