typst_library/layout/
regions.rs1use std::fmt::{self, Debug, Formatter};
2
3use crate::layout::{Abs, Axes, Size};
4
5#[derive(Debug, Copy, Clone, Hash)]
7pub struct Region {
8 pub size: Size,
10 pub expand: Axes<bool>,
13}
14
15impl Region {
16 pub fn new(size: Size, expand: Axes<bool>) -> Self {
18 Self { size, expand }
19 }
20}
21
22impl From<Region> for Regions<'_> {
23 fn from(region: Region) -> Self {
24 Regions {
25 size: region.size,
26 expand: region.expand,
27 full: region.size.y,
28 backlog: &[],
29 last: None,
30 }
31 }
32}
33
34#[derive(Copy, Clone, Hash)]
42pub struct Regions<'a> {
43 pub size: Size,
45 pub expand: Axes<bool>,
48 pub full: Abs,
50 pub backlog: &'a [Abs],
52 pub last: Option<Abs>,
55}
56
57impl Regions<'_> {
58 pub fn repeat(size: Size, expand: Axes<bool>) -> Self {
60 Self {
61 size,
62 full: size.y,
63 backlog: &[],
64 last: Some(size.y),
65 expand,
66 }
67 }
68
69 pub fn base(&self) -> Size {
74 Size::new(self.size.x, self.full)
75 }
76
77 pub fn map<'v, F>(&self, backlog: &'v mut Vec<Abs>, mut f: F) -> Regions<'v>
82 where
83 F: FnMut(Size) -> Size,
84 {
85 let x = self.size.x;
86 backlog.clear();
87 backlog.extend(self.backlog.iter().map(|&y| f(Size::new(x, y)).y));
88 Regions {
89 size: f(self.size),
90 full: f(Size::new(x, self.full)).y,
91 backlog,
92 last: self.last.map(|y| f(Size::new(x, y)).y),
93 expand: self.expand,
94 }
95 }
96
97 pub fn is_full(&self) -> bool {
99 Abs::zero().fits(self.size.y) && self.may_progress()
100 }
101
102 pub fn may_break(&self) -> bool {
104 !self.backlog.is_empty() || self.last.is_some()
105 }
106
107 pub fn may_progress(&self) -> bool {
110 !self.backlog.is_empty() || self.last.is_some_and(|height| self.size.y != height)
111 }
112
113 pub fn next(&mut self) {
115 if let Some(height) = self
116 .backlog
117 .split_first()
118 .map(|(first, tail)| {
119 self.backlog = tail;
120 *first
121 })
122 .or(self.last)
123 {
124 self.size.y = height;
125 self.full = height;
126 }
127 }
128
129 pub fn iter(&self) -> impl Iterator<Item = Size> + '_ {
134 let first = std::iter::once(self.size);
135 let backlog = self.backlog.iter();
136 let last = self.last.iter().cycle();
137 first.chain(backlog.chain(last).map(|&h| Size::new(self.size.x, h)))
138 }
139}
140
141impl Debug for Regions<'_> {
142 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
143 f.write_str("Regions ")?;
144 let mut list = f.debug_list();
145 let mut prev = self.size.y;
146 list.entry(&self.size);
147 for &height in self.backlog {
148 list.entry(&Size::new(self.size.x, height));
149 prev = height;
150 }
151 if let Some(last) = self.last {
152 if last != prev {
153 list.entry(&Size::new(self.size.x, last));
154 }
155 list.entry(&(..));
156 }
157 list.finish()
158 }
159}