Skip to main content

laser_pdf/elements/
max_width.rs

1use crate::*;
2
3pub struct MaxWidth<E: Element> {
4    pub element: E,
5    pub max_width: f32,
6}
7
8impl<E: Element> Element for MaxWidth<E> {
9    fn first_location_usage(&self, ctx: FirstLocationUsageCtx) -> FirstLocationUsage {
10        self.element.first_location_usage(FirstLocationUsageCtx {
11            width: self.width(ctx.width),
12            ..ctx
13        })
14    }
15
16    fn measure(&self, ctx: MeasureCtx) -> ElementSize {
17        self.element.measure(MeasureCtx {
18            width: self.width(ctx.width),
19            ..ctx
20        })
21    }
22
23    fn draw(&self, ctx: DrawCtx) -> ElementSize {
24        self.element.draw(DrawCtx {
25            width: self.width(ctx.width),
26            ..ctx
27        })
28    }
29}
30
31impl<E: Element> MaxWidth<E> {
32    fn width(&self, width: WidthConstraint) -> WidthConstraint {
33        WidthConstraint {
34            max: width.max.min(self.max_width),
35            expand: width.expand,
36        }
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43    use crate::{
44        elements::{svg::Svg, text::Text},
45        fonts::builtin::BuiltinFont,
46        test_utils::binary_snapshots::*,
47    };
48    use insta::*;
49
50    #[test]
51    fn test_text() {
52        let bytes = test_element_bytes(
53            TestElementParams {
54                first_height: 10.,
55                ..TestElementParams::breakable()
56            },
57            |mut callback| {
58                let font = BuiltinFont::courier(callback.pdf());
59                let element = MaxWidth {
60                    element: Text::basic("Abcd Abcd Abcd", &font, 12.).debug(1),
61                    max_width: 12.,
62                };
63
64                callback.call(&element.debug(0));
65            },
66        );
67        assert_binary_snapshot!(".pdf", bytes);
68    }
69
70    #[test]
71    fn test_image() {
72        const SVG: &str = "\
73            <svg
74               width=\"512\"
75               height=\"512\"
76               viewBox=\"0 0 135.46666 135.46667\"
77               version=\"1.1\"
78               id=\"svg1\"
79               xmlns=\"http://www.w3.org/2000/svg\"
80               xmlns:svg=\"http://www.w3.org/2000/svg\">
81              <defs
82                 id=\"defs1\" />
83              <g
84                 id=\"layer1\">
85                <rect
86                   style=\"fill:#000f80;fill-opacity:1;stroke:none;stroke-width:1.3386\"
87                   id=\"rect1\"
88                   width=\"108.92857\"
89                   height=\"72.85714\"
90                   x=\"18.571426\"
91                   y=\"11.428572\" />
92                <ellipse
93                   style=\"fill:#008080;fill-opacity:1;stroke:none;stroke-width:2.07092\"
94                   id=\"path1\"
95                   cx=\"84.107147\"
96                   cy=\"84.107132\"
97                   rx=\"51.964283\"
98                   ry=\"46.250004\" />
99              </g>
100            </svg>
101        ";
102
103        let tree = usvg::Tree::from_str(
104            SVG,
105            &usvg::Options {
106                ..Default::default()
107            },
108        )
109        .unwrap();
110
111        let bytes = test_element_bytes(TestElementParams::breakable(), |callback| {
112            let element = MaxWidth {
113                element: Svg { data: &tree },
114                max_width: 105.,
115            };
116
117            callback.call(
118                &element
119                    .debug(0)
120                    .show_max_width()
121                    .show_last_location_max_height(),
122            );
123        });
124        assert_binary_snapshot!(".pdf", bytes);
125    }
126}