laser_pdf/test_utils/
build_element.rs1use crate::*;
2
3pub struct BuildElementReturnToken(());
4
5pub struct BuildElementCallback<'a>(&'a mut dyn FnMut(&dyn Element));
7
8impl<'a> BuildElementCallback<'a> {
9 pub fn call(self, element: impl Element) -> BuildElementReturnToken {
10 self.0(&element);
11 BuildElementReturnToken(())
12 }
13}
14
15pub struct BreakableDraw {
16 pub full_height: f32,
17 pub preferred_height_break_count: u32,
18}
19
20pub enum Pass {
21 FirstLocationUsage {
22 full_height: f32,
23 },
24 Measure {
25 full_height: Option<f32>,
26 },
27 Draw {
28 preferred_height: Option<f32>,
29 breakable: Option<BreakableDraw>,
30 },
31}
32
33pub struct BuildElementCtx {
34 pub width: WidthConstraint,
35 pub first_height: f32,
36 pub pass: Pass,
37}
38
39impl BuildElementCtx {
40 pub fn is_breakable(&self) -> bool {
41 match self.pass {
42 Pass::FirstLocationUsage { .. } => true,
43 Pass::Measure { full_height } => full_height.is_some(),
44 Pass::Draw { ref breakable, .. } => breakable.is_some(),
45 }
46 }
47}
48
49pub struct BuildElement<F: Fn(BuildElementCtx, BuildElementCallback) -> BuildElementReturnToken>(
50 pub F,
51);
52
53impl<F: Fn(BuildElementCtx, BuildElementCallback) -> BuildElementReturnToken> Element
54 for BuildElement<F>
55{
56 fn first_location_usage(&self, ctx: FirstLocationUsageCtx) -> FirstLocationUsage {
57 let mut ret = FirstLocationUsage::NoneHeight;
58
59 let build_ctx = BuildElementCtx {
60 width: ctx.width,
61 first_height: ctx.first_height,
62 pass: Pass::FirstLocationUsage {
63 full_height: ctx.full_height,
64 },
65 };
66
67 let mut ctx = Some(ctx);
68
69 (self.0)(
70 build_ctx,
71 BuildElementCallback(&mut |e| ret = e.first_location_usage(ctx.take().unwrap())),
72 );
73 ret
74 }
75
76 fn measure(&self, ctx: MeasureCtx) -> ElementSize {
77 let mut ret = ElementSize {
78 width: None,
79 height: None,
80 };
81
82 let build_ctx = BuildElementCtx {
83 width: ctx.width,
84 first_height: ctx.first_height,
85 pass: Pass::Measure {
86 full_height: ctx.breakable.as_ref().map(|b| b.full_height),
87 },
88 };
89
90 let mut ctx = Some(ctx);
91
92 (self.0)(
93 build_ctx,
94 BuildElementCallback(&mut |e| ret = e.measure(ctx.take().unwrap())),
95 );
96 ret
97 }
98
99 fn draw(&self, ctx: DrawCtx) -> ElementSize {
100 let mut ret = ElementSize {
101 width: None,
102 height: None,
103 };
104
105 let build_ctx = BuildElementCtx {
106 width: ctx.width,
107 first_height: ctx.first_height,
108 pass: Pass::Draw {
109 preferred_height: ctx.preferred_height,
110 breakable: ctx.breakable.as_ref().map(|b| BreakableDraw {
111 full_height: b.full_height,
112 preferred_height_break_count: b.preferred_height_break_count,
113 }),
114 },
115 };
116
117 let mut ctx = Some(ctx);
118
119 (self.0)(
120 build_ctx,
121 BuildElementCallback(&mut |e| ret = e.draw(ctx.take().unwrap())),
122 );
123 ret
124 }
125}