1use crate::geometry::Line;
4use crate::style::{GenericGridPlacement, GridPlacement, Style};
5use core::cmp::{max, min};
6
7use super::types::TrackCounts;
8use super::OriginZeroLine;
9
10pub(crate) fn compute_grid_size_estimate<'a>(
19 explicit_col_count: u16,
20 explicit_row_count: u16,
21 child_styles_iter: impl Iterator<Item = &'a Style>,
22) -> (TrackCounts, TrackCounts) {
23 let (col_min, col_max, col_max_span, row_min, row_max, row_max_span) =
26 get_known_child_positions(child_styles_iter, explicit_col_count, explicit_row_count);
27
28 let negative_implicit_inline_tracks = col_min.implied_negative_implicit_tracks();
32 let explicit_inline_tracks = explicit_col_count;
33 let mut positive_implicit_inline_tracks = col_max.implied_positive_implicit_tracks(explicit_col_count);
34 let negative_implicit_block_tracks = row_min.implied_negative_implicit_tracks();
35 let explicit_block_tracks = explicit_row_count;
36 let mut positive_implicit_block_tracks = row_max.implied_positive_implicit_tracks(explicit_row_count);
37
38 let tot_inline_tracks = negative_implicit_inline_tracks + explicit_inline_tracks + positive_implicit_inline_tracks;
41 if tot_inline_tracks < col_max_span {
42 positive_implicit_inline_tracks = col_max_span - explicit_inline_tracks - negative_implicit_inline_tracks;
43 }
44
45 let tot_block_tracks = negative_implicit_block_tracks + explicit_block_tracks + positive_implicit_block_tracks;
46 if tot_block_tracks < row_max_span {
47 positive_implicit_block_tracks = row_max_span - explicit_block_tracks - negative_implicit_block_tracks;
48 }
49
50 let column_counts =
51 TrackCounts::from_raw(negative_implicit_inline_tracks, explicit_inline_tracks, positive_implicit_inline_tracks);
52
53 let row_counts =
54 TrackCounts::from_raw(negative_implicit_block_tracks, explicit_block_tracks, positive_implicit_block_tracks);
55
56 (column_counts, row_counts)
57}
58
59fn get_known_child_positions<'a>(
64 children_iter: impl Iterator<Item = &'a Style>,
65 explicit_col_count: u16,
66 explicit_row_count: u16,
67) -> (OriginZeroLine, OriginZeroLine, u16, OriginZeroLine, OriginZeroLine, u16) {
68 let (mut col_min, mut col_max, mut col_max_span) = (OriginZeroLine(0), OriginZeroLine(0), 0);
69 let (mut row_min, mut row_max, mut row_max_span) = (OriginZeroLine(0), OriginZeroLine(0), 0);
70 children_iter.for_each(|child_style: &Style| {
71 let (child_col_min, child_col_max, child_col_span) =
74 child_min_line_max_line_span(child_style.grid_column, explicit_col_count);
75 let (child_row_min, child_row_max, child_row_span) =
76 child_min_line_max_line_span(child_style.grid_row, explicit_row_count);
77 col_min = min(col_min, child_col_min);
78 col_max = max(col_max, child_col_max);
79 col_max_span = max(col_max_span, child_col_span);
80 row_min = min(row_min, child_row_min);
81 row_max = max(row_max, child_row_max);
82 row_max_span = max(row_max_span, child_row_span);
83 });
84
85 (col_min, col_max, col_max_span, row_min, row_max, row_max_span)
86}
87
88#[inline]
93fn child_min_line_max_line_span(
94 line: Line<GridPlacement>,
95 explicit_track_count: u16,
96) -> (OriginZeroLine, OriginZeroLine, u16) {
97 use GenericGridPlacement::*;
98
99 let oz_line = line.into_origin_zero(explicit_track_count);
107
108 let min = match (oz_line.start, oz_line.end) {
109 (Line(track1), Line(track2)) => {
111 if track1 == track2 {
113 track1
114 } else {
115 min(track1, track2)
116 }
117 }
118
119 (Line(track), Auto) => track,
121 (Line(track), Span(_)) => track,
122
123 (Auto, Line(track)) => track,
125 (Span(span), Line(track)) => track - span,
126
127 (Auto | Span(_), Auto | Span(_)) => OriginZeroLine(0),
130 };
131
132 let max = match (oz_line.start, oz_line.end) {
133 (Line(track1), Line(track2)) => {
135 if track1 == track2 {
137 track1 + 1
138 } else {
139 max(track1, track2)
140 }
141 }
142
143 (Line(track), Auto) => track + 1,
145 (Line(track), Span(span)) => track + span,
146
147 (Auto, Line(track)) => track,
149 (Span(_), Line(track)) => track,
150
151 (Auto | Span(_), Auto | Span(_)) => OriginZeroLine(0),
154 };
155
156 let span = match (line.start, line.end) {
159 (Auto | Span(_), Auto | Span(_)) => line.indefinite_span(),
160 _ => 1,
161 };
162
163 (min, max, span)
164}
165
166#[allow(clippy::bool_assert_comparison)]
167#[cfg(test)]
168mod tests {
169 mod test_child_min_max_line {
170 use super::super::child_min_line_max_line_span;
171 use super::super::OriginZeroLine;
172 use crate::geometry::Line;
173 use crate::style_helpers::*;
174
175 #[test]
176 fn child_min_max_line_auto() {
177 let (min_col, max_col, span) = child_min_line_max_line_span(Line { start: line(5), end: span(6) }, 6);
178 assert_eq!(min_col, OriginZeroLine(4));
179 assert_eq!(max_col, OriginZeroLine(10));
180 assert_eq!(span, 1);
181 }
182
183 #[test]
184 fn child_min_max_line_negative_track() {
185 let (min_col, max_col, span) = child_min_line_max_line_span(Line { start: line(-5), end: span(3) }, 6);
186 assert_eq!(min_col, OriginZeroLine(2));
187 assert_eq!(max_col, OriginZeroLine(5));
188 assert_eq!(span, 1);
189 }
190 }
191
192 mod test_intial_grid_sizing {
193 use super::super::compute_grid_size_estimate;
194 use crate::compute::grid::util::test_helpers::*;
195 use crate::style_helpers::*;
196
197 #[test]
198 fn explicit_grid_sizing_with_children() {
199 let explicit_col_count = 6;
200 let explicit_row_count = 8;
201 let child_styles = vec![
202 (line(1), span(2), line(2), auto()).into_grid_child(),
203 (line(-4), auto(), line(-2), auto()).into_grid_child(),
204 ];
205 let (inline, block) =
206 compute_grid_size_estimate(explicit_col_count, explicit_row_count, child_styles.iter());
207 assert_eq!(inline.negative_implicit, 0);
208 assert_eq!(inline.explicit, explicit_col_count);
209 assert_eq!(inline.positive_implicit, 0);
210 assert_eq!(block.negative_implicit, 0);
211 assert_eq!(block.explicit, explicit_row_count);
212 assert_eq!(block.positive_implicit, 0);
213 }
214
215 #[test]
216 fn negative_implicit_grid_sizing() {
217 let explicit_col_count = 4;
218 let explicit_row_count = 4;
219 let child_styles = vec![
220 (line(-6), span(2), line(-8), auto()).into_grid_child(),
221 (line(4), auto(), line(3), auto()).into_grid_child(),
222 ];
223 let (inline, block) =
224 compute_grid_size_estimate(explicit_col_count, explicit_row_count, child_styles.iter());
225 assert_eq!(inline.negative_implicit, 1);
226 assert_eq!(inline.explicit, explicit_col_count);
227 assert_eq!(inline.positive_implicit, 0);
228 assert_eq!(block.negative_implicit, 3);
229 assert_eq!(block.explicit, explicit_row_count);
230 assert_eq!(block.positive_implicit, 0);
231 }
232 }
233}