diff --git a/crates/idml/src/model/mod.rs b/crates/idml/src/model/mod.rs index 620dddb39..e3a002af6 100644 --- a/crates/idml/src/model/mod.rs +++ b/crates/idml/src/model/mod.rs @@ -23,7 +23,8 @@ pub use resources::{ SwatchKind, color_groups, inks, named, preference, stroke_styles, style_groups, swatches, }; pub use spread::{ - Graphic, GraphicChild, GraphicKind, Guide, ItemChild, ItemKind, Link, MarginPreference, Page, PageChild, PageItem, Spread, SpreadChild, spreads, + Graphic, GraphicChild, GraphicKind, Guide, ItemChild, ItemKind, Link, MarginPreference, Page, PageChild, PageItem, Spread, SpreadChild, TextPath, + spreads, }; pub use story::{Ace, CONTAINERS, Cell, Container, ContentPart, Range, Story, Table, TableChild, TextNode, stories}; @@ -106,6 +107,13 @@ impl Values { self.prop(key).and_then(|v| v.trim().parse::().ok()).filter(|v| v.is_finite()) } + /// A two-number value (for properties such as `GradientFillStart`), bounded to three tokens. + pub fn pair(&self, key: &str) -> Option<[f64; 2]> { + let source = self.prop(key)?; + let values: Vec = source.split_whitespace().take(3).filter_map(|v| v.parse::().ok()).collect(); + <[f64; 2]>::try_from(values).ok().filter(|v| v.iter().all(|n| n.is_finite())) + } + /// `true` or `false`; anything else counts as absent. pub fn boolean(&self, key: &str) -> Option { match self.prop(key)?.trim() { diff --git a/crates/idml/src/model/spread.rs b/crates/idml/src/model/spread.rs index c34ce14a5..d38102b35 100644 --- a/crates/idml/src/model/spread.rs +++ b/crates/idml/src/model/spread.rs @@ -437,6 +437,29 @@ impl PageItem { self.values.boolean("Nonprinting") == Some(true) } + pub fn gradient_fill_angle(&self) -> Option { + self.values.num("GradientFillAngle") + } + pub fn gradient_fill_start(&self) -> Option<[f64; 2]> { + self.values.pair("GradientFillStart") + } + pub fn gradient_fill_length(&self) -> Option { + self.values.num("GradientFillLength") + } + pub fn gradient_stroke_angle(&self) -> Option { + self.values.num("GradientStrokeAngle") + } + pub fn gradient_stroke_start(&self) -> Option<[f64; 2]> { + self.values.pair("GradientStrokeStart") + } + pub fn gradient_stroke_length(&self) -> Option { + self.values.num("GradientStrokeLength") + } + + pub fn text_path(&self) -> Option { + self.other("TextPath").map(|el| TextPath { values: Values::of(el) }) + } + /// Replaces the outline. pub fn set_geometry(&mut self, g: &PathGeometry) { self.values.set_prop_el("PathGeometry", Some(g.to_el())); @@ -486,6 +509,30 @@ impl PageItem { } } +/// Type-on-a-path settings. +#[derive(Clone, Debug, PartialEq)] +pub struct TextPath { + pub values: Values, +} + +impl TextPath { + pub fn parent_story(&self) -> Option<&str> { + self.values.get("ParentStory").filter(|s| *s != "n") + } + pub fn start_bracket(&self) -> Option { + self.values.num("StartBracket") + } + pub fn end_bracket(&self) -> Option { + self.values.num("EndBracket") + } + pub fn flipped(&self) -> bool { + self.values.get("FlipPathEffect") == Some("Flipped") + } + pub fn alignment(&self) -> Option<&str> { + self.values.get("TextAlignment") + } +} + /// What a placed graphic is. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum GraphicKind {