layout/taffy/stylo_taffy/
wrapper.rs1use std::ops::Deref;
6
7use style::properties::ComputedValues;
8use style::values::CustomIdent;
9use style::values::computed::{GridTemplateAreas, LengthPercentage};
10use style::values::generics::grid::{TrackListValue, TrackRepeat, TrackSize};
11use style::values::specified::position::NamedArea;
12use style::{Atom, OwnedSlice};
13
14use super::{convert, stylo};
15
16pub struct TaffyStyloStyle<T: Deref<Target = ComputedValues>> {
19 pub style: T,
20 pub is_compressible_replaced: bool,
21}
22
23impl<T: Deref<Target = ComputedValues>> TaffyStyloStyle<T> {
24 pub fn new(style: T, is_compressible_replaced: bool) -> Self {
25 Self {
26 style,
27 is_compressible_replaced,
28 }
29 }
30}
31
32impl<T: Deref<Target = ComputedValues>> taffy::CoreStyle for TaffyStyloStyle<T> {
33 type CustomIdent = Atom;
34
35 #[inline]
36 fn box_generation_mode(&self) -> taffy::BoxGenerationMode {
37 convert::box_generation_mode(self.style.get_box().display)
38 }
39
40 #[inline]
41 fn is_block(&self) -> bool {
42 convert::is_block(self.style.get_box().display)
43 }
44
45 #[inline]
46 fn is_compressible_replaced(&self) -> bool {
47 self.is_compressible_replaced
48 }
49
50 #[inline]
51 fn box_sizing(&self) -> taffy::BoxSizing {
52 convert::box_sizing(self.style.get_position().box_sizing)
53 }
54
55 #[inline]
56 fn overflow(&self) -> taffy::Point<taffy::Overflow> {
57 let box_styles = self.style.get_box();
58 taffy::Point {
59 x: convert::overflow(box_styles.overflow_x),
60 y: convert::overflow(box_styles.overflow_y),
61 }
62 }
63
64 #[inline]
65 fn scrollbar_width(&self) -> f32 {
66 0.0
67 }
68
69 #[inline]
70 fn position(&self) -> taffy::Position {
71 convert::position(self.style.get_box().position)
72 }
73
74 #[inline]
75 fn inset(&self) -> taffy::Rect<taffy::LengthPercentageAuto> {
76 let position_styles = self.style.get_position();
77 taffy::Rect {
78 left: convert::inset(&position_styles.left),
79 right: convert::inset(&position_styles.right),
80 top: convert::inset(&position_styles.top),
81 bottom: convert::inset(&position_styles.bottom),
82 }
83 }
84
85 #[inline]
86 fn size(&self) -> taffy::Size<taffy::Dimension> {
87 let position_styles = self.style.get_position();
88 taffy::Size {
89 width: convert::dimension(&position_styles.width),
90 height: convert::dimension(&position_styles.height),
91 }
92 }
93
94 #[inline]
95 fn min_size(&self) -> taffy::Size<taffy::Dimension> {
96 let position_styles = self.style.get_position();
97 taffy::Size {
98 width: convert::dimension(&position_styles.min_width),
99 height: convert::dimension(&position_styles.min_height),
100 }
101 }
102
103 #[inline]
104 fn max_size(&self) -> taffy::Size<taffy::Dimension> {
105 let position_styles = self.style.get_position();
106 taffy::Size {
107 width: convert::max_size_dimension(&position_styles.max_width),
108 height: convert::max_size_dimension(&position_styles.max_height),
109 }
110 }
111
112 #[inline]
113 fn aspect_ratio(&self) -> Option<f32> {
114 convert::aspect_ratio(self.style.get_position().aspect_ratio)
115 }
116
117 #[inline]
118 fn margin(&self) -> taffy::Rect<taffy::LengthPercentageAuto> {
119 let margin_styles = self.style.get_margin();
120 taffy::Rect {
121 left: convert::margin(&margin_styles.margin_left),
122 right: convert::margin(&margin_styles.margin_right),
123 top: convert::margin(&margin_styles.margin_top),
124 bottom: convert::margin(&margin_styles.margin_bottom),
125 }
126 }
127
128 #[inline]
129 fn padding(&self) -> taffy::Rect<taffy::LengthPercentage> {
130 let padding_styles = self.style.get_padding();
131 taffy::Rect {
132 left: convert::length_percentage(&padding_styles.padding_left.0),
133 right: convert::length_percentage(&padding_styles.padding_right.0),
134 top: convert::length_percentage(&padding_styles.padding_top.0),
135 bottom: convert::length_percentage(&padding_styles.padding_bottom.0),
136 }
137 }
138
139 #[inline]
140 fn border(&self) -> taffy::Rect<taffy::LengthPercentage> {
141 let border_styles = self.style.get_border();
142 taffy::Rect {
143 left: taffy::LengthPercentage::length(border_styles.border_left_width.to_f32_px()),
144 right: taffy::LengthPercentage::length(border_styles.border_right_width.to_f32_px()),
145 top: taffy::LengthPercentage::length(border_styles.border_top_width.to_f32_px()),
146 bottom: taffy::LengthPercentage::length(border_styles.border_bottom_width.to_f32_px()),
147 }
148 }
149}
150
151type SliceMapIter<'a, Input, Output> =
152 core::iter::Map<core::slice::Iter<'a, Input>, for<'c> fn(&'c Input) -> Output>;
153type SliceMapRefIter<'a, Input, Output> =
154 core::iter::Map<core::slice::Iter<'a, Input>, for<'c> fn(&'c Input) -> &'c Output>;
155
156type LineNameSetIter<'a> = SliceMapRefIter<'a, CustomIdent, Atom>;
158type LineNameIter<'a> = core::iter::Map<
159 core::slice::Iter<'a, OwnedSlice<CustomIdent>>,
160 fn(&OwnedSlice<CustomIdent>) -> LineNameSetIter<'_>,
161>;
162
163#[derive(Clone)]
164pub struct StyloLineNameIter<'a>(LineNameIter<'a>);
165impl<'a> StyloLineNameIter<'a> {
166 fn new(names: &'a OwnedSlice<OwnedSlice<CustomIdent>>) -> Self {
167 Self(names.iter().map(|names| names.iter().map(|ident| &ident.0)))
168 }
169}
170impl<'a> Iterator for StyloLineNameIter<'a> {
171 type Item = core::iter::Map<core::slice::Iter<'a, CustomIdent>, fn(&CustomIdent) -> &Atom>;
172 fn next(&mut self) -> Option<Self::Item> {
173 self.0.next()
174 }
175 fn size_hint(&self) -> (usize, Option<usize>) {
176 self.0.size_hint()
177 }
178}
179impl ExactSizeIterator for StyloLineNameIter<'_> {}
180impl<'a> taffy::TemplateLineNames<'a, Atom> for StyloLineNameIter<'a> {
181 type LineNameSet<'b>
182 = SliceMapRefIter<'b, CustomIdent, Atom>
183 where
184 Self: 'b;
185}
186
187pub struct RepetitionWrapper<'a>(&'a TrackRepeat<LengthPercentage, i32>);
188
189impl taffy::GenericRepetition for RepetitionWrapper<'_> {
190 type CustomIdent = Atom;
191
192 type RepetitionTrackList<'a>
193 = SliceMapIter<'a, stylo::TrackSize<LengthPercentage>, taffy::TrackSizingFunction>
194 where
195 Self: 'a;
196
197 type TemplateLineNames<'a>
198 = StyloLineNameIter<'a>
199 where
200 Self: 'a;
201
202 fn count(&self) -> taffy::RepetitionCount {
203 convert::track_repeat(self.0.count)
204 }
205
206 fn tracks(&self) -> Self::RepetitionTrackList<'_> {
207 self.0.track_sizes.iter().map(convert::track_size)
208 }
209
210 fn lines_names(&self) -> Self::TemplateLineNames<'_> {
211 StyloLineNameIter::new(&self.0.line_names)
212 }
213}
214
215impl<T: Deref<Target = ComputedValues>> taffy::GridContainerStyle for TaffyStyloStyle<T> {
216 type Repetition<'a>
217 = RepetitionWrapper<'a>
218 where
219 Self: 'a;
220
221 type TemplateTrackList<'a>
222 = core::iter::Map<
223 core::slice::Iter<'a, TrackListValue<LengthPercentage, i32>>,
224 fn(
225 &'a TrackListValue<LengthPercentage, i32>,
226 ) -> taffy::GenericGridTemplateComponent<Atom, RepetitionWrapper<'a>>,
227 >
228 where
229 Self: 'a;
230
231 type AutoTrackList<'a>
232 = SliceMapIter<'a, TrackSize<LengthPercentage>, taffy::TrackSizingFunction>
233 where
234 Self: 'a;
235
236 type TemplateLineNames<'a>
237 = StyloLineNameIter<'a>
238 where
239 Self: 'a;
240 type GridTemplateAreas<'a>
241 = SliceMapIter<'a, NamedArea, taffy::GridTemplateArea<Atom>>
242 where
243 Self: 'a;
244
245 #[inline]
246 fn grid_template_rows(&self) -> Option<Self::TemplateTrackList<'_>> {
247 match &self.style.get_position().grid_template_rows {
248 stylo::GenericGridTemplateComponent::None => None,
249 stylo::GenericGridTemplateComponent::TrackList(list) => {
250 Some(list.values.iter().map(|track| match track {
251 stylo::TrackListValue::TrackSize(size) => {
252 taffy::GenericGridTemplateComponent::Single(convert::track_size(size))
253 },
254 stylo::TrackListValue::TrackRepeat(repeat) => {
255 taffy::GenericGridTemplateComponent::Repeat(RepetitionWrapper(repeat))
256 },
257 }))
258 },
259
260 stylo::GenericGridTemplateComponent::Subgrid(_) => None,
262 stylo::GenericGridTemplateComponent::Masonry => None,
263 }
264 }
265
266 #[inline]
267 fn grid_template_columns(&self) -> Option<Self::TemplateTrackList<'_>> {
268 match &self.style.get_position().grid_template_columns {
269 stylo::GenericGridTemplateComponent::None => None,
270 stylo::GenericGridTemplateComponent::TrackList(list) => {
271 Some(list.values.iter().map(|track| match track {
272 stylo::TrackListValue::TrackSize(size) => {
273 taffy::GenericGridTemplateComponent::Single(convert::track_size(size))
274 },
275 stylo::TrackListValue::TrackRepeat(repeat) => {
276 taffy::GenericGridTemplateComponent::Repeat(RepetitionWrapper(repeat))
277 },
278 }))
279 },
280
281 stylo::GenericGridTemplateComponent::Subgrid(_) => None,
283 stylo::GenericGridTemplateComponent::Masonry => None,
284 }
285 }
286
287 #[inline]
288 fn grid_auto_rows(&self) -> Self::AutoTrackList<'_> {
289 self.style
290 .get_position()
291 .grid_auto_rows
292 .0
293 .iter()
294 .map(convert::track_size)
295 }
296
297 #[inline]
298 fn grid_auto_columns(&self) -> Self::AutoTrackList<'_> {
299 self.style
300 .get_position()
301 .grid_auto_columns
302 .0
303 .iter()
304 .map(convert::track_size)
305 }
306
307 fn grid_template_areas(&self) -> Option<Self::GridTemplateAreas<'_>> {
308 match &self.style.get_position().grid_template_areas {
309 GridTemplateAreas::Areas(areas) => {
310 Some(areas.0.areas.iter().map(|area| taffy::GridTemplateArea {
311 name: area.name.clone(),
312 row_start: area.rows.start as u16,
313 row_end: area.rows.end as u16,
314 column_start: area.columns.start as u16,
315 column_end: area.columns.end as u16,
316 }))
317 },
318 GridTemplateAreas::None => None,
319 }
320 }
321
322 fn grid_template_column_names(&self) -> Option<Self::TemplateLineNames<'_>> {
323 match &self.style.get_position().grid_template_columns {
324 stylo::GenericGridTemplateComponent::None => None,
325 stylo::GenericGridTemplateComponent::TrackList(list) => {
326 Some(StyloLineNameIter::new(&list.line_names))
327 },
328 stylo::GenericGridTemplateComponent::Subgrid(_) => None,
330 stylo::GenericGridTemplateComponent::Masonry => None,
331 }
332 }
333
334 fn grid_template_row_names(&self) -> Option<Self::TemplateLineNames<'_>> {
335 match &self.style.get_position().grid_template_rows {
336 stylo::GenericGridTemplateComponent::None => None,
337 stylo::GenericGridTemplateComponent::TrackList(list) => {
338 Some(StyloLineNameIter::new(&list.line_names))
339 },
340 stylo::GenericGridTemplateComponent::Subgrid(_) => None,
342 stylo::GenericGridTemplateComponent::Masonry => None,
343 }
344 }
345
346 #[inline]
347 fn grid_auto_flow(&self) -> taffy::GridAutoFlow {
348 convert::grid_auto_flow(self.style.get_position().grid_auto_flow)
349 }
350
351 #[inline]
352 fn gap(&self) -> taffy::Size<taffy::LengthPercentage> {
353 let position_styles = self.style.get_position();
354 taffy::Size {
355 width: convert::gap(&position_styles.column_gap),
356 height: convert::gap(&position_styles.row_gap),
357 }
358 }
359
360 #[inline]
361 fn align_content(&self) -> Option<taffy::AlignContent> {
362 convert::content_alignment(self.style.get_position().align_content.0)
363 }
364
365 #[inline]
366 fn justify_content(&self) -> Option<taffy::JustifyContent> {
367 convert::content_alignment(self.style.get_position().justify_content.0)
368 }
369
370 #[inline]
371 fn align_items(&self) -> Option<taffy::AlignItems> {
372 convert::item_alignment(self.style.get_position().align_items.0)
373 }
374
375 #[inline]
376 fn justify_items(&self) -> Option<taffy::AlignItems> {
377 convert::item_alignment(self.style.get_position().justify_items.computed.0)
378 }
379}
380
381impl<T: Deref<Target = ComputedValues>> taffy::GridItemStyle for TaffyStyloStyle<T> {
382 #[inline]
383 fn grid_row(&self) -> taffy::Line<taffy::GridPlacement<Atom>> {
384 let position_styles = self.style.get_position();
385 taffy::Line {
386 start: convert::grid_line(&position_styles.grid_row_start),
387 end: convert::grid_line(&position_styles.grid_row_end),
388 }
389 }
390
391 #[inline]
392 fn grid_column(&self) -> taffy::Line<taffy::GridPlacement<Atom>> {
393 let position_styles = self.style.get_position();
394 taffy::Line {
395 start: convert::grid_line(&position_styles.grid_column_start),
396 end: convert::grid_line(&position_styles.grid_column_end),
397 }
398 }
399
400 #[inline]
401 fn align_self(&self) -> Option<taffy::AlignSelf> {
402 convert::item_alignment(self.style.get_position().align_self.0.0)
403 }
404
405 #[inline]
406 fn justify_self(&self) -> Option<taffy::AlignSelf> {
407 convert::item_alignment(self.style.get_position().justify_self.0.0)
408 }
409}