laser_pdf/elements/force_break.rs
1use crate::*;
2
3/// Forces a break after it. Breaking mostly means page breaking, but the same mechanism could be
4/// used for columns or other advanced layout usecases.
5///
6/// This element takes up no space but causes the layout to continue on the next page or column when
7/// used in a breakable context.
8pub struct ForceBreak;
9
10impl Element for ForceBreak {
11 fn first_location_usage(&self, _ctx: FirstLocationUsageCtx) -> FirstLocationUsage {
12 FirstLocationUsage::WillUse
13 }
14
15 fn measure(&self, ctx: MeasureCtx) -> ElementSize {
16 if let Some(breakable) = ctx.breakable {
17 *breakable.break_count = 1;
18 }
19
20 ElementSize {
21 width: None,
22 height: None,
23 }
24 }
25
26 fn draw(&self, ctx: DrawCtx) -> ElementSize {
27 if let Some(breakable) = ctx.breakable {
28 // Note: This passes None as the height even though it always returns WillUse from
29 // first_location_usage. Just because the first location has None height doesn't mean
30 // it was skipped. In fact it would be incorrect if this element were to return
31 // WillSkip. WillSkip implies that if the element is drawn with a full first height it
32 // has to then look the same.
33 (breakable.do_break)(ctx.pdf, 0, None);
34 }
35
36 ElementSize {
37 width: None,
38 height: None,
39 }
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46 use crate::test_utils::*;
47
48 #[test]
49 fn test_force_break() {
50 for output in ElementTestParams::default().run(&ForceBreak) {
51 output.assert_size(ElementSize {
52 width: None,
53 height: None,
54 });
55
56 if let Some(b) = output.breakable {
57 b.assert_break_count(1);
58 b.assert_extra_location_min_height(None);
59 }
60 }
61 }
62}