mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-14 22:35:26 +00:00
Read IDML page margins through shared model
This commit is contained in:
5 files changed
+42
-36
No files matched your search
Generated
+17
-17
@@ -1225,10 +1225,10 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-idml"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca#584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=11511e0d82a2f92ca4092eb02e8ef67cc85b42a5#11511e0d82a2f92ca4092eb02e8ef67cc85b42a5"
|
||||
dependencies = [
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca)",
|
||||
"craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=11511e0d82a2f92ca4092eb02e8ef67cc85b42a5)",
|
||||
"craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=11511e0d82a2f92ca4092eb02e8ef67cc85b42a5)",
|
||||
"thiserror 2.0.21",
|
||||
]
|
||||
|
||||
@@ -1566,6 +1566,15 @@ dependencies = [
|
||||
"thiserror 2.0.21",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "craft-xml"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=11511e0d82a2f92ca4092eb02e8ef67cc85b42a5#11511e0d82a2f92ca4092eb02e8ef67cc85b42a5"
|
||||
dependencies = [
|
||||
"quick-xml 0.41.0",
|
||||
"thiserror 2.0.21",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "craft-xml"
|
||||
version = "0.1.0"
|
||||
@@ -1584,15 +1593,6 @@ dependencies = [
|
||||
"thiserror 2.0.21",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "craft-xml"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca#584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca"
|
||||
dependencies = [
|
||||
"quick-xml 0.41.0",
|
||||
"thiserror 2.0.21",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "craft-xml"
|
||||
version = "0.1.0"
|
||||
@@ -1633,7 +1633,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-zip"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca#584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=11511e0d82a2f92ca4092eb02e8ef67cc85b42a5#11511e0d82a2f92ca4092eb02e8ef67cc85b42a5"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"thiserror 2.0.21",
|
||||
@@ -1914,7 +1914,7 @@ dependencies = [
|
||||
"craft-prepress",
|
||||
"craft-print",
|
||||
"craft-svg 0.1.0 (git+https://github.com/dylanmtaylor/craft-libs?rev=2e670cf9377b523112f3fe4b409399772c745895)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=11511e0d82a2f92ca4092eb02e8ef67cc85b42a5)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=f23b0f33f0d00b157476533a43cbbcfd901aa1f1)",
|
||||
"designcraft-color",
|
||||
"designcraft-compose",
|
||||
@@ -1998,8 +1998,8 @@ dependencies = [
|
||||
name = "designcraft-idml"
|
||||
version = "0.20.1"
|
||||
dependencies = [
|
||||
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca)",
|
||||
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=11511e0d82a2f92ca4092eb02e8ef67cc85b42a5)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=11511e0d82a2f92ca4092eb02e8ef67cc85b42a5)",
|
||||
"designcraft-color",
|
||||
"designcraft-compose",
|
||||
"designcraft-doc",
|
||||
@@ -2116,7 +2116,7 @@ version = "0.20.1"
|
||||
dependencies = [
|
||||
"craft-docx",
|
||||
"craft-file-formats",
|
||||
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca)",
|
||||
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=11511e0d82a2f92ca4092eb02e8ef67cc85b42a5)",
|
||||
"craft-rtf",
|
||||
"craft-wordmodel",
|
||||
"craft-xlsx",
|
||||
|
||||
+2
-2
@@ -16,10 +16,10 @@ craft-pdf = { git = "https://github.com/storytold/craft-libs", rev = "4052591363
|
||||
craft-document-bundle = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", 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 = "584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca", version = "=0.1.0" }
|
||||
craft-idml = { git = "https://github.com/storytold/craft-libs", rev = "11511e0d82a2f92ca4092eb02e8ef67cc85b42a5", 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/dylanmtaylor/craft-libs", rev = "2e670cf9377b523112f3fe4b409399772c745895", version = "=0.1.0", features = ["tree-render", "tree-text"] }
|
||||
craft-xml = { git = "https://github.com/storytold/craft-libs", rev = "584e00bf1f7e812e4fd204bc9b077c8a96e0d1ca", version = "=0.1.0" }
|
||||
craft-xml = { git = "https://github.com/storytold/craft-libs", rev = "11511e0d82a2f92ca4092eb02e8ef67cc85b42a5", 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" }
|
||||
|
||||
@@ -33,7 +33,7 @@ mod text_attrs;
|
||||
mod values;
|
||||
|
||||
use document::IndexTopic;
|
||||
use frame::margins_of;
|
||||
use frame::margins_of_el;
|
||||
use package::Package;
|
||||
#[cfg(test)]
|
||||
pub(crate) use package::{percent_decode, uri_to_path};
|
||||
@@ -349,7 +349,7 @@ impl<'r> Importer<'r> {
|
||||
}
|
||||
}
|
||||
"MarginPreference" => {
|
||||
let (m, c) = margins_of(e);
|
||||
let (m, c) = margins_of_el(e);
|
||||
self.default_margins = Some((m, c));
|
||||
}
|
||||
"ViewPreference" => {
|
||||
|
||||
@@ -17,31 +17,37 @@ pub(super) fn text_wrap(w: &El) -> TextWrap {
|
||||
tw
|
||||
}
|
||||
|
||||
pub(super) fn margins_of(m: &El) -> (Margins, Columns) {
|
||||
let g = |k: &str, d: f64| m.num(k).filter(|v| v.is_finite()).unwrap_or(d);
|
||||
let margins = Margins { top: g("Top", 36.0), bottom: g("Bottom", 36.0), inside: g("Left", 36.0), outside: g("Right", 36.0) };
|
||||
let count = g("ColumnCount", 1.0).clamp(1.0, f64::from(designcraft_doc::MAX_COLUMNS)) as u32;
|
||||
let gutter = g("ColumnGutter", 12.0);
|
||||
let positions = m.get("ColumnsPositions").and_then(|s| custom_columns(s, count, gutter));
|
||||
pub(super) fn margins_of(m: &craft_idml::model::MarginPreference) -> (Margins, Columns) {
|
||||
let margins = Margins {
|
||||
top: m.top().unwrap_or(36.0),
|
||||
bottom: m.bottom().unwrap_or(36.0),
|
||||
inside: m.left().unwrap_or(36.0),
|
||||
outside: m.right().unwrap_or(36.0),
|
||||
};
|
||||
let count = m.column_count().unwrap_or(1.0).clamp(1.0, f64::from(designcraft_doc::MAX_COLUMNS)) as u32;
|
||||
let gutter = m.column_gutter().unwrap_or(12.0);
|
||||
let positions = m.column_positions(2 * count as usize + 1).and_then(|pos| custom_columns(&pos, count, gutter));
|
||||
(margins, Columns { count, gutter, positions })
|
||||
}
|
||||
|
||||
pub(super) fn margins_of_el(m: &El) -> (Margins, Columns) {
|
||||
margins_of(&craft_idml::model::MarginPreference::from_el(&crate::xml::to_craft(m)))
|
||||
}
|
||||
|
||||
/// `ColumnsPositions` when the column guides have been dragged off the even split: `2 × count`
|
||||
/// offsets from the margin box's left edge, valid as [`designcraft_doc::valid_column_positions`]
|
||||
/// over the box they span. InDesign writes the attribute whether or not they have been moved, so
|
||||
/// an even set is dropped: `positions` means "custom", and keeping an even copy would freeze the
|
||||
/// columns against a later change of count or gutter. Anything malformed is the even split; at
|
||||
/// most one number past `2 × count` is parsed, so a long list costs nothing.
|
||||
fn custom_columns(s: &str, count: u32, gutter: f64) -> Option<Vec<f64>> {
|
||||
let want = 2 * count as usize;
|
||||
let pos = s.split_whitespace().take(want + 1).map(|v| v.parse::<f64>().ok()).collect::<Option<Vec<f64>>>()?;
|
||||
fn custom_columns(pos: &[f64], count: u32, gutter: f64) -> Option<Vec<f64>> {
|
||||
let width = *pos.last()?;
|
||||
if !designcraft_doc::valid_column_positions(&pos, count, width) {
|
||||
if !designcraft_doc::valid_column_positions(pos, count, width) {
|
||||
return None;
|
||||
}
|
||||
let even = Columns { count, gutter, positions: None }.edges(width);
|
||||
// The tolerance only absorbs float noise in InDesign's arithmetic; a dragged guide moves far more.
|
||||
pos.iter().zip(&even).any(|(a, b)| (a - b).abs() > 1e-4).then_some(pos)
|
||||
pos.iter().zip(&even).any(|(a, b)| (a - b).abs() > 1e-4).then(|| pos.to_vec())
|
||||
}
|
||||
|
||||
/// `columns` with custom positions only when they fit the margin box of a `page_width`-wide page
|
||||
@@ -351,7 +357,7 @@ mod page_column_import_safety_tests {
|
||||
.attr("Bottom", "-inf")
|
||||
.attr("Left", "NaN")
|
||||
.attr("Right", "1e309");
|
||||
let (margins, columns) = margins_of(&m);
|
||||
let (margins, columns) = margins_of_el(&m);
|
||||
assert_eq!(columns.count, expected);
|
||||
assert_eq!(columns.gutter, 12.);
|
||||
assert_eq!(margins, Margins::uniform(36.));
|
||||
@@ -364,7 +370,7 @@ mod page_column_import_safety_tests {
|
||||
fn hostile_column_positions_fall_back_to_the_even_split() {
|
||||
let positions = |count: &str, raw: &str| {
|
||||
let m = El::new("MarginPreference").attr("ColumnCount", count).attr("ColumnGutter", "20").attr("ColumnsPositions", raw);
|
||||
margins_of(&m).1.positions
|
||||
margins_of_el(&m).1.positions
|
||||
};
|
||||
assert_eq!(positions("2", "0 150 170 450"), Some(vec![0., 150., 170., 450.]));
|
||||
let huge = (0..10_000).map(|i| i.to_string()).collect::<Vec<_>>().join(" ");
|
||||
@@ -391,7 +397,7 @@ mod page_column_import_safety_tests {
|
||||
// makes them custom.
|
||||
let gapless = |raw: &str| {
|
||||
let m = El::new("MarginPreference").attr("ColumnCount", "216").attr("ColumnGutter", "0").attr("ColumnsPositions", raw);
|
||||
margins_of(&m).1.positions
|
||||
margins_of_el(&m).1.positions
|
||||
};
|
||||
let edges = |first_right: &str| {
|
||||
(0..432).map(|i| if i == 1 { first_right.to_string() } else { ((i + 1) / 2).to_string() }).collect::<Vec<_>>().join(" ")
|
||||
|
||||
@@ -66,7 +66,7 @@ impl<'r> Importer<'r> {
|
||||
.and_then(|sp| sp.pages.get(sp.parent_page_at(side, index)?))
|
||||
.map(|q| (q.margins, q.columns.clone()))
|
||||
};
|
||||
let preference = p.margin_preference().map(|v| crate::xml::from_craft(v.element("MarginPreference")));
|
||||
let preference = p.margin_settings();
|
||||
let (margins, columns) = match (preference.as_ref(), &from_parent) {
|
||||
(Some(m), _) => {
|
||||
let (margins, columns) = margins_of(m);
|
||||
|
||||
Reference in new issue
Block a user