From 3696a3473e2fa5706e657caaea4f646c628c1909 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 09:00:17 -0500 Subject: [PATCH] Parse IDML anchored object settings in shared model --- crates/idml/src/model/mod.rs | 5 ++-- crates/idml/src/model/story.rs | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/crates/idml/src/model/mod.rs b/crates/idml/src/model/mod.rs index f16ceb15d..d9a15d85b 100644 --- a/crates/idml/src/model/mod.rs +++ b/crates/idml/src/model/mod.rs @@ -45,8 +45,9 @@ pub use spread::{ TextWrapPreference, spreads, }; pub use story::{ - Ace, CONTAINERS, Cell, CellOptions, Container, ContainerKind, ContentPart, PageReference, Range, SavedCrossReference, SavedCrossReferencePart, - Story, StoryAnchor, StoryPreference, Table, TableChild, TableColumn, TableLayout, TableRow, TextNode, TrackedChangeKind, stories, + Ace, AnchoredObjectValues, CONTAINERS, Cell, CellOptions, Container, ContainerKind, ContentPart, PageReference, Range, SavedCrossReference, + SavedCrossReferencePart, Story, StoryAnchor, StoryPreference, Table, TableChild, TableColumn, TableLayout, TableRow, TextNode, TrackedChangeKind, + stories, }; use crate::value::{matrix, nums}; diff --git a/crates/idml/src/model/story.rs b/crates/idml/src/model/story.rs index 7d133d343..ffe0ef17d 100644 --- a/crates/idml/src/model/story.rs +++ b/crates/idml/src/model/story.rs @@ -5,6 +5,49 @@ use craft_xml::{El, Local, Node}; use super::{PageItem, Values, tidy}; +/// Resolved IDML anchored-object options from an item and its inherited style levels. +#[derive(Clone, Debug, PartialEq)] +pub struct AnchoredObjectValues { + pub position: String, + pub anchor_point: String, + pub horizontal_alignment: String, + pub horizontal_reference: String, + pub vertical_alignment: String, + pub vertical_reference: String, + pub pin_position: bool, + pub spine_relative: bool, + pub space_above: f64, + pub x_offset: f64, + pub y_offset: f64, +} + +impl AnchoredObjectValues { + /// Resolves attributes item-first from `AnchoredObjectSetting` children. + pub fn from_elements(elements: &[&El]) -> Self { + let get = |key: &str, default: &str| { + elements + .iter() + .filter_map(|element| element.child(Local("AnchoredObjectSetting"))) + .find_map(|setting| Values::of(setting).get(key).map(str::to_owned)) + .unwrap_or_else(|| default.to_owned()) + }; + let number = |key: &str| get(key, "0").parse::().ok().filter(|value| value.is_finite()).unwrap_or(0.0); + Self { + position: get("AnchoredPosition", "InlinePosition"), + anchor_point: get("AnchorPoint", "BottomRightAnchor"), + horizontal_alignment: get("HorizontalAlignment", "LeftAlign"), + horizontal_reference: get("HorizontalReferencePoint", "TextFrame"), + vertical_alignment: get("VerticalAlignment", "BottomAlign"), + vertical_reference: get("VerticalReferencePoint", "LineBaseline"), + pin_position: get("PinPosition", "true") == "true", + spine_relative: get("SpineRelative", "false") == "true", + space_above: number("AnchorSpaceAbove"), + x_offset: number("AnchorXoffset"), + y_offset: number("AnchorYoffset"), + } + } +} + /// A `Story`. #[derive(Clone, Debug, Default, PartialEq)] pub struct Story {