1use std::collections::HashMap;
4
5use oxml_chart::CT_ChartSpace;
6use oxml_layout::{
7 Diagnostic, Effect, GroupElement, MediaId, Paint, Path, Point, Rect, Stroke, Transform,
8};
9
10mod context;
11mod font;
12mod style;
13mod text;
14pub mod timeline;
15
16pub use context::{
17 BackgroundContent, BackgroundSource, EffectiveBackground, FlattenedItem, FlattenedSource,
18 ResolveCtx,
19};
20pub use style::{EffectiveShapeStyle, ResolveError};
21pub use text::{EffectiveListStyle, EffectiveTextProperties};
22
23#[derive(Clone, Debug, Default, Eq, PartialEq)]
25pub struct ScopedMediaIds {
26 pub slide: HashMap<String, MediaId>,
27 pub layout: HashMap<String, MediaId>,
28 pub master: HashMap<String, MediaId>,
29 pub media_content_types: HashMap<MediaId, String>,
31}
32
33impl ScopedMediaIds {
34 pub fn get(&self, source: FlattenedSource, relationship_id: &str) -> Option<MediaId> {
36 match source {
37 FlattenedSource::Slide => &self.slide,
38 FlattenedSource::Layout => &self.layout,
39 FlattenedSource::Master => &self.master,
40 FlattenedSource::Background => return None,
41 }
42 .get(relationship_id)
43 .copied()
44 }
45
46 pub fn content_type(&self, source: FlattenedSource, relationship_id: &str) -> Option<&str> {
48 let media_id = self.get(source, relationship_id)?;
49 self.media_content_types.get(&media_id).map(String::as_str)
50 }
51}
52
53#[derive(Clone, Debug, PartialEq)]
55pub enum ChartResource {
56 Parsed(Box<CT_ChartSpace>),
57 External(String),
58 MissingTarget(String),
59 Invalid(String),
60}
61
62#[derive(Clone, Debug, Default, PartialEq)]
64pub struct ScopedChartResources {
65 pub slide: HashMap<String, ChartResource>,
66 pub layout: HashMap<String, ChartResource>,
67 pub master: HashMap<String, ChartResource>,
68}
69
70impl ScopedChartResources {
71 pub fn get(&self, source: FlattenedSource, relationship_id: &str) -> Option<&ChartResource> {
73 match source {
74 FlattenedSource::Slide => &self.slide,
75 FlattenedSource::Layout => &self.layout,
76 FlattenedSource::Master => &self.master,
77 FlattenedSource::Background => return None,
78 }
79 .get(relationship_id)
80 }
81}
82
83#[derive(Clone, Debug, Default, Eq, PartialEq)]
85pub struct ScopedHyperlinkTargets {
86 pub slide: HashMap<String, String>,
87 pub layout: HashMap<String, String>,
88 pub master: HashMap<String, String>,
89}
90
91impl ScopedHyperlinkTargets {
92 pub fn get(&self, source: FlattenedSource, relationship_id: &str) -> Option<&str> {
94 match source {
95 FlattenedSource::Slide => &self.slide,
96 FlattenedSource::Layout => &self.layout,
97 FlattenedSource::Master => &self.master,
98 FlattenedSource::Background => return None,
99 }
100 .get(relationship_id)
101 .map(String::as_str)
102 }
103}
104
105#[derive(Clone, Debug, PartialEq)]
107pub struct ResolvedSlide {
108 pub size: (f64, f64),
110 pub background: Option<ResolvedBackground>,
111 pub shapes: Vec<ResolvedShape>,
113 pub diagnostics: Vec<Diagnostic>,
114}
115
116pub type ResolvedSlideTextDirections = Vec<Vec<Vec<oxml_layout::TextDirection>>>;
118
119#[derive(Clone, Debug, PartialEq)]
121pub enum ResolvedBackground {
122 Paint(Paint),
123 Image(ResolvedImage),
124}
125
126#[derive(Clone, Debug, PartialEq)]
128pub struct ResolvedShape {
129 pub group_transform: Transform,
131 pub bounds: Rect,
132 pub rotation_deg: f64,
133 pub flip_h: bool,
134 pub flip_v: bool,
135 pub geometry: ResolvedGeometry,
136 pub fill: Option<Paint>,
137 pub image_fill: Option<ResolvedImage>,
138 pub line: Option<Stroke>,
139 pub head_end: Option<ResolvedLineEnd>,
140 pub tail_end: Option<ResolvedLineEnd>,
141 pub shadow: Option<Effect>,
142 pub content: ResolvedContent,
143 pub unsupported: Option<&'static str>,
145}
146
147#[derive(Clone, Copy, Debug, Eq, PartialEq)]
149pub struct ResolvedLineEnd {
150 pub kind: ResolvedLineEndKind,
151 pub width: ResolvedLineEndSize,
152 pub length: ResolvedLineEndSize,
153}
154
155#[derive(Clone, Copy, Debug, Eq, PartialEq)]
157pub enum ResolvedLineEndKind {
158 Triangle,
159 Stealth,
160 Diamond,
161 Oval,
162 Arrow,
163}
164
165#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
167pub enum ResolvedLineEndSize {
168 Small,
169 #[default]
170 Medium,
171 Large,
172}
173
174#[derive(Clone, Debug, PartialEq)]
176pub enum ResolvedGeometry {
177 Rectangle,
178 Custom {
179 paths: Vec<Path>,
180 text_rect: Option<Rect>,
181 },
182 BoundsFallback,
183}
184
185#[derive(Clone, Debug, PartialEq)]
187pub enum ResolvedContent {
188 None,
189 Text(ResolvedTextBody),
190 Image(ResolvedImage),
191 Table(ResolvedTable),
192 Group(GroupElement),
193}
194
195#[derive(Clone, Debug, PartialEq)]
197pub struct ResolvedImage {
198 pub media: MediaId,
199 pub src_rect: Option<CropRect>,
200 pub placement: ResolvedImagePlacement,
201 pub dpi: Option<f64>,
202 pub rotate_with_shape: bool,
203}
204
205#[derive(Clone, Debug, PartialEq)]
207pub enum ResolvedImagePlacement {
208 Stretch { fill_rect: Option<CropRect> },
209 Tile(ResolvedTilePlacement),
210}
211
212impl Default for ResolvedImagePlacement {
213 fn default() -> Self {
214 Self::Stretch { fill_rect: None }
215 }
216}
217
218#[derive(Clone, Copy, Debug, PartialEq)]
220pub struct ResolvedTilePlacement {
221 pub translation: Point,
222 pub scale_x: f64,
223 pub scale_y: f64,
224 pub flip: ResolvedTileFlip,
225 pub alignment: ResolvedRectAlignment,
226}
227
228#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
230pub enum ResolvedTileFlip {
231 #[default]
232 None,
233 Horizontal,
234 Vertical,
235 Both,
236}
237
238#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
240pub enum ResolvedRectAlignment {
241 #[default]
242 TopLeft,
243 Top,
244 TopRight,
245 Left,
246 Center,
247 Right,
248 BottomLeft,
249 Bottom,
250 BottomRight,
251}
252
253#[derive(Clone, Copy, Debug, Default, PartialEq)]
255pub struct CropRect {
256 pub left: f64,
257 pub top: f64,
258 pub right: f64,
259 pub bottom: f64,
260}
261
262#[derive(Clone, Debug, PartialEq)]
264pub struct ResolvedTextBody {
265 pub insets: TextInsets,
266 pub anchor: TextAnchor,
267 pub wrap: bool,
268 pub vertical: TextDirection,
269 pub space_first_last_paragraph: bool,
270 pub autofit: ResolvedAutofit,
271 pub paragraphs: Vec<ResolvedParagraph>,
272}
273
274#[derive(Clone, Copy, Debug, Default, PartialEq)]
276pub struct TextInsets {
277 pub left: f64,
278 pub top: f64,
279 pub right: f64,
280 pub bottom: f64,
281}
282
283#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
284pub enum TextAnchor {
285 #[default]
286 Top,
287 Center,
288 Bottom,
289 Justified,
290 Distributed,
291}
292
293#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
294pub enum TextDirection {
295 #[default]
296 Horizontal,
297 Vertical,
298 Vertical270,
299 EastAsianVertical,
300 MongolianVertical,
301 WordArtVertical,
302 WordArtVerticalRtl,
303}
304
305#[derive(Clone, Copy, Debug, Default, PartialEq)]
306pub enum ResolvedAutofit {
307 #[default]
308 None,
309 Shape,
310 Normal {
311 font_scale: Option<f64>,
312 line_spacing_reduction: Option<f64>,
313 },
314}
315
316#[derive(Clone, Debug, Default, PartialEq)]
318pub struct ResolvedParagraph {
319 pub level: u8,
320 pub left_margin: f64,
321 pub right_margin: f64,
322 pub indent: f64,
323 pub alignment: ParagraphAlignment,
324 pub line_spacing: Option<ResolvedTextSpacing>,
325 pub space_before: Option<ResolvedTextSpacing>,
326 pub space_after: Option<ResolvedTextSpacing>,
327 pub bullet: Option<ResolvedBullet>,
328 pub end_style: ResolvedRunStyle,
329 pub runs: Vec<ResolvedTextRun>,
330}
331
332#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
333pub enum ParagraphAlignment {
334 #[default]
335 Left,
336 Center,
337 Right,
338 Justified,
339 Distributed,
340}
341
342#[derive(Clone, Debug, PartialEq)]
344pub enum ResolvedTextSpacing {
345 Percent(f64),
346 Points(f64),
347}
348
349#[derive(Clone, Debug, PartialEq)]
351pub enum ResolvedBulletSize {
352 Percent(f64),
353 Points(f64),
354}
355
356#[derive(Clone, Debug, PartialEq)]
357pub enum ResolvedBullet {
358 Character {
359 character: String,
360 font: Option<String>,
361 color: Option<oxml_layout::Color>,
362 size: Option<ResolvedBulletSize>,
363 },
364 AutoNumber {
365 scheme: String,
366 start_at: u32,
367 font: Option<String>,
368 color: Option<oxml_layout::Color>,
369 size: Option<ResolvedBulletSize>,
370 },
371}
372
373#[derive(Clone, Debug, PartialEq)]
375pub enum ResolvedTextRun {
376 Text {
377 text: String,
378 style: ResolvedRunStyle,
379 },
380 Break,
381 Field {
382 text: String,
383 field_type: Option<String>,
384 style: ResolvedRunStyle,
385 },
386}
387
388#[derive(Clone, Debug, Default, PartialEq)]
390pub struct ResolvedRunStyle {
391 pub font_size: Option<f64>,
392 pub bold: bool,
393 pub italic: bool,
394 pub all_caps: bool,
395 pub underline: bool,
396 pub strike: bool,
397 pub spacing: Option<f64>,
398 pub baseline: Option<f64>,
399 pub fill: Option<Paint>,
400 pub latin_typeface: Option<String>,
401 pub east_asian_typeface: Option<String>,
402 pub complex_script_typeface: Option<String>,
403 pub symbol_typeface: Option<String>,
404 pub hyperlink_url: Option<String>,
406}
407
408#[derive(Clone, Debug, Default, PartialEq)]
410pub struct ResolvedTable {
411 pub right_to_left: bool,
412 pub column_widths: Vec<f64>,
413 pub rows: Vec<ResolvedTableRow>,
414}
415
416#[derive(Clone, Debug, Default, PartialEq)]
417pub struct ResolvedTableRow {
418 pub height: f64,
419 pub cells: Vec<ResolvedTableCell>,
420}
421
422#[derive(Clone, Debug, PartialEq)]
423pub struct ResolvedTableCell {
424 pub text: Option<ResolvedTextBody>,
425 pub fill: Option<Paint>,
426 pub margins: TextInsets,
427 pub left: Option<ResolvedTableBorder>,
428 pub right: Option<ResolvedTableBorder>,
429 pub top: Option<ResolvedTableBorder>,
430 pub bottom: Option<ResolvedTableBorder>,
431 pub row_span: u32,
432 pub grid_span: u32,
433 pub horizontal_merge: bool,
434 pub vertical_merge: bool,
435}
436
437impl Default for ResolvedTableCell {
438 fn default() -> Self {
439 Self {
440 text: None,
441 fill: None,
442 margins: TextInsets::default(),
443 left: None,
444 right: None,
445 top: None,
446 bottom: None,
447 row_span: 1,
448 grid_span: 1,
449 horizontal_merge: false,
450 vertical_merge: false,
451 }
452 }
453}
454
455#[derive(Clone, Debug, Default, PartialEq)]
457pub struct ResolvedTableBorder {
458 pub stroke: Option<Stroke>,
459 pub priority: u8,
460}