From 2f6c85dcfeec0c73d9a625a260314e1816a4fef5 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 04:49:44 -0500 Subject: [PATCH] Model IDML page margin preferences --- crates/idml/src/model/mod.rs | 4 +++- crates/idml/src/model/spread.rs | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/crates/idml/src/model/mod.rs b/crates/idml/src/model/mod.rs index 33ba5a75c..620dddb39 100644 --- a/crates/idml/src/model/mod.rs +++ b/crates/idml/src/model/mod.rs @@ -22,7 +22,9 @@ pub use resources::{ ColorGroup, ColorSpace, GradientStop, GradientStopValue, Ink, StrokeStyle, StrokeStyleKind, Style, StyleGroup, StyleKind, StyleNode, Swatch, SwatchKind, color_groups, inks, named, preference, stroke_styles, style_groups, swatches, }; -pub use spread::{Graphic, GraphicChild, GraphicKind, Guide, ItemChild, ItemKind, Link, Page, PageChild, PageItem, Spread, SpreadChild, spreads}; +pub use spread::{ + Graphic, GraphicChild, GraphicKind, Guide, ItemChild, ItemKind, Link, MarginPreference, Page, PageChild, PageItem, Spread, SpreadChild, spreads, +}; pub use story::{Ace, CONTAINERS, Cell, Container, ContentPart, Range, Story, Table, TableChild, TextNode, stories}; use craft_xml::{El, Local, Node}; diff --git a/crates/idml/src/model/spread.rs b/crates/idml/src/model/spread.rs index eba967362..c941ed25f 100644 --- a/crates/idml/src/model/spread.rs +++ b/crates/idml/src/model/spread.rs @@ -146,6 +146,41 @@ pub struct Page { pub children: Vec, } +/// Parsed layout values of an IDML `MarginPreference`. +#[derive(Clone, Debug, PartialEq)] +pub struct MarginPreference { + pub values: Values, +} + +impl MarginPreference { + pub fn top(&self) -> Option { + self.values.num("Top") + } + pub fn left(&self) -> Option { + self.values.num("Left") + } + pub fn bottom(&self) -> Option { + self.values.num("Bottom") + } + pub fn right(&self) -> Option { + self.values.num("Right") + } + pub fn column_count(&self) -> Option { + self.values.num("ColumnCount") + } + pub fn column_gutter(&self) -> Option { + self.values.num("ColumnGutter") + } + + /// Parse at most `limit` whitespace-separated `ColumnsPositions` values; malformed or + /// non-finite values invalidate the list. + pub fn column_positions(&self, limit: usize) -> Option> { + let source = self.values.get("ColumnsPositions")?; + let values: Option> = source.split_whitespace().take(limit).map(|v| v.parse::().ok().filter(|v| v.is_finite())).collect(); + values.filter(|values| !values.is_empty()) + } +} + /// A child of a page, in document order. #[derive(Clone, Debug, PartialEq)] pub enum PageChild { @@ -215,6 +250,10 @@ impl Page { }) } + pub fn margin_settings(&self) -> Option { + self.margin_preference().map(|values| MarginPreference { values }) + } + pub fn guides(&self) -> impl DoubleEndedIterator { self.children.iter().filter_map(|c| if let PageChild::Guide(g) = c { Some(g) } else { None }) }