From 660173d9b7658ea6d277435bbea8ce96ff8b41d5 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 08:48:48 -0500 Subject: [PATCH] Parse IDML cell style values in shared model --- crates/idml/src/model/document.rs | 40 +++++++++++++++++++++++++++++++ crates/idml/src/model/mod.rs | 4 ++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/crates/idml/src/model/document.rs b/crates/idml/src/model/document.rs index ed3c2f5d1..bf29c45ed 100644 --- a/crates/idml/src/model/document.rs +++ b/crates/idml/src/model/document.rs @@ -199,6 +199,46 @@ pub struct NumberingListValues { pub continue_across_stories: bool, } +/// Parsed cell-style assignments that are independent of DesignCraft's style resolution. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct CellStyleValues { + pub self_id: Option, + pub name: Option, + pub based_on: Option, + pub fill: Option, + pub fill_tint: Option, + pub insets: [Option; 4], + pub vertical_justification: Option, + pub first_baseline: Option, + pub first_baseline_min: Option, + pub paragraph_style: Option, +} + +impl CellStyleValues { + /// Reads the cell-style value assignments and supports the older inset property names. + pub fn from_el(el: &El) -> Self { + let values = Values::of(el); + let inset = |modern, legacy| values.num(modern).or_else(|| values.num(legacy)).map(|v| v.max(0.0)); + Self { + self_id: values.self_id().map(str::to_owned), + name: values.name().map(str::to_owned), + based_on: values.prop("BasedOn"), + fill: values.prop("FillColor"), + fill_tint: values.num("FillTint"), + insets: [ + inset("TextTopInset", "TopInset"), + inset("TextLeftInset", "LeftInset"), + inset("TextBottomInset", "BottomInset"), + inset("TextRightInset", "RightInset"), + ], + vertical_justification: values.get("VerticalJustification").map(str::to_owned), + first_baseline: values.get("FirstBaselineOffset").map(str::to_owned), + first_baseline_min: values.num("MinimumFirstBaselineOffset").filter(|v| v.is_finite()).map(|v| v.clamp(0.0, 8640.0)), + paragraph_style: values.get("AppliedParagraphStyle").map(str::to_owned), + } + } +} + impl NumberingListValues { /// Reads a `NumberingList` element. pub fn from_el(el: &El) -> Self { diff --git a/crates/idml/src/model/mod.rs b/crates/idml/src/model/mod.rs index 19c23882f..d473e843c 100644 --- a/crates/idml/src/model/mod.rs +++ b/crates/idml/src/model/mod.rs @@ -22,8 +22,8 @@ mod story; use craft_xml::{El, Local, Node}; pub use document::{ - ConditionValues, CrossReferenceBuildingBlock, CrossReferenceFormatValues, EpubSplitValues, ModelDocument, NumberingListValues, TextDateKind, - TextVariableKind, TextVariableValues, TocStyleEntryValues, TocStyleValues, TopLevelKind, TopLevelNode, + CellStyleValues, ConditionValues, CrossReferenceBuildingBlock, CrossReferenceFormatValues, EpubSplitValues, ModelDocument, NumberingListValues, + TextDateKind, TextVariableKind, TextVariableValues, TocStyleEntryValues, TocStyleValues, TopLevelKind, TopLevelNode, }; pub use effects::{DirectionalFeatherValues, DropShadowValues, FeatherValues, GradientFeatherValues, OpacityStopValues, TransparencySetting}; pub use geometry::{MAX_PATH_POINTS, PathGeometry, PathGeometryError, PathPoint, SubPath};