From 91a6abf7b7f45bf49dae73b243047027d8560c31 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 07:50:43 -0500 Subject: [PATCH] Write paragraph alignment through shared IDML model --- crates/idml/src/model/mod.rs | 6 +-- crates/idml/src/model/resources.rs | 68 ++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/crates/idml/src/model/mod.rs b/crates/idml/src/model/mod.rs index 924a9fbe6..6dc2f8ec6 100644 --- a/crates/idml/src/model/mod.rs +++ b/crates/idml/src/model/mod.rs @@ -29,9 +29,9 @@ pub use resources::{ CjkCharacterValues, ColorDefinition, ColorGroup, ColorGroupDefinition, ColorGroupMember, ColorSpace, CompositeFontDefinition, CompositeFontEntryDefinition, EpubExportTagMap, FontDefinition, FontFamilyDefinition, FontsPart, GradientDefinition, GradientStop, GradientStopDefinition, GradientStopValue, GraphicPart, GrepStyleValue, Ink, InkDefinition, MojikumiRow, NestedLineStyleValue, NestedStyleValue, - NestedStyleValues, OpenTypeFeatureValues, ParagraphBoxValues, ParagraphListValues, StrokeDefinition, StrokeStyle, StrokeStyleKind, Style, - StyleGroup, StyleGroupWriter, StyleKind, StyleNode, Swatch, SwatchKind, TabStopValues, TintDefinition, color_groups, inks, named, preference, - stroke_styles, style_groups, swatches, + NestedStyleValues, OpenTypeFeatureValues, ParagraphAlignmentValues, ParagraphBoxValues, ParagraphListValues, StrokeDefinition, StrokeStyle, + StrokeStyleKind, Style, StyleGroup, StyleGroupWriter, StyleKind, StyleNode, Swatch, SwatchKind, TabStopValues, TintDefinition, color_groups, + inks, named, preference, stroke_styles, style_groups, swatches, }; pub use spread::{ ClippingPathValues, Graphic, GraphicChild, GraphicKind, GraphicLayerOptions, Guide, ItemChild, ItemKind, Link, MarginPreference, Page, PageChild, diff --git a/crates/idml/src/model/resources.rs b/crates/idml/src/model/resources.rs index f89f35f67..b589a6c0d 100644 --- a/crates/idml/src/model/resources.rs +++ b/crates/idml/src/model/resources.rs @@ -67,6 +67,74 @@ pub struct ParagraphBoxValues { pub shading_corners: Option<[(String, f64); 4]>, } +/// Paragraph alignment, spacing, drop cap, baseline grid and composer values after the caller +/// maps application semantics to IDML enumerations. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct ParagraphAlignmentValues { + pub justification: Option, + pub direction: Option, + pub kashidas: Option, + pub paragraph_justification: Option, + pub paragraph_kashida_width: Option, + pub left_indent: Option, + pub right_indent: Option, + pub first_line_indent: Option, + pub last_line_indent: Option, + pub space_before: Option, + pub space_after: Option, + pub same_para_style_spacing: Option>, + pub drop_cap_lines: Option, + pub drop_cap_chars: Option, + pub dropcap_detail: Option, + pub grid_alignment: Option, + pub grid_align_first_line_only: Option, + pub composer: Option, +} + +impl ParagraphAlignmentValues { + /// Writes the IDML attributes for paragraph alignment and spacing. + pub fn to_attrs(&self) -> Vec<(String, String)> { + let mut attrs = Vec::new(); + for (key, value) in [ + ("Justification", &self.justification), + ("ParagraphDirection", &self.direction), + ("Kashidas", &self.kashidas), + ("ParagraphJustification", &self.paragraph_justification), + ("GridAlignment", &self.grid_alignment), + ("Composer", &self.composer), + ] { + if let Some(value) = value { + attrs.push((key.to_string(), value.clone())); + } + } + for (key, value) in [ + ("ParagraphKashidaWidth", self.paragraph_kashida_width), + ("LeftIndent", self.left_indent), + ("RightIndent", self.right_indent), + ("FirstLineIndent", self.first_line_indent), + ("LastLineIndent", self.last_line_indent), + ("SpaceBefore", self.space_before), + ("SpaceAfter", self.space_after), + ("DropCapLines", self.drop_cap_lines), + ("DropCapCharacters", self.drop_cap_chars), + ] { + if let Some(value) = value { + attrs.push((key.to_string(), crate::value::num(value))); + } + } + if let Some(value) = self.same_para_style_spacing { + attrs.push(("SameParaStyleSpacing".to_string(), value.map(crate::value::num).unwrap_or_else(|| "Nothing".to_string()))); + } + if let Some(value) = self.dropcap_detail { + attrs.push(("DropcapDetail".to_string(), value.to_string())); + } + if let Some(value) = self.grid_align_first_line_only { + attrs.push(("GridAlignFirstLineOnly".to_string(), if value { "true" } else { "false" }.to_string())); + } + attrs + } +} + impl ParagraphBoxValues { /// Writes IDML attributes and properties for paragraph borders and shading. pub fn to_parts(&self) -> (Vec<(String, String)>, Vec) {