1use std::ops::Index;
2
3use elements::rotate::Rotation;
4
5use crate::{
6 elements::{h_align::HorizontalAlignment, row::Flex, text::TextAlign},
7 *,
8};
9
10use super::{Font, SerdeElement, SerdeElementElement};
11
12const fn default_false() -> bool {
13 false
14}
15
16const fn default_0u8() -> u8 {
17 0
18}
19
20#[derive(Clone, Serialize, Deserialize)]
21pub enum SerdeLinkTarget {
22 Uri(String),
23}
24
25impl SerdeLinkTarget {
26 pub fn as_link_target(&self) -> LinkTarget<'_> {
27 match self {
28 SerdeLinkTarget::Uri(uri) => LinkTarget::Uri(uri),
29 }
30 }
31}
32
33#[derive(Clone, Serialize, Deserialize)]
34pub struct None;
35
36impl SerdeElement for None {
37 fn element(
38 &self,
39 _: &impl for<'a> Index<&'a str, Output = Font>,
40 _: impl CompositeElementCallback,
41 ) {
42 }
43}
44
45#[derive(Clone, Serialize, Deserialize)]
46pub struct Empty;
47
48impl SerdeElement for Empty {
49 fn element(
50 &self,
51 _: &impl for<'a> Index<&'a str, Output = Font>,
52 callback: impl CompositeElementCallback,
53 ) {
54 callback.call(&elements::empty::Empty);
55 }
56}
57
58#[derive(Clone, Serialize, Deserialize)]
59pub struct Debug<E> {
60 pub element: Box<E>,
61
62 #[serde(default = "default_0u8")]
63 pub color: u8,
64
65 #[serde(default = "default_false")]
66 pub show_max_width: bool,
67
68 #[serde(default = "default_false")]
69 pub show_last_location_max_height: bool,
70}
71
72impl<E: SerdeElement> SerdeElement for Debug<E> {
73 fn element(
74 &self,
75 fonts: &impl for<'a> Index<&'a str, Output = Font>,
76 callback: impl CompositeElementCallback,
77 ) {
78 callback.call(&elements::debug::Debug {
79 element: SerdeElementElement {
80 element: &*self.element,
81 fonts,
82 },
83 color: self.color,
84 show_max_width: self.show_max_width,
85 show_last_location_max_height: self.show_last_location_max_height,
86 });
87 }
88}
89
90#[derive(Clone, Serialize, Deserialize)]
91pub struct Text {
92 pub text: String,
93 pub font: String,
94 pub size: f32,
95 pub color: u32,
96 pub underline: bool,
97 pub extra_character_spacing: f32,
98 pub extra_word_spacing: f32,
99 pub extra_line_height: f32,
100 pub align: TextAlign,
101 #[serde(default)]
103 pub link: Option<SerdeLinkTarget>,
104}
105
106impl SerdeElement for Text {
107 fn element(
108 &self,
109 fonts: &impl for<'a> Index<&'a str, Output = Font>,
110 callback: impl CompositeElementCallback,
111 ) {
112 callback.call(&elements::text::Text {
113 text: &self.text,
114 font: &*fonts[&self.font],
115 size: self.size,
116 color: self.color,
117 underline: self.underline,
118 extra_character_spacing: self.extra_character_spacing,
119 extra_word_spacing: self.extra_word_spacing,
120 extra_line_height: self.extra_line_height,
121 align: self.align,
122 link: self.link.as_ref().map(SerdeLinkTarget::as_link_target),
123 });
124 }
125}
126
127#[derive(Clone, Serialize, Deserialize)]
128pub struct RichTextSpan {
129 pub text: String,
131 pub font: String,
133 pub size: f32,
135 pub color: u32,
137 pub underline: bool,
139 pub extra_character_spacing: f32,
141 pub extra_word_spacing: f32,
143 pub extra_line_height: f32,
145 #[serde(default)]
147 pub link: Option<SerdeLinkTarget>,
148}
149
150#[derive(Clone, Serialize, Deserialize)]
151pub struct RichText {
152 pub spans: Vec<RichTextSpan>,
153 pub align: TextAlign,
154}
155
156impl SerdeElement for RichText {
157 fn element(
158 &self,
159 fonts: &impl for<'a> Index<&'a str, Output = Font>,
160 callback: impl CompositeElementCallback,
161 ) {
162 callback.call(&elements::rich_text::RichText {
163 spans: self.spans.iter().map(|s| elements::rich_text::Span {
164 text: &s.text,
165 font: &*fonts[&s.font],
166 size: s.size,
167 color: s.color,
168 underline: s.underline,
169 extra_character_spacing: s.extra_character_spacing,
170 extra_word_spacing: s.extra_word_spacing,
171 extra_line_height: s.extra_line_height,
172 link: s.link.as_ref().map(SerdeLinkTarget::as_link_target),
173 }),
174 align: self.align,
175 });
176 }
177}
178
179#[derive(Clone, Serialize, Deserialize)]
180pub struct VGap {
181 pub gap: f32,
182}
183
184impl SerdeElement for VGap {
185 fn element(
186 &self,
187 _: &impl for<'a> Index<&'a str, Output = Font>,
188 callback: impl CompositeElementCallback,
189 ) {
190 callback.call(&elements::v_gap::VGap(self.gap));
191 }
192}
193
194#[derive(Clone, Serialize, Deserialize)]
195pub struct HAlign<E> {
196 pub alignment: HorizontalAlignment,
197 pub element: Box<E>,
198}
199
200impl<E: SerdeElement> SerdeElement for HAlign<E> {
201 fn element(
202 &self,
203 fonts: &impl for<'a> Index<&'a str, Output = Font>,
204 callback: impl CompositeElementCallback,
205 ) {
206 callback.call(&elements::h_align::HAlign(
207 self.alignment,
208 SerdeElementElement {
209 element: &*self.element,
210 fonts,
211 },
212 ));
213 }
214}
215
216#[derive(Clone, Serialize, Deserialize)]
217pub struct Padding<E> {
218 pub left: f32,
219 pub right: f32,
220 pub top: f32,
221 pub bottom: f32,
222 pub element: Box<E>,
223}
224
225impl<E: SerdeElement> SerdeElement for Padding<E> {
226 fn element(
227 &self,
228 fonts: &impl for<'a> Index<&'a str, Output = Font>,
229 callback: impl CompositeElementCallback,
230 ) {
231 callback.call(&elements::padding::Padding {
232 left: self.left,
233 right: self.right,
234 top: self.top,
235 bottom: self.bottom,
236 element: SerdeElementElement {
237 element: &*self.element,
238 fonts,
239 },
240 });
241 }
242}
243
244#[derive(Clone, Serialize, Deserialize)]
245pub struct StyledBox<E> {
246 pub element: Box<E>,
247 pub padding_left: f32,
248 pub padding_right: f32,
249 pub padding_top: f32,
250 pub padding_bottom: f32,
251 pub border_radius: f32,
252 pub fill: Option<u32>,
253 pub outline: Option<LineStyle>,
254}
255
256impl<E: SerdeElement> SerdeElement for StyledBox<E> {
257 fn element(
258 &self,
259 fonts: &impl for<'a> Index<&'a str, Output = Font>,
260 callback: impl CompositeElementCallback,
261 ) {
262 callback.call(&elements::styled_box::StyledBox {
263 element: SerdeElementElement {
264 element: &*self.element,
265 fonts,
266 },
267 padding_left: self.padding_left,
268 padding_right: self.padding_right,
269 padding_top: self.padding_top,
270 padding_bottom: self.padding_bottom,
271 border_radius: self.border_radius,
272 fill: self.fill,
273 outline: self.outline,
274 });
275 }
276}
277
278#[derive(Clone, Serialize, Deserialize)]
279pub struct Line {
280 pub style: LineStyle,
281}
282
283impl SerdeElement for Line {
284 fn element(
285 &self,
286 _: &impl for<'a> Index<&'a str, Output = Font>,
287 callback: impl CompositeElementCallback,
288 ) {
289 callback.call(&elements::line::Line { style: self.style });
290 }
291}
292
293#[derive(Clone, Deserialize)]
294pub struct Image {
295 #[serde(rename = "path", deserialize_with = "crate::image::deserialize_image")]
296 pub image: crate::image::Image,
297}
298
299impl SerdeElement for Image {
300 fn element(
301 &self,
302 _: &impl for<'a> Index<&'a str, Output = Font>,
303 callback: impl CompositeElementCallback,
304 ) {
305 callback.call(&elements::image::ImageElement { image: &self.image });
306 }
307}
308
309#[derive(Clone, Serialize, Deserialize)]
310pub struct Rectangle {
311 pub size: (f32, f32),
312 pub fill: Option<u32>,
313 pub outline: Option<(f32, u32)>,
314}
315
316impl SerdeElement for Rectangle {
317 fn element(
318 &self,
319 _: &impl for<'a> Index<&'a str, Output = Font>,
320 callback: impl CompositeElementCallback,
321 ) {
322 callback.call(&elements::rectangle::Rectangle {
323 size: self.size,
324 fill: self.fill,
325 outline: self.outline,
326 });
327 }
328}
329
330#[derive(Clone, Serialize, Deserialize)]
331pub struct Circle {
332 pub radius: f32,
333 pub fill: Option<u32>,
334 pub outline: Option<(f32, u32)>,
335}
336
337impl SerdeElement for Circle {
338 fn element(
339 &self,
340 _: &impl for<'a> Index<&'a str, Output = Font>,
341 callback: impl CompositeElementCallback,
342 ) {
343 callback.call(&elements::circle::Circle {
344 radius: self.radius,
345 fill: self.fill,
346 outline: self.outline,
347 });
348 }
349}
350
351#[derive(Clone, Serialize, Deserialize)]
352pub struct Column<E> {
353 pub content: Vec<E>,
354 pub gap: f32,
355
356 #[serde(default = "default_false")]
357 pub collapse: bool,
358}
359
360impl<E: SerdeElement> SerdeElement for Column<E> {
361 fn element(
362 &self,
363 fonts: &impl for<'a> Index<&'a str, Output = Font>,
364 callback: impl CompositeElementCallback,
365 ) {
366 callback.call(&elements::column::Column {
367 content: |mut content| {
368 for element in &self.content {
369 content = content.add(&SerdeElementElement { element, fonts })?;
370 }
371
372 Option::None
373 },
374 gap: self.gap,
375 collapse: self.collapse,
376 });
377 }
378}
379
380#[derive(Clone, Serialize, Deserialize)]
381pub struct RowElement<E> {
382 pub element: E,
383 pub flex: Flex,
384}
385
386#[derive(Clone, Serialize, Deserialize)]
387pub struct Row<E> {
388 pub content: Vec<RowElement<E>>,
389 pub gap: f32,
390 pub expand: bool,
391 pub collapse: bool,
392}
393
394impl<E: SerdeElement> SerdeElement for Row<E> {
395 fn element(
396 &self,
397 fonts: &impl for<'a> Index<&'a str, Output = Font>,
398 callback: impl CompositeElementCallback,
399 ) {
400 callback.call(&elements::row::Row {
401 content: |content| {
402 for RowElement { element, flex } in &self.content {
403 content.add(&SerdeElementElement { element, fonts }, *flex);
404 }
405 },
406 gap: self.gap,
407 expand: self.expand,
408 collapse: self.collapse,
409 });
410 }
411}
412
413#[derive(Clone, Serialize, Deserialize)]
414pub struct BreakList<E> {
415 pub content: Vec<E>,
416 pub gap: f32,
417}
418
419impl<E: SerdeElement> SerdeElement for BreakList<E> {
420 fn element(
421 &self,
422 fonts: &impl for<'a> Index<&'a str, Output = Font>,
423 callback: impl CompositeElementCallback,
424 ) {
425 callback.call(&elements::break_list::BreakList {
426 content: |mut content| {
427 for element in &self.content {
428 content = content.add(&SerdeElementElement { element, fonts })?;
429 }
430
431 Option::None
432 },
433 gap: self.gap,
434 });
435 }
436}
437
438#[derive(Clone, Serialize, Deserialize)]
439pub struct Stack<E> {
440 pub content: Vec<E>,
441 pub expand: bool,
442}
443
444impl<E: SerdeElement> SerdeElement for Stack<E> {
445 fn element(
446 &self,
447 fonts: &impl for<'a> Index<&'a str, Output = Font>,
448 callback: impl CompositeElementCallback,
449 ) {
450 callback.call(&elements::stack::Stack {
451 content: |content| {
452 for element in &self.content {
453 content.add(&SerdeElementElement { element, fonts });
454 }
455 },
456 expand: self.expand,
457 });
458 }
459}
460
461#[derive(Clone, Serialize, Deserialize)]
462pub struct TableRowElement<E> {
463 pub element: E,
464 pub flex: elements::table_row::Flex,
465}
466
467#[derive(Clone, Serialize, Deserialize)]
468pub struct TableRow<E> {
469 pub content: Vec<TableRowElement<E>>,
470 pub line_style: LineStyle,
471
472 #[serde(alias = "y_expand")]
473 pub expand: bool,
474}
475
476impl<E: SerdeElement> SerdeElement for TableRow<E> {
477 fn element(
478 &self,
479 fonts: &impl for<'a> Index<&'a str, Output = Font>,
480 callback: impl CompositeElementCallback,
481 ) {
482 callback.call(&elements::table_row::TableRow {
483 content: |content| {
484 for TableRowElement { element, flex } in &self.content {
485 content.add(&SerdeElementElement { element, fonts }, *flex);
486 }
487 },
488 line_style: self.line_style,
489 expand: self.expand,
490 });
491 }
492}
493
494#[derive(Clone, Serialize, Deserialize)]
495pub struct Titled<E> {
496 pub title: Box<E>,
497 pub content: Box<E>,
498 pub gap: f32,
499
500 #[serde(default = "default_false")]
501 pub collapse_on_empty_content: bool,
502}
503
504impl<E: SerdeElement> SerdeElement for Titled<E> {
505 fn element(
506 &self,
507 fonts: &impl for<'a> Index<&'a str, Output = Font>,
508 callback: impl CompositeElementCallback,
509 ) {
510 callback.call(&elements::titled::Titled {
511 title: SerdeElementElement {
512 element: &*self.title,
513 fonts,
514 },
515 content: SerdeElementElement {
516 element: &*self.content,
517 fonts,
518 },
519 gap: self.gap,
520 collapse_on_empty_content: self.collapse_on_empty_content,
521 });
522 }
523}
524
525#[derive(Clone, Serialize, Deserialize)]
526pub struct TitleOrBreak<E> {
527 pub title: Box<E>,
528 pub content: Box<E>,
529 pub gap: f32,
530
531 #[serde(default = "default_false")]
532 pub collapse_on_empty_content: bool,
533}
534
535impl<E: SerdeElement> SerdeElement for TitleOrBreak<E> {
536 fn element(
537 &self,
538 fonts: &impl for<'a> Index<&'a str, Output = Font>,
539 callback: impl CompositeElementCallback,
540 ) {
541 callback.call(&elements::title_or_break::TitleOrBreak {
542 title: &SerdeElementElement {
543 element: &*self.title,
544 fonts,
545 },
546 content: &SerdeElementElement {
547 element: &*self.content,
548 fonts,
549 },
550 gap: self.gap,
551 collapse_on_empty_content: self.collapse_on_empty_content,
552 });
553 }
554}
555
556#[derive(Clone, Serialize, Deserialize)]
557pub struct ChangingTitle<E> {
558 pub first_title: Box<E>,
559
560 #[serde(alias = "second_title")]
561 pub remaining_title: Box<E>,
562
563 pub content: Box<E>,
564 pub gap: f32,
565
566 #[serde(default = "default_false")]
567 pub collapse: bool,
568}
569
570impl<E: SerdeElement> SerdeElement for ChangingTitle<E> {
571 fn element(
572 &self,
573 fonts: &impl for<'a> Index<&'a str, Output = Font>,
574 callback: impl CompositeElementCallback,
575 ) {
576 callback.call(&elements::changing_title::ChangingTitle {
577 first_title: SerdeElementElement {
578 element: &*self.first_title,
579 fonts,
580 },
581 remaining_title: SerdeElementElement {
582 element: &*self.remaining_title,
583 fonts,
584 },
585 content: SerdeElementElement {
586 element: &*self.content,
587 fonts,
588 },
589 gap: self.gap,
590 collapse: self.collapse,
591 });
592 }
593}
594
595#[derive(Clone, Serialize, Deserialize)]
596pub struct RepeatAfterBreak<E> {
597 pub title: Box<E>,
598 pub content: Box<E>,
599 pub gap: f32,
600
601 #[serde(default = "default_false")]
602 pub collapse_on_empty_content: bool,
603}
604
605impl<E: SerdeElement> SerdeElement for RepeatAfterBreak<E> {
606 fn element(
607 &self,
608 fonts: &impl for<'a> Index<&'a str, Output = Font>,
609 callback: impl CompositeElementCallback,
610 ) {
611 callback.call(&elements::repeat_after_break::RepeatAfterBreak {
612 title: &SerdeElementElement {
613 element: &*self.title,
614 fonts,
615 },
616 content: &SerdeElementElement {
617 element: &*self.content,
618 fonts,
619 },
620 gap: self.gap,
621 collapse_on_empty_content: self.collapse_on_empty_content,
622 });
623 }
624}
625
626#[derive(Clone, Serialize, Deserialize)]
627pub struct RepeatBottom<E> {
628 pub content: Box<E>,
629 pub bottom: Box<E>,
630 pub gap: f32,
631
632 #[serde(default = "default_false")]
633 pub collapse: bool,
634}
635
636impl<E: SerdeElement> SerdeElement for RepeatBottom<E> {
637 fn element(
638 &self,
639 fonts: &impl for<'a> Index<&'a str, Output = Font>,
640 callback: impl CompositeElementCallback,
641 ) {
642 callback.call(&elements::repeat_bottom::RepeatBottom {
643 content: SerdeElementElement {
644 element: &*self.content,
645 fonts,
646 },
647 bottom: SerdeElementElement {
648 element: &*self.bottom,
649 fonts,
650 },
651 gap: self.gap,
652 collapse: self.collapse,
653 });
654 }
655}
656
657#[derive(Clone, Serialize, Deserialize)]
658pub struct PinBelow<E> {
659 pub content: Box<E>,
660 pub pinned_element: Box<E>,
661 pub gap: f32,
662
663 #[serde(default = "default_false")]
664 pub collapse: bool,
665}
666
667impl<E: SerdeElement> SerdeElement for PinBelow<E> {
668 fn element(
669 &self,
670 fonts: &impl for<'a> Index<&'a str, Output = Font>,
671 callback: impl CompositeElementCallback,
672 ) {
673 callback.call(&elements::pin_below::PinBelow {
674 content: SerdeElementElement {
675 element: &*self.content,
676 fonts,
677 },
678 pinned_element: SerdeElementElement {
679 element: &*self.pinned_element,
680 fonts,
681 },
682 gap: self.gap,
683 collapse: self.collapse,
684 });
685 }
686}
687
688#[derive(Clone, Serialize, Deserialize)]
689pub struct ForceBreak;
690
691impl SerdeElement for ForceBreak {
692 fn element(
693 &self,
694 _: &impl for<'a> Index<&'a str, Output = Font>,
695 callback: impl CompositeElementCallback,
696 ) {
697 callback.call(&elements::force_break::ForceBreak);
698 }
699}
700
701#[derive(Clone, Serialize, Deserialize)]
702pub struct BreakWhole<E> {
703 pub element: Box<E>,
704}
705
706impl<E: SerdeElement> SerdeElement for BreakWhole<E> {
707 fn element(
708 &self,
709 fonts: &impl for<'a> Index<&'a str, Output = Font>,
710 callback: impl CompositeElementCallback,
711 ) {
712 callback.call(&elements::break_whole::BreakWhole(&SerdeElementElement {
713 element: &*self.element,
714 fonts,
715 }));
716 }
717}
718
719#[derive(Clone, Serialize, Deserialize)]
720pub struct MinFirstHeight<E> {
721 pub element: Box<E>,
722 pub min_first_height: f32,
723}
724
725impl<E: SerdeElement> SerdeElement for MinFirstHeight<E> {
726 fn element(
727 &self,
728 fonts: &impl for<'a> Index<&'a str, Output = Font>,
729 callback: impl CompositeElementCallback,
730 ) {
731 callback.call(&elements::min_first_height::MinFirstHeight {
732 element: SerdeElementElement {
733 element: &*self.element,
734 fonts,
735 },
736 min_first_height: self.min_first_height,
737 });
738 }
739}
740
741#[derive(Clone, Serialize, Deserialize)]
742pub struct AlignLocationBottom<E> {
743 pub element: Box<E>,
744}
745
746impl<E: SerdeElement> SerdeElement for AlignLocationBottom<E> {
747 fn element(
748 &self,
749 fonts: &impl for<'a> Index<&'a str, Output = Font>,
750 callback: impl CompositeElementCallback,
751 ) {
752 callback.call(&elements::align_location_bottom::AlignLocationBottom(
753 SerdeElementElement {
754 element: &*self.element,
755 fonts,
756 },
757 ));
758 }
759}
760
761#[derive(Clone, Serialize, Deserialize)]
762pub struct AlignPreferredHeightBottom<E> {
763 pub element: Box<E>,
764}
765
766impl<E: SerdeElement> SerdeElement for AlignPreferredHeightBottom<E> {
767 fn element(
768 &self,
769 fonts: &impl for<'a> Index<&'a str, Output = Font>,
770 callback: impl CompositeElementCallback,
771 ) {
772 callback.call(
773 &elements::align_preferred_height_bottom::AlignPreferredHeightBottom(
774 SerdeElementElement {
775 element: &*self.element,
776 fonts,
777 },
778 ),
779 );
780 }
781}
782
783#[derive(Clone, Serialize, Deserialize)]
784pub struct ExpandToPreferredHeight<E> {
785 pub element: Box<E>,
786}
787
788impl<E: SerdeElement> SerdeElement for ExpandToPreferredHeight<E> {
789 fn element(
790 &self,
791 fonts: &impl for<'a> Index<&'a str, Output = Font>,
792 callback: impl CompositeElementCallback,
793 ) {
794 callback.call(
795 &elements::expand_to_preferred_height::ExpandToPreferredHeight(SerdeElementElement {
796 element: &*self.element,
797 fonts,
798 }),
799 );
800 }
801}
802
803#[derive(Clone, Serialize, Deserialize)]
804pub struct CenterInPreferredHeight<E> {
805 pub element: Box<E>,
806}
807
808impl<E: SerdeElement> SerdeElement for CenterInPreferredHeight<E> {
809 fn element(
810 &self,
811 fonts: &impl for<'a> Index<&'a str, Output = Font>,
812 callback: impl CompositeElementCallback,
813 ) {
814 callback.call(
815 &elements::center_in_preferred_height::CenterInPreferredHeight(SerdeElementElement {
816 element: &*self.element,
817 fonts,
818 }),
819 );
820 }
821}
822
823#[derive(Clone, Serialize, Deserialize)]
824pub struct ShrinkToFit<E> {
825 pub element: Box<E>,
826 pub min_height: f32,
827}
828
829impl<E: SerdeElement> SerdeElement for ShrinkToFit<E> {
830 fn element(
831 &self,
832 fonts: &impl for<'a> Index<&'a str, Output = Font>,
833 callback: impl CompositeElementCallback,
834 ) {
835 callback.call(&elements::shrink_to_fit::ShrinkToFit {
836 element: SerdeElementElement {
837 element: &*self.element,
838 fonts,
839 },
840 min_height: self.min_height,
841 });
842 }
843}
844
845#[derive(Clone, Serialize, Deserialize)]
846pub struct Rotate<E> {
847 pub element: Box<E>,
848 pub rotation: Rotation,
849}
850
851impl<E: SerdeElement> SerdeElement for Rotate<E> {
852 fn element(
853 &self,
854 fonts: &impl for<'a> Index<&'a str, Output = Font>,
855 callback: impl CompositeElementCallback,
856 ) {
857 callback.call(&elements::rotate::Rotate {
858 element: SerdeElementElement {
859 element: &*self.element,
860 fonts,
861 },
862 rotation: self.rotation,
863 });
864 }
865}
866
867#[derive(Clone, Serialize, Deserialize)]
868pub struct MaxWidth<E> {
869 pub element: Box<E>,
870 pub max_width: f32,
871}
872
873impl<E: SerdeElement> SerdeElement for MaxWidth<E> {
874 fn element(
875 &self,
876 fonts: &impl for<'a> Index<&'a str, Output = Font>,
877 callback: impl CompositeElementCallback,
878 ) {
879 callback.call(&elements::max_width::MaxWidth {
880 element: SerdeElementElement {
881 element: &*self.element,
882 fonts,
883 },
884 max_width: self.max_width,
885 });
886 }
887}
888
889#[derive(Clone, Serialize, Deserialize)]
890pub enum PageNumberText {
891 Current {
892 before: String,
893 after: String,
894 },
895 Total {
896 before: String,
897 after: String,
898 },
899 CurrentAndTotal {
900 before: String,
901 between: String,
902 after: String,
903 },
904}
905
906#[derive(Clone, Serialize, Deserialize)]
907pub struct PageNumber {
908 pub skip_pages: usize,
909 pub pos: (elements::page::X, elements::page::Y),
910 pub text: PageNumberText,
911 pub font: String,
912 pub size: f32,
913 pub color: u32,
914 pub underline: bool,
915}
916
917#[derive(Clone, Serialize, Deserialize)]
918pub struct DecorationElement<E> {
919 pub element: E,
920 pub pos: (elements::page::X, elements::page::Y),
921 pub width: Option<f32>,
922 pub skip_pages: usize,
923 pub repeat: bool,
924}
925
926#[derive(Clone, Serialize, Deserialize)]
927pub struct Page<E> {
928 pub primary: Box<E>,
929 pub border_left: f32,
930 pub border_right: f32,
931 pub border_top: f32,
932 pub border_bottom: f32,
933 pub decoration_elements: Vec<DecorationElement<E>>,
934 pub page_numbers: Vec<PageNumber>,
935}
936
937impl<E: SerdeElement> SerdeElement for Page<E> {
938 fn element(
939 &self,
940 fonts: &impl for<'a> Index<&'a str, Output = Font>,
941 callback: impl CompositeElementCallback,
942 ) {
943 callback.call(&elements::page::Page {
944 primary: SerdeElementElement {
945 element: &*self.primary,
946 fonts,
947 },
948 border_left: self.border_left,
949 border_right: self.border_right,
950 border_top: self.border_top,
951 border_bottom: self.border_bottom,
952 decoration_elements: |content, page, page_count| {
953 for decoration_element in &self.decoration_elements {
954 if page == decoration_element.skip_pages
955 || decoration_element.repeat && page > decoration_element.skip_pages
956 {
957 content.add(
958 &SerdeElementElement {
959 element: &decoration_element.element,
960 fonts,
961 },
962 decoration_element.pos,
963 decoration_element.width,
964 );
965 }
966 }
967
968 for page_number in &self.page_numbers {
969 if page >= page_number.skip_pages {
970 content.add(
971 &elements::text::Text {
972 underline: page_number.underline,
973 color: page_number.color,
974 ..elements::text::Text::new(
975 &match page_number.text {
979 PageNumberText::Current {
980 ref before,
981 ref after,
982 } => {
983 format!("{before}{}{after}", page + 1)
984 }
985 PageNumberText::Total {
986 ref before,
987 ref after,
988 } => format!("{before}{page_count}{after}"),
989 PageNumberText::CurrentAndTotal {
990 ref before,
991 ref between,
992 ref after,
993 } => {
994 format!(
995 "{before}{}{between}{page_count}{after}",
996 page + 1
997 )
998 }
999 },
1000 &*fonts[&page_number.font],
1001 page_number.size,
1002 )
1003 },
1004 page_number.pos,
1005 Option::None,
1006 );
1007 }
1008 }
1009 },
1010 });
1011 }
1012}
1013
1014#[derive(Clone, Serialize, Deserialize)]
1015pub struct Link<E> {
1016 pub element: Box<E>,
1017 pub target: SerdeLinkTarget,
1018}
1019
1020impl<E: SerdeElement> SerdeElement for Link<E> {
1021 fn element(
1022 &self,
1023 fonts: &impl for<'a> Index<&'a str, Output = Font>,
1024 callback: impl CompositeElementCallback,
1025 ) {
1026 callback.call(&elements::link::Link {
1027 element: SerdeElementElement {
1028 element: &*self.element,
1029 fonts,
1030 },
1031 target: self.target.as_link_target(),
1032 });
1033 }
1034}