1use typst_library::diag::SourceResult;
2use typst_library::engine::Engine;
3use typst_library::foundations::{Packed, Resolve, StyleChain};
4use typst_library::introspection::Locator;
5use typst_library::layout::{
6 Abs, Fragment, Frame, PadElem, Point, Regions, Rel, Sides, Size,
7};
8
9#[typst_macros::time(span = elem.span())]
11pub fn layout_pad(
12 elem: &Packed<PadElem>,
13 engine: &mut Engine,
14 locator: Locator,
15 styles: StyleChain,
16 regions: Regions,
17) -> SourceResult<Fragment> {
18 let padding = Sides::new(
19 elem.left(styles).resolve(styles),
20 elem.top(styles).resolve(styles),
21 elem.right(styles).resolve(styles),
22 elem.bottom(styles).resolve(styles),
23 );
24
25 let mut backlog = vec![];
26 let pod = regions.map(&mut backlog, |size| shrink(size, &padding));
27
28 let mut fragment = crate::layout_fragment(engine, &elem.body, locator, styles, pod)?;
30
31 for frame in &mut fragment {
32 grow(frame, &padding);
33 }
34
35 Ok(fragment)
36}
37
38pub fn shrink(size: Size, inset: &Sides<Rel<Abs>>) -> Size {
40 size - inset.sum_by_axis().relative_to(size)
41}
42
43pub fn shrink_multiple(
46 size: &mut Size,
47 full: &mut Abs,
48 backlog: &mut [Abs],
49 last: &mut Option<Abs>,
50 inset: &Sides<Rel<Abs>>,
51) {
52 let summed = inset.sum_by_axis();
53 *size -= summed.relative_to(*size);
54 *full -= summed.y.relative_to(*full);
55 for item in backlog {
56 *item -= summed.y.relative_to(*item);
57 }
58 *last = last.map(|v| v - summed.y.relative_to(v));
59}
60
61pub fn grow(frame: &mut Frame, inset: &Sides<Rel<Abs>>) {
81 let padded = frame
84 .size()
85 .zip_map(inset.sum_by_axis(), |s, p| (s + p.abs) / (1.0 - p.rel.get()));
86
87 let inset = inset.relative_to(padded);
88 let offset = Point::new(inset.left, inset.top);
89
90 frame.set_size(padded);
92 frame.translate(offset);
93}