From 676714b6d26e0d93dc7d37d2fe24da39d73a1cfd Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 06:04:14 -0500 Subject: [PATCH] Parse IDML text wrap preferences --- crates/idml/src/model/mod.rs | 2 +- crates/idml/src/model/spread.rs | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/crates/idml/src/model/mod.rs b/crates/idml/src/model/mod.rs index 916dbcb90..419c4b70c 100644 --- a/crates/idml/src/model/mod.rs +++ b/crates/idml/src/model/mod.rs @@ -25,7 +25,7 @@ pub use resources::{ }; pub use spread::{ Graphic, GraphicChild, GraphicKind, Guide, ItemChild, ItemKind, Link, MarginPreference, Page, PageChild, PageItem, Spread, SpreadChild, TextPath, - spreads, + TextWrapPreference, spreads, }; pub use story::{ Ace, CONTAINERS, Cell, CellOptions, Container, ContainerKind, ContentPart, PageReference, Range, Story, StoryAnchor, StoryPreference, Table, diff --git a/crates/idml/src/model/spread.rs b/crates/idml/src/model/spread.rs index d38102b35..f0b1842da 100644 --- a/crates/idml/src/model/spread.rs +++ b/crates/idml/src/model/spread.rs @@ -460,6 +460,10 @@ impl PageItem { self.other("TextPath").map(|el| TextPath { values: Values::of(el) }) } + pub fn text_wrap(&self) -> Option { + self.other("TextWrapPreference").map(TextWrapPreference::from_el) + } + /// Replaces the outline. pub fn set_geometry(&mut self, g: &PathGeometry) { self.values.set_prop_el("PathGeometry", Some(g.to_el())); @@ -509,6 +513,46 @@ impl PageItem { } } +/// Parsed IDML `TextWrapPreference` values, including the nested offset and contour elements. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct TextWrapPreference { + values: Values, + contour_type: Option, + offsets: Option<[f64; 4]>, +} + +impl TextWrapPreference { + pub fn from_el(el: &El) -> Self { + let contour_type = el.child(Local("ContourOption")).and_then(|c| Values::of(c).get("ContourType").map(str::to_string)); + let offsets = el.child(Local("Properties")).and_then(|p| p.child(Local("TextWrapOffset"))).map(|o| { + let values = Values::of(o); + [ + values.num("Top").unwrap_or(0.0), + values.num("Left").unwrap_or(0.0), + values.num("Bottom").unwrap_or(0.0), + values.num("Right").unwrap_or(0.0), + ] + }); + Self { values: Values::of(el), contour_type, offsets } + } + + pub fn mode(&self) -> Option<&str> { + self.values.get("TextWrapMode") + } + pub fn inverse(&self) -> bool { + self.values.boolean("Inverse") == Some(true) + } + pub fn side(&self) -> Option<&str> { + self.values.get("TextWrapSide") + } + pub fn contour_type(&self) -> Option<&str> { + self.contour_type.as_deref() + } + pub fn offsets(&self) -> Option<[f64; 4]> { + self.offsets + } +} + /// Type-on-a-path settings. #[derive(Clone, Debug, PartialEq)] pub struct TextPath {