use std::collections::HashMap;
use oxml_layout::{
Diagnostic, Effect, GroupElement, MediaId, Paint, Path, Point, Rect, Stroke, Transform,
};
use rpptx_chart::CT_ChartSpace;
mod context;
mod font;
mod style;
mod text;
pub use context::{
BackgroundContent, BackgroundSource, EffectiveBackground, FlattenedItem, FlattenedSource,
ResolveCtx,
};
pub use style::{EffectiveShapeStyle, ResolveError};
pub use text::{EffectiveListStyle, EffectiveTextProperties};
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct ScopedMediaIds {
pub slide: HashMap<String, MediaId>,
pub layout: HashMap<String, MediaId>,
pub master: HashMap<String, MediaId>,
pub media_content_types: HashMap<MediaId, String>,
}
impl ScopedMediaIds {
pub fn get(&self, source: FlattenedSource, relationship_id: &str) -> Option<MediaId> {
match source {
FlattenedSource::Slide => &self.slide,
FlattenedSource::Layout => &self.layout,
FlattenedSource::Master => &self.master,
FlattenedSource::Background => return None,
}
.get(relationship_id)
.copied()
}
pub fn content_type(&self, source: FlattenedSource, relationship_id: &str) -> Option<&str> {
let media_id = self.get(source, relationship_id)?;
self.media_content_types.get(&media_id).map(String::as_str)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum ChartResource {
Parsed(Box<CT_ChartSpace>),
External(String),
MissingTarget(String),
Invalid(String),
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ScopedChartResources {
pub slide: HashMap<String, ChartResource>,
pub layout: HashMap<String, ChartResource>,
pub master: HashMap<String, ChartResource>,
}
impl ScopedChartResources {
pub fn get(&self, source: FlattenedSource, relationship_id: &str) -> Option<&ChartResource> {
match source {
FlattenedSource::Slide => &self.slide,
FlattenedSource::Layout => &self.layout,
FlattenedSource::Master => &self.master,
FlattenedSource::Background => return None,
}
.get(relationship_id)
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct ScopedHyperlinkTargets {
pub slide: HashMap<String, String>,
pub layout: HashMap<String, String>,
pub master: HashMap<String, String>,
}
impl ScopedHyperlinkTargets {
pub fn get(&self, source: FlattenedSource, relationship_id: &str) -> Option<&str> {
match source {
FlattenedSource::Slide => &self.slide,
FlattenedSource::Layout => &self.layout,
FlattenedSource::Master => &self.master,
FlattenedSource::Background => return None,
}
.get(relationship_id)
.map(String::as_str)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct ResolvedSlide {
pub size: (f64, f64),
pub background: Option<ResolvedBackground>,
pub shapes: Vec<ResolvedShape>,
pub diagnostics: Vec<Diagnostic>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ResolvedBackground {
Paint(Paint),
Image(ResolvedImage),
}
#[derive(Clone, Debug, PartialEq)]
pub struct ResolvedShape {
pub group_transform: Transform,
pub bounds: Rect,
pub rotation_deg: f64,
pub flip_h: bool,
pub flip_v: bool,
pub geometry: ResolvedGeometry,
pub fill: Option<Paint>,
pub image_fill: Option<ResolvedImage>,
pub line: Option<Stroke>,
pub head_end: Option<ResolvedLineEnd>,
pub tail_end: Option<ResolvedLineEnd>,
pub shadow: Option<Effect>,
pub content: ResolvedContent,
pub unsupported: Option<&'static str>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ResolvedLineEnd {
pub kind: ResolvedLineEndKind,
pub width: ResolvedLineEndSize,
pub length: ResolvedLineEndSize,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ResolvedLineEndKind {
Triangle,
Stealth,
Diamond,
Oval,
Arrow,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum ResolvedLineEndSize {
Small,
#[default]
Medium,
Large,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ResolvedGeometry {
Rectangle,
Custom {
paths: Vec<Path>,
text_rect: Option<Rect>,
},
BoundsFallback,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ResolvedContent {
None,
Text(ResolvedTextBody),
Image(ResolvedImage),
Table(ResolvedTable),
Group(GroupElement),
}
#[derive(Clone, Debug, PartialEq)]
pub struct ResolvedImage {
pub media: MediaId,
pub src_rect: Option<CropRect>,
pub placement: ResolvedImagePlacement,
pub dpi: Option<f64>,
pub rotate_with_shape: bool,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ResolvedImagePlacement {
Stretch { fill_rect: Option<CropRect> },
Tile(ResolvedTilePlacement),
}
impl Default for ResolvedImagePlacement {
fn default() -> Self {
Self::Stretch { fill_rect: None }
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ResolvedTilePlacement {
pub translation: Point,
pub scale_x: f64,
pub scale_y: f64,
pub flip: ResolvedTileFlip,
pub alignment: ResolvedRectAlignment,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum ResolvedTileFlip {
#[default]
None,
Horizontal,
Vertical,
Both,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum ResolvedRectAlignment {
#[default]
TopLeft,
Top,
TopRight,
Left,
Center,
Right,
BottomLeft,
Bottom,
BottomRight,
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct CropRect {
pub left: f64,
pub top: f64,
pub right: f64,
pub bottom: f64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ResolvedTextBody {
pub insets: TextInsets,
pub anchor: TextAnchor,
pub wrap: bool,
pub vertical: TextDirection,
pub space_first_last_paragraph: bool,
pub autofit: ResolvedAutofit,
pub paragraphs: Vec<ResolvedParagraph>,
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct TextInsets {
pub left: f64,
pub top: f64,
pub right: f64,
pub bottom: f64,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum TextAnchor {
#[default]
Top,
Center,
Bottom,
Justified,
Distributed,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum TextDirection {
#[default]
Horizontal,
Vertical,
Vertical270,
EastAsianVertical,
MongolianVertical,
WordArtVertical,
WordArtVerticalRtl,
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub enum ResolvedAutofit {
#[default]
None,
Shape,
Normal {
font_scale: Option<f64>,
line_spacing_reduction: Option<f64>,
},
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ResolvedParagraph {
pub level: u8,
pub left_margin: f64,
pub right_margin: f64,
pub indent: f64,
pub alignment: ParagraphAlignment,
pub line_spacing: Option<ResolvedTextSpacing>,
pub space_before: Option<ResolvedTextSpacing>,
pub space_after: Option<ResolvedTextSpacing>,
pub bullet: Option<ResolvedBullet>,
pub end_style: ResolvedRunStyle,
pub runs: Vec<ResolvedTextRun>,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum ParagraphAlignment {
#[default]
Left,
Center,
Right,
Justified,
Distributed,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ResolvedTextSpacing {
Percent(f64),
Points(f64),
}
#[derive(Clone, Debug, PartialEq)]
pub enum ResolvedBulletSize {
Percent(f64),
Points(f64),
}
#[derive(Clone, Debug, PartialEq)]
pub enum ResolvedBullet {
Character {
character: String,
font: Option<String>,
color: Option<oxml_layout::Color>,
size: Option<ResolvedBulletSize>,
},
AutoNumber {
scheme: String,
start_at: u32,
font: Option<String>,
color: Option<oxml_layout::Color>,
size: Option<ResolvedBulletSize>,
},
}
#[derive(Clone, Debug, PartialEq)]
pub enum ResolvedTextRun {
Text {
text: String,
style: ResolvedRunStyle,
},
Break,
Field {
text: String,
field_type: Option<String>,
style: ResolvedRunStyle,
},
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ResolvedRunStyle {
pub font_size: Option<f64>,
pub bold: bool,
pub italic: bool,
pub all_caps: bool,
pub underline: bool,
pub strike: bool,
pub spacing: Option<f64>,
pub baseline: Option<f64>,
pub fill: Option<Paint>,
pub latin_typeface: Option<String>,
pub east_asian_typeface: Option<String>,
pub complex_script_typeface: Option<String>,
pub symbol_typeface: Option<String>,
pub hyperlink_url: Option<String>,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ResolvedTable {
pub right_to_left: bool,
pub column_widths: Vec<f64>,
pub rows: Vec<ResolvedTableRow>,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ResolvedTableRow {
pub height: f64,
pub cells: Vec<ResolvedTableCell>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ResolvedTableCell {
pub text: Option<ResolvedTextBody>,
pub fill: Option<Paint>,
pub margins: TextInsets,
pub left: Option<ResolvedTableBorder>,
pub right: Option<ResolvedTableBorder>,
pub top: Option<ResolvedTableBorder>,
pub bottom: Option<ResolvedTableBorder>,
pub row_span: u32,
pub grid_span: u32,
pub horizontal_merge: bool,
pub vertical_merge: bool,
}
impl Default for ResolvedTableCell {
fn default() -> Self {
Self {
text: None,
fill: None,
margins: TextInsets::default(),
left: None,
right: None,
top: None,
bottom: None,
row_span: 1,
grid_span: 1,
horizontal_merge: false,
vertical_merge: false,
}
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ResolvedTableBorder {
pub stroke: Option<Stroke>,
pub priority: u8,
}