1use crate::geometry::Line;
4use crate::style::{GenericGridPlacement, OriginZeroGridPlacement};
5use core::cmp::{max, min};
6
7use super::types::TrackCounts;
8use super::{ItemPlacement, OriginZeroLine, MAX_OZ_LINE, MIN_OZ_LINE};
9
10pub(crate) fn compute_grid_size_estimate(
19 explicit_col_count: u16,
20 explicit_row_count: u16,
21 placements: &[ItemPlacement],
22) -> (TrackCounts, TrackCounts) {
23 let (col_min, col_max, col_max_span, row_min, row_max, row_max_span) = get_known_child_positions(placements);
26
27 let negative_implicit_inline_tracks = col_min.implied_negative_implicit_tracks();
31 let explicit_inline_tracks = explicit_col_count;
32 let mut positive_implicit_inline_tracks = col_max.implied_positive_implicit_tracks(explicit_col_count);
33 let negative_implicit_block_tracks = row_min.implied_negative_implicit_tracks();
34 let explicit_block_tracks = explicit_row_count;
35 let mut positive_implicit_block_tracks = row_max.implied_positive_implicit_tracks(explicit_row_count);
36
37 let tot_inline_tracks = negative_implicit_inline_tracks + explicit_inline_tracks + positive_implicit_inline_tracks;
40 if tot_inline_tracks < col_max_span {
41 positive_implicit_inline_tracks = col_max_span - explicit_inline_tracks - negative_implicit_inline_tracks;
42 }
43
44 let tot_block_tracks = negative_implicit_block_tracks + explicit_block_tracks + positive_implicit_block_tracks;
45 if tot_block_tracks < row_max_span {
46 positive_implicit_block_tracks = row_max_span - explicit_block_tracks - negative_implicit_block_tracks;
47 }
48
49 let column_counts =
50 TrackCounts::from_raw(negative_implicit_inline_tracks, explicit_inline_tracks, positive_implicit_inline_tracks);
51
52 let row_counts =
53 TrackCounts::from_raw(negative_implicit_block_tracks, explicit_block_tracks, positive_implicit_block_tracks);
54
55 (column_counts, row_counts)
56}
57
58fn get_known_child_positions(
64 placements: &[ItemPlacement],
65) -> (OriginZeroLine, OriginZeroLine, u16, OriginZeroLine, OriginZeroLine, u16) {
66 let (mut col_min, mut col_max, mut col_max_span) = (OriginZeroLine(0), OriginZeroLine(0), 0);
67 let (mut row_min, mut row_max, mut row_max_span) = (OriginZeroLine(0), OriginZeroLine(0), 0);
68 placements.iter().for_each(|placement| {
69 let (child_col_min, child_col_max, child_col_span) = child_min_line_max_line_span(placement.horizontal);
72 let (child_row_min, child_row_max, child_row_span) = child_min_line_max_line_span(placement.vertical);
73
74 col_min = min(col_min, child_col_min);
75 col_max = max(col_max, child_col_max);
76 col_max_span = max(col_max_span, child_col_span);
77 row_min = min(row_min, child_row_min);
78 row_max = max(row_max, child_row_max);
79 row_max_span = max(row_max_span, child_row_span);
80 });
81
82 (col_min, col_max, col_max_span, row_min, row_max, row_max_span)
83}
84
85#[inline]
90fn child_min_line_max_line_span(oz_line: Line<OriginZeroGridPlacement>) -> (OriginZeroLine, OriginZeroLine, u16) {
91 use GenericGridPlacement::*;
92
93 let min = match (oz_line.start, oz_line.end) {
100 (Line(track1), Line(track2)) => {
102 if track1 == track2 {
104 track1
105 } else {
106 min(track1, track2)
107 }
108 }
109
110 (Line(track), Auto) => track,
112 (Line(track), Span(_)) => track,
113
114 (Auto, Line(track)) => track - 1,
117 (Span(span), Line(track)) => track - span,
118
119 (Auto | Span(_), Auto | Span(_)) => OriginZeroLine(0),
122 };
123
124 let max = match (oz_line.start, oz_line.end) {
125 (Line(track1), Line(track2)) => {
127 if track1 == track2 {
129 track1 + 1
130 } else {
131 max(track1, track2)
132 }
133 }
134
135 (Line(track), Auto) => track + 1,
137 (Line(track), Span(span)) => track + span,
138
139 (Auto, Line(track)) => track,
141 (Span(_), Line(track)) => track,
142
143 (Auto | Span(_), Auto | Span(_)) => OriginZeroLine(0),
146 };
147
148 let span = match (oz_line.start, oz_line.end) {
151 (Auto | Span(_), Auto | Span(_)) => oz_line.indefinite_span(),
152 _ => 1,
153 };
154
155 let clamped_min = OriginZeroLine(min.0.max(MIN_OZ_LINE));
159 let clamped_max = OriginZeroLine(max.0.min(MAX_OZ_LINE));
160
161 (clamped_min, clamped_max, span)
162}
163
164#[allow(clippy::bool_assert_comparison)]
165#[cfg(test)]
166mod tests {
167 mod test_child_min_max_line {
168 use super::super::child_min_line_max_line_span;
169 use super::super::OriginZeroLine;
170 use crate::geometry::Line;
171 use crate::style::GridPlacement;
172 use crate::style_helpers::*;
173
174 #[test]
175 fn child_min_max_line_auto() {
176 let (min_col, max_col, span) = child_min_line_max_line_span(
177 Line::<GridPlacement<String>> { start: line(5), end: span(6) }.into_origin_zero_ignoring_named(6),
178 );
179 assert_eq!(min_col, OriginZeroLine(4));
180 assert_eq!(max_col, OriginZeroLine(10));
181 assert_eq!(span, 1);
182 }
183
184 #[test]
185 fn child_min_max_line_negative_track() {
186 let (min_col, max_col, span) = child_min_line_max_line_span(
187 Line::<GridPlacement<String>> { start: line(-5), end: span(3) }.into_origin_zero_ignoring_named(6),
188 );
189 assert_eq!(min_col, OriginZeroLine(2));
190 assert_eq!(max_col, OriginZeroLine(5));
191 assert_eq!(span, 1);
192 }
193 }
194
195 mod test_initial_grid_sizing {
196 use super::super::{compute_grid_size_estimate, TrackCounts};
197 use crate::compute::grid::util::test_helpers::*;
198 use crate::compute::grid::NamedLineResolver;
199 use crate::style_helpers::*;
200 use crate::Style;
201
202 fn estimate(
203 explicit_col_count: u16,
204 explicit_row_count: u16,
205 child_styles: &[Style],
206 ) -> (TrackCounts, TrackCounts) {
207 let mut name_resolver = NamedLineResolver::new(&Style::DEFAULT, 0, 0);
208 name_resolver.set_explicit_column_count(explicit_col_count);
209 name_resolver.set_explicit_row_count(explicit_row_count);
210 let placements =
211 resolve_named_lines(child_styles.iter(), &name_resolver, explicit_col_count, explicit_row_count);
212 compute_grid_size_estimate(explicit_col_count, explicit_row_count, &placements)
213 }
214
215 #[test]
216 fn explicit_grid_sizing_with_children() {
217 let explicit_col_count = 6;
218 let explicit_row_count = 8;
219 let child_styles = [
220 (line(1), span(2), line(2), auto()).into_grid_child(),
221 (line(-4), auto(), line(-2), auto()).into_grid_child(),
222 ];
223 let (inline, block) = estimate(explicit_col_count, explicit_row_count, &child_styles);
224 assert_eq!(inline.negative_implicit, 0);
225 assert_eq!(inline.explicit, explicit_col_count);
226 assert_eq!(inline.positive_implicit, 0);
227 assert_eq!(block.negative_implicit, 0);
228 assert_eq!(block.explicit, explicit_row_count);
229 assert_eq!(block.positive_implicit, 0);
230 }
231
232 #[test]
233 fn negative_implicit_grid_sizing() {
234 let explicit_col_count = 4;
235 let explicit_row_count = 4;
236 let child_styles = [
237 (line(-6), span(2), line(-8), auto()).into_grid_child(),
238 (line(4), auto(), line(3), auto()).into_grid_child(),
239 ];
240 let (inline, block) = estimate(explicit_col_count, explicit_row_count, &child_styles);
241 assert_eq!(inline.negative_implicit, 1);
242 assert_eq!(inline.explicit, explicit_col_count);
243 assert_eq!(inline.positive_implicit, 0);
244 assert_eq!(block.negative_implicit, 3);
245 assert_eq!(block.explicit, explicit_row_count);
246 assert_eq!(block.positive_implicit, 0);
247 }
248 }
249}