laser_pdf/test_utils/
assert_passes.rs1use std::cell::Cell;
2
3use crate::*;
4
5#[derive(PartialEq, Debug)]
6pub struct Break {
7 pub page: usize,
8 pub layer: usize,
9 pub pos: (f32, f32),
10}
11
12#[derive(PartialEq, Debug)]
13pub struct BreakableDraw {
14 pub full_height: f32,
15 pub preferred_height_break_count: u32,
16 pub breaks: Vec<Break>,
17}
18
19#[derive(PartialEq, Debug)]
20pub enum Pass {
21 FirstLocationUsage {
22 width: WidthConstraint,
23 first_height: f32,
24 full_height: f32,
25 },
26 Measure {
27 width: WidthConstraint,
28 first_height: f32,
29
30 full_height: Option<f32>,
32 },
33 Draw {
34 width: WidthConstraint,
35 first_height: f32,
36 preferred_height: Option<f32>,
37 page: usize,
38 layer: usize,
39 pos: (f32, f32),
40 breakable: Option<BreakableDraw>,
41 },
42}
43
44pub struct AssertPasses<E: Element> {
48 element: E,
49 passes: Vec<Pass>,
50 current: Cell<usize>,
51}
52
53impl<E: Element> AssertPasses<E> {
54 pub fn new(element: E, passes: Vec<Pass>) -> Self {
55 AssertPasses {
56 element,
57 passes,
58 current: Cell::new(0),
59 }
60 }
61}
62
63impl<E: Element> Drop for AssertPasses<E> {
64 fn drop(&mut self) {
65 assert_eq!(self.current.get(), self.passes.len());
70 }
71}
72
73impl<E: Element> Element for AssertPasses<E> {
74 fn first_location_usage(&self, ctx: FirstLocationUsageCtx) -> FirstLocationUsage {
75 let idx = self.current.get();
76 self.current.set(idx + 1);
77
78 let current = &self.passes[idx];
79
80 assert_eq!(
81 &Pass::FirstLocationUsage {
82 width: ctx.width,
83 first_height: ctx.first_height,
84 full_height: ctx.full_height,
85 },
86 current,
87 );
88
89 self.element.first_location_usage(ctx)
90 }
91
92 fn measure(&self, ctx: MeasureCtx) -> ElementSize {
93 let idx = self.current.get();
94 self.current.set(idx + 1);
95
96 let current = &self.passes[idx];
97
98 if let Some(ref b) = ctx.breakable {
99 assert_eq!(*b.break_count, 0);
100 assert_eq!(*b.extra_location_min_height, None);
101 }
102
103 assert_eq!(
104 &Pass::Measure {
105 width: ctx.width,
106 first_height: ctx.first_height,
107 full_height: ctx.breakable.as_ref().map(|b| b.full_height),
108 },
109 current,
110 );
111
112 self.element.measure(ctx)
113 }
114
115 fn draw(&self, ctx: DrawCtx) -> ElementSize {
116 let idx = self.current.get();
117 self.current.set(idx + 1);
118
119 let current = &self.passes[idx];
120
121 let width = ctx.width;
122 let first_height = ctx.first_height;
123 let preferred_height = ctx.preferred_height;
124
125 let page = ctx.location.page_idx;
126 let layer = ctx.location.layer_idx;
127 let pos = ctx.location.pos;
128
129 let result;
130
131 let breakable = if let Some(breakable) = ctx.breakable {
132 let full_height = breakable.full_height;
133 let preferred_height_break_count = breakable.preferred_height_break_count;
134
135 let mut breaks = Vec::new();
136
137 result = self.element.draw(DrawCtx {
138 breakable: Some(crate::BreakableDraw {
139 do_break: &mut |pdf, location_idx, height| {
140 let location = (breakable.do_break)(pdf, location_idx, height);
141
142 breaks.push(Break {
143 page: location.page_idx,
144 layer: location.layer_idx,
145 pos: location.pos,
146 });
147
148 location
149 },
150 ..breakable
151 }),
152 ..ctx
153 });
154
155 Some(BreakableDraw {
156 full_height,
157 preferred_height_break_count,
158 breaks,
159 })
160 } else {
161 result = self.element.draw(ctx);
162 None
163 };
164
165 assert_eq!(
166 &Pass::Draw {
167 width,
168 first_height,
169 preferred_height,
170 page,
171 layer,
172 pos,
173 breakable,
174 },
175 current,
176 );
177
178 result
179 }
180}