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