bevy_ui/layout/
convert.rs

1use taffy::style_helpers;
2
3use crate::{
4    AlignContent, AlignItems, AlignSelf, BoxSizing, Display, FlexDirection, FlexWrap, GridAutoFlow,
5    GridPlacement, GridTrack, GridTrackRepetition, JustifyContent, JustifyItems, JustifySelf,
6    MaxTrackSizingFunction, MinTrackSizingFunction, Node, OverflowAxis, PositionType,
7    RepeatedGridTrack, UiRect, Val,
8};
9
10use super::LayoutContext;
11
12impl Val {
13    fn into_length_percentage_auto(
14        self,
15        context: &LayoutContext,
16    ) -> taffy::style::LengthPercentageAuto {
17        match self {
18            Val::Auto => taffy::style::LengthPercentageAuto::Auto,
19            Val::Percent(value) => taffy::style::LengthPercentageAuto::Percent(value / 100.),
20            Val::Px(value) => {
21                taffy::style::LengthPercentageAuto::Length(context.scale_factor * value)
22            }
23            Val::VMin(value) => taffy::style::LengthPercentageAuto::Length(
24                context.physical_size.min_element() * value / 100.,
25            ),
26            Val::VMax(value) => taffy::style::LengthPercentageAuto::Length(
27                context.physical_size.max_element() * value / 100.,
28            ),
29            Val::Vw(value) => {
30                taffy::style::LengthPercentageAuto::Length(context.physical_size.x * value / 100.)
31            }
32            Val::Vh(value) => {
33                taffy::style::LengthPercentageAuto::Length(context.physical_size.y * value / 100.)
34            }
35        }
36    }
37
38    fn into_length_percentage(self, context: &LayoutContext) -> taffy::style::LengthPercentage {
39        match self.into_length_percentage_auto(context) {
40            taffy::style::LengthPercentageAuto::Auto => taffy::style::LengthPercentage::Length(0.0),
41            taffy::style::LengthPercentageAuto::Percent(value) => {
42                taffy::style::LengthPercentage::Percent(value)
43            }
44            taffy::style::LengthPercentageAuto::Length(value) => {
45                taffy::style::LengthPercentage::Length(value)
46            }
47        }
48    }
49
50    fn into_dimension(self, context: &LayoutContext) -> taffy::style::Dimension {
51        self.into_length_percentage_auto(context).into()
52    }
53}
54
55impl UiRect {
56    fn map_to_taffy_rect<T>(self, map_fn: impl Fn(Val) -> T) -> taffy::geometry::Rect<T> {
57        taffy::geometry::Rect {
58            left: map_fn(self.left),
59            right: map_fn(self.right),
60            top: map_fn(self.top),
61            bottom: map_fn(self.bottom),
62        }
63    }
64}
65
66pub fn from_node(node: &Node, context: &LayoutContext, ignore_border: bool) -> taffy::style::Style {
67    taffy::style::Style {
68        display: node.display.into(),
69        box_sizing: node.box_sizing.into(),
70        item_is_table: false,
71        text_align: taffy::TextAlign::Auto,
72        overflow: taffy::Point {
73            x: node.overflow.x.into(),
74            y: node.overflow.y.into(),
75        },
76        scrollbar_width: node.scrollbar_width * context.scale_factor,
77        position: node.position_type.into(),
78        flex_direction: node.flex_direction.into(),
79        flex_wrap: node.flex_wrap.into(),
80        align_items: node.align_items.into(),
81        justify_items: node.justify_items.into(),
82        align_self: node.align_self.into(),
83        justify_self: node.justify_self.into(),
84        align_content: node.align_content.into(),
85        justify_content: node.justify_content.into(),
86        inset: taffy::Rect {
87            left: node.left.into_length_percentage_auto(context),
88            right: node.right.into_length_percentage_auto(context),
89            top: node.top.into_length_percentage_auto(context),
90            bottom: node.bottom.into_length_percentage_auto(context),
91        },
92        margin: node
93            .margin
94            .map_to_taffy_rect(|m| m.into_length_percentage_auto(context)),
95        padding: node
96            .padding
97            .map_to_taffy_rect(|m| m.into_length_percentage(context)),
98        // Ignore border for leaf nodes as it isn't implemented in the rendering engine.
99        // TODO: Implement rendering of border for leaf nodes
100        border: if ignore_border {
101            taffy::Rect::zero()
102        } else {
103            node.border
104                .map_to_taffy_rect(|m| m.into_length_percentage(context))
105        },
106        flex_grow: node.flex_grow,
107        flex_shrink: node.flex_shrink,
108        flex_basis: node.flex_basis.into_dimension(context),
109        size: taffy::Size {
110            width: node.width.into_dimension(context),
111            height: node.height.into_dimension(context),
112        },
113        min_size: taffy::Size {
114            width: node.min_width.into_dimension(context),
115            height: node.min_height.into_dimension(context),
116        },
117        max_size: taffy::Size {
118            width: node.max_width.into_dimension(context),
119            height: node.max_height.into_dimension(context),
120        },
121        aspect_ratio: node.aspect_ratio,
122        gap: taffy::Size {
123            width: node.column_gap.into_length_percentage(context),
124            height: node.row_gap.into_length_percentage(context),
125        },
126        grid_auto_flow: node.grid_auto_flow.into(),
127        grid_template_rows: node
128            .grid_template_rows
129            .iter()
130            .map(|track| track.clone_into_repeated_taffy_track(context))
131            .collect::<Vec<_>>(),
132        grid_template_columns: node
133            .grid_template_columns
134            .iter()
135            .map(|track| track.clone_into_repeated_taffy_track(context))
136            .collect::<Vec<_>>(),
137        grid_auto_rows: node
138            .grid_auto_rows
139            .iter()
140            .map(|track| track.into_taffy_track(context))
141            .collect::<Vec<_>>(),
142        grid_auto_columns: node
143            .grid_auto_columns
144            .iter()
145            .map(|track| track.into_taffy_track(context))
146            .collect::<Vec<_>>(),
147        grid_row: node.grid_row.into(),
148        grid_column: node.grid_column.into(),
149    }
150}
151
152impl From<AlignItems> for Option<taffy::style::AlignItems> {
153    fn from(value: AlignItems) -> Self {
154        match value {
155            AlignItems::Default => None,
156            AlignItems::Start => taffy::style::AlignItems::Start.into(),
157            AlignItems::End => taffy::style::AlignItems::End.into(),
158            AlignItems::FlexStart => taffy::style::AlignItems::FlexStart.into(),
159            AlignItems::FlexEnd => taffy::style::AlignItems::FlexEnd.into(),
160            AlignItems::Center => taffy::style::AlignItems::Center.into(),
161            AlignItems::Baseline => taffy::style::AlignItems::Baseline.into(),
162            AlignItems::Stretch => taffy::style::AlignItems::Stretch.into(),
163        }
164    }
165}
166
167impl From<JustifyItems> for Option<taffy::style::JustifyItems> {
168    fn from(value: JustifyItems) -> Self {
169        match value {
170            JustifyItems::Default => None,
171            JustifyItems::Start => taffy::style::JustifyItems::Start.into(),
172            JustifyItems::End => taffy::style::JustifyItems::End.into(),
173            JustifyItems::Center => taffy::style::JustifyItems::Center.into(),
174            JustifyItems::Baseline => taffy::style::JustifyItems::Baseline.into(),
175            JustifyItems::Stretch => taffy::style::JustifyItems::Stretch.into(),
176        }
177    }
178}
179
180impl From<AlignSelf> for Option<taffy::style::AlignSelf> {
181    fn from(value: AlignSelf) -> Self {
182        match value {
183            AlignSelf::Auto => None,
184            AlignSelf::Start => taffy::style::AlignSelf::Start.into(),
185            AlignSelf::End => taffy::style::AlignSelf::End.into(),
186            AlignSelf::FlexStart => taffy::style::AlignSelf::FlexStart.into(),
187            AlignSelf::FlexEnd => taffy::style::AlignSelf::FlexEnd.into(),
188            AlignSelf::Center => taffy::style::AlignSelf::Center.into(),
189            AlignSelf::Baseline => taffy::style::AlignSelf::Baseline.into(),
190            AlignSelf::Stretch => taffy::style::AlignSelf::Stretch.into(),
191        }
192    }
193}
194
195impl From<JustifySelf> for Option<taffy::style::JustifySelf> {
196    fn from(value: JustifySelf) -> Self {
197        match value {
198            JustifySelf::Auto => None,
199            JustifySelf::Start => taffy::style::JustifySelf::Start.into(),
200            JustifySelf::End => taffy::style::JustifySelf::End.into(),
201            JustifySelf::Center => taffy::style::JustifySelf::Center.into(),
202            JustifySelf::Baseline => taffy::style::JustifySelf::Baseline.into(),
203            JustifySelf::Stretch => taffy::style::JustifySelf::Stretch.into(),
204        }
205    }
206}
207
208impl From<AlignContent> for Option<taffy::style::AlignContent> {
209    fn from(value: AlignContent) -> Self {
210        match value {
211            AlignContent::Default => None,
212            AlignContent::Start => taffy::style::AlignContent::Start.into(),
213            AlignContent::End => taffy::style::AlignContent::End.into(),
214            AlignContent::FlexStart => taffy::style::AlignContent::FlexStart.into(),
215            AlignContent::FlexEnd => taffy::style::AlignContent::FlexEnd.into(),
216            AlignContent::Center => taffy::style::AlignContent::Center.into(),
217            AlignContent::Stretch => taffy::style::AlignContent::Stretch.into(),
218            AlignContent::SpaceBetween => taffy::style::AlignContent::SpaceBetween.into(),
219            AlignContent::SpaceAround => taffy::style::AlignContent::SpaceAround.into(),
220            AlignContent::SpaceEvenly => taffy::style::AlignContent::SpaceEvenly.into(),
221        }
222    }
223}
224
225impl From<JustifyContent> for Option<taffy::style::JustifyContent> {
226    fn from(value: JustifyContent) -> Self {
227        match value {
228            JustifyContent::Default => None,
229            JustifyContent::Start => taffy::style::JustifyContent::Start.into(),
230            JustifyContent::End => taffy::style::JustifyContent::End.into(),
231            JustifyContent::FlexStart => taffy::style::JustifyContent::FlexStart.into(),
232            JustifyContent::FlexEnd => taffy::style::JustifyContent::FlexEnd.into(),
233            JustifyContent::Center => taffy::style::JustifyContent::Center.into(),
234            JustifyContent::Stretch => taffy::style::JustifyContent::Stretch.into(),
235            JustifyContent::SpaceBetween => taffy::style::JustifyContent::SpaceBetween.into(),
236            JustifyContent::SpaceAround => taffy::style::JustifyContent::SpaceAround.into(),
237            JustifyContent::SpaceEvenly => taffy::style::JustifyContent::SpaceEvenly.into(),
238        }
239    }
240}
241
242impl From<Display> for taffy::style::Display {
243    fn from(value: Display) -> Self {
244        match value {
245            Display::Flex => taffy::style::Display::Flex,
246            Display::Grid => taffy::style::Display::Grid,
247            Display::Block => taffy::style::Display::Block,
248            Display::None => taffy::style::Display::None,
249        }
250    }
251}
252
253impl From<BoxSizing> for taffy::style::BoxSizing {
254    fn from(value: BoxSizing) -> Self {
255        match value {
256            BoxSizing::BorderBox => taffy::style::BoxSizing::BorderBox,
257            BoxSizing::ContentBox => taffy::style::BoxSizing::ContentBox,
258        }
259    }
260}
261
262impl From<OverflowAxis> for taffy::style::Overflow {
263    fn from(value: OverflowAxis) -> Self {
264        match value {
265            OverflowAxis::Visible => taffy::style::Overflow::Visible,
266            OverflowAxis::Clip => taffy::style::Overflow::Clip,
267            OverflowAxis::Hidden => taffy::style::Overflow::Hidden,
268            OverflowAxis::Scroll => taffy::style::Overflow::Scroll,
269        }
270    }
271}
272
273impl From<FlexDirection> for taffy::style::FlexDirection {
274    fn from(value: FlexDirection) -> Self {
275        match value {
276            FlexDirection::Row => taffy::style::FlexDirection::Row,
277            FlexDirection::Column => taffy::style::FlexDirection::Column,
278            FlexDirection::RowReverse => taffy::style::FlexDirection::RowReverse,
279            FlexDirection::ColumnReverse => taffy::style::FlexDirection::ColumnReverse,
280        }
281    }
282}
283
284impl From<PositionType> for taffy::style::Position {
285    fn from(value: PositionType) -> Self {
286        match value {
287            PositionType::Relative => taffy::style::Position::Relative,
288            PositionType::Absolute => taffy::style::Position::Absolute,
289        }
290    }
291}
292
293impl From<FlexWrap> for taffy::style::FlexWrap {
294    fn from(value: FlexWrap) -> Self {
295        match value {
296            FlexWrap::NoWrap => taffy::style::FlexWrap::NoWrap,
297            FlexWrap::Wrap => taffy::style::FlexWrap::Wrap,
298            FlexWrap::WrapReverse => taffy::style::FlexWrap::WrapReverse,
299        }
300    }
301}
302
303impl From<GridAutoFlow> for taffy::style::GridAutoFlow {
304    fn from(value: GridAutoFlow) -> Self {
305        match value {
306            GridAutoFlow::Row => taffy::style::GridAutoFlow::Row,
307            GridAutoFlow::RowDense => taffy::style::GridAutoFlow::RowDense,
308            GridAutoFlow::Column => taffy::style::GridAutoFlow::Column,
309            GridAutoFlow::ColumnDense => taffy::style::GridAutoFlow::ColumnDense,
310        }
311    }
312}
313
314impl From<GridPlacement> for taffy::geometry::Line<taffy::style::GridPlacement> {
315    fn from(value: GridPlacement) -> Self {
316        let span = value.get_span().unwrap_or(1);
317        match (value.get_start(), value.get_end()) {
318            (Some(start), Some(end)) => taffy::geometry::Line {
319                start: style_helpers::line(start),
320                end: style_helpers::line(end),
321            },
322            (Some(start), None) => taffy::geometry::Line {
323                start: style_helpers::line(start),
324                end: style_helpers::span(span),
325            },
326            (None, Some(end)) => taffy::geometry::Line {
327                start: style_helpers::span(span),
328                end: style_helpers::line(end),
329            },
330            (None, None) => style_helpers::span(span),
331        }
332    }
333}
334
335impl MinTrackSizingFunction {
336    fn into_taffy(self, context: &LayoutContext) -> taffy::style::MinTrackSizingFunction {
337        match self {
338            MinTrackSizingFunction::Px(val) => taffy::style::MinTrackSizingFunction::Fixed(
339                Val::Px(val).into_length_percentage(context),
340            ),
341            MinTrackSizingFunction::Percent(val) => taffy::style::MinTrackSizingFunction::Fixed(
342                Val::Percent(val).into_length_percentage(context),
343            ),
344            MinTrackSizingFunction::Auto => taffy::style::MinTrackSizingFunction::Auto,
345            MinTrackSizingFunction::MinContent => taffy::style::MinTrackSizingFunction::MinContent,
346            MinTrackSizingFunction::MaxContent => taffy::style::MinTrackSizingFunction::MaxContent,
347            MinTrackSizingFunction::VMin(val) => taffy::style::MinTrackSizingFunction::Fixed(
348                Val::VMin(val).into_length_percentage(context),
349            ),
350            MinTrackSizingFunction::VMax(val) => taffy::style::MinTrackSizingFunction::Fixed(
351                Val::VMax(val).into_length_percentage(context),
352            ),
353            MinTrackSizingFunction::Vh(val) => taffy::style::MinTrackSizingFunction::Fixed(
354                Val::Vh(val).into_length_percentage(context),
355            ),
356            MinTrackSizingFunction::Vw(val) => taffy::style::MinTrackSizingFunction::Fixed(
357                Val::Vw(val).into_length_percentage(context),
358            ),
359        }
360    }
361}
362
363impl MaxTrackSizingFunction {
364    fn into_taffy(self, context: &LayoutContext) -> taffy::style::MaxTrackSizingFunction {
365        match self {
366            MaxTrackSizingFunction::Px(val) => taffy::style::MaxTrackSizingFunction::Fixed(
367                Val::Px(val).into_length_percentage(context),
368            ),
369            MaxTrackSizingFunction::Percent(val) => taffy::style::MaxTrackSizingFunction::Fixed(
370                Val::Percent(val).into_length_percentage(context),
371            ),
372            MaxTrackSizingFunction::Auto => taffy::style::MaxTrackSizingFunction::Auto,
373            MaxTrackSizingFunction::MinContent => taffy::style::MaxTrackSizingFunction::MinContent,
374            MaxTrackSizingFunction::MaxContent => taffy::style::MaxTrackSizingFunction::MaxContent,
375            MaxTrackSizingFunction::FitContentPx(val) => {
376                taffy::style::MaxTrackSizingFunction::FitContent(
377                    Val::Px(val).into_length_percentage(context),
378                )
379            }
380            MaxTrackSizingFunction::FitContentPercent(val) => {
381                taffy::style::MaxTrackSizingFunction::FitContent(
382                    Val::Percent(val).into_length_percentage(context),
383                )
384            }
385            MaxTrackSizingFunction::Fraction(fraction) => {
386                taffy::style::MaxTrackSizingFunction::Fraction(fraction)
387            }
388            MaxTrackSizingFunction::VMin(val) => taffy::style::MaxTrackSizingFunction::Fixed(
389                Val::VMin(val).into_length_percentage(context),
390            ),
391            MaxTrackSizingFunction::VMax(val) => taffy::style::MaxTrackSizingFunction::Fixed(
392                Val::VMax(val).into_length_percentage(context),
393            ),
394            MaxTrackSizingFunction::Vh(val) => taffy::style::MaxTrackSizingFunction::Fixed(
395                Val::Vh(val).into_length_percentage(context),
396            ),
397            MaxTrackSizingFunction::Vw(val) => taffy::style::MaxTrackSizingFunction::Fixed(
398                Val::Vw(val).into_length_percentage(context),
399            ),
400        }
401    }
402}
403
404impl GridTrack {
405    fn into_taffy_track(
406        self,
407        context: &LayoutContext,
408    ) -> taffy::style::NonRepeatedTrackSizingFunction {
409        let min = self.min_sizing_function.into_taffy(context);
410        let max = self.max_sizing_function.into_taffy(context);
411        style_helpers::minmax(min, max)
412    }
413}
414
415impl RepeatedGridTrack {
416    fn clone_into_repeated_taffy_track(
417        &self,
418        context: &LayoutContext,
419    ) -> taffy::style::TrackSizingFunction {
420        if self.tracks.len() == 1 && self.repetition == GridTrackRepetition::Count(1) {
421            let min = self.tracks[0].min_sizing_function.into_taffy(context);
422            let max = self.tracks[0].max_sizing_function.into_taffy(context);
423            let taffy_track = style_helpers::minmax(min, max);
424            taffy::style::TrackSizingFunction::Single(taffy_track)
425        } else {
426            let taffy_tracks: Vec<_> = self
427                .tracks
428                .iter()
429                .map(|track| {
430                    let min = track.min_sizing_function.into_taffy(context);
431                    let max = track.max_sizing_function.into_taffy(context);
432                    style_helpers::minmax(min, max)
433                })
434                .collect();
435
436            match self.repetition {
437                GridTrackRepetition::Count(count) => style_helpers::repeat(count, taffy_tracks),
438                GridTrackRepetition::AutoFit => {
439                    style_helpers::repeat(taffy::style::GridTrackRepetition::AutoFit, taffy_tracks)
440                }
441                GridTrackRepetition::AutoFill => {
442                    style_helpers::repeat(taffy::style::GridTrackRepetition::AutoFill, taffy_tracks)
443                }
444            }
445        }
446    }
447}
448
449#[cfg(test)]
450mod tests {
451    use bevy_math::Vec2;
452
453    use super::*;
454
455    #[test]
456    fn test_convert_from() {
457        use sh::TaffyZero;
458        use taffy::style_helpers as sh;
459
460        let node = Node {
461            display: Display::Flex,
462            box_sizing: BoxSizing::ContentBox,
463            position_type: PositionType::Absolute,
464            left: Val::ZERO,
465            right: Val::Percent(50.),
466            top: Val::Px(12.),
467            bottom: Val::Auto,
468            flex_direction: FlexDirection::ColumnReverse,
469            flex_wrap: FlexWrap::WrapReverse,
470            align_items: AlignItems::Baseline,
471            align_self: AlignSelf::Start,
472            align_content: AlignContent::SpaceAround,
473            justify_items: JustifyItems::Default,
474            justify_self: JustifySelf::Center,
475            justify_content: JustifyContent::SpaceEvenly,
476            margin: UiRect {
477                left: Val::ZERO,
478                right: Val::Px(10.),
479                top: Val::Percent(15.),
480                bottom: Val::Auto,
481            },
482            padding: UiRect {
483                left: Val::Percent(13.),
484                right: Val::Px(21.),
485                top: Val::Auto,
486                bottom: Val::ZERO,
487            },
488            border: UiRect {
489                left: Val::Px(14.),
490                right: Val::ZERO,
491                top: Val::Auto,
492                bottom: Val::Percent(31.),
493            },
494            flex_grow: 1.,
495            flex_shrink: 0.,
496            flex_basis: Val::ZERO,
497            width: Val::ZERO,
498            height: Val::Auto,
499            min_width: Val::ZERO,
500            min_height: Val::ZERO,
501            max_width: Val::Auto,
502            max_height: Val::ZERO,
503            aspect_ratio: None,
504            overflow: crate::Overflow::clip(),
505            overflow_clip_margin: crate::OverflowClipMargin::default(),
506            scrollbar_width: 7.,
507            column_gap: Val::ZERO,
508            row_gap: Val::ZERO,
509            grid_auto_flow: GridAutoFlow::ColumnDense,
510            grid_template_rows: vec![
511                GridTrack::px(10.0),
512                GridTrack::percent(50.0),
513                GridTrack::fr(1.0),
514            ],
515            grid_template_columns: RepeatedGridTrack::px(5, 10.0),
516            grid_auto_rows: vec![
517                GridTrack::fit_content_px(10.0),
518                GridTrack::fit_content_percent(25.0),
519                GridTrack::flex(2.0),
520            ],
521            grid_auto_columns: vec![
522                GridTrack::auto(),
523                GridTrack::min_content(),
524                GridTrack::max_content(),
525            ],
526            grid_column: GridPlacement::start(4),
527            grid_row: GridPlacement::span(3),
528        };
529        let viewport_values = LayoutContext::new(1.0, Vec2::new(800., 600.));
530        let taffy_style = from_node(&node, &viewport_values, false);
531        assert_eq!(taffy_style.display, taffy::style::Display::Flex);
532        assert_eq!(taffy_style.box_sizing, taffy::style::BoxSizing::ContentBox);
533        assert_eq!(taffy_style.position, taffy::style::Position::Absolute);
534        assert_eq!(
535            taffy_style.inset.left,
536            taffy::style::LengthPercentageAuto::ZERO
537        );
538        assert_eq!(
539            taffy_style.inset.right,
540            taffy::style::LengthPercentageAuto::Percent(0.5)
541        );
542        assert_eq!(
543            taffy_style.inset.top,
544            taffy::style::LengthPercentageAuto::Length(12.)
545        );
546        assert_eq!(
547            taffy_style.inset.bottom,
548            taffy::style::LengthPercentageAuto::Auto
549        );
550        assert_eq!(
551            taffy_style.flex_direction,
552            taffy::style::FlexDirection::ColumnReverse
553        );
554        assert_eq!(taffy_style.flex_wrap, taffy::style::FlexWrap::WrapReverse);
555        assert_eq!(
556            taffy_style.align_items,
557            Some(taffy::style::AlignItems::Baseline)
558        );
559        assert_eq!(taffy_style.align_self, Some(taffy::style::AlignSelf::Start));
560        assert_eq!(
561            taffy_style.align_content,
562            Some(taffy::style::AlignContent::SpaceAround)
563        );
564        assert_eq!(
565            taffy_style.justify_content,
566            Some(taffy::style::JustifyContent::SpaceEvenly)
567        );
568        assert_eq!(taffy_style.justify_items, None);
569        assert_eq!(
570            taffy_style.justify_self,
571            Some(taffy::style::JustifySelf::Center)
572        );
573        assert_eq!(
574            taffy_style.margin.left,
575            taffy::style::LengthPercentageAuto::ZERO
576        );
577        assert_eq!(
578            taffy_style.margin.right,
579            taffy::style::LengthPercentageAuto::Length(10.)
580        );
581        assert_eq!(
582            taffy_style.margin.top,
583            taffy::style::LengthPercentageAuto::Percent(0.15)
584        );
585        assert_eq!(
586            taffy_style.margin.bottom,
587            taffy::style::LengthPercentageAuto::Auto
588        );
589        assert_eq!(
590            taffy_style.padding.left,
591            taffy::style::LengthPercentage::Percent(0.13)
592        );
593        assert_eq!(
594            taffy_style.padding.right,
595            taffy::style::LengthPercentage::Length(21.)
596        );
597        assert_eq!(
598            taffy_style.padding.top,
599            taffy::style::LengthPercentage::ZERO
600        );
601        assert_eq!(
602            taffy_style.padding.bottom,
603            taffy::style::LengthPercentage::ZERO
604        );
605        assert_eq!(
606            taffy_style.border.left,
607            taffy::style::LengthPercentage::Length(14.)
608        );
609        assert_eq!(
610            taffy_style.border.right,
611            taffy::style::LengthPercentage::ZERO
612        );
613        assert_eq!(taffy_style.border.top, taffy::style::LengthPercentage::ZERO);
614        assert_eq!(
615            taffy_style.border.bottom,
616            taffy::style::LengthPercentage::Percent(0.31)
617        );
618        assert_eq!(taffy_style.flex_grow, 1.);
619        assert_eq!(taffy_style.flex_shrink, 0.);
620        assert_eq!(taffy_style.flex_basis, taffy::style::Dimension::ZERO);
621        assert_eq!(taffy_style.size.width, taffy::style::Dimension::ZERO);
622        assert_eq!(taffy_style.size.height, taffy::style::Dimension::Auto);
623        assert_eq!(taffy_style.min_size.width, taffy::style::Dimension::ZERO);
624        assert_eq!(taffy_style.min_size.height, taffy::style::Dimension::ZERO);
625        assert_eq!(taffy_style.max_size.width, taffy::style::Dimension::Auto);
626        assert_eq!(taffy_style.max_size.height, taffy::style::Dimension::ZERO);
627        assert_eq!(taffy_style.aspect_ratio, None);
628        assert_eq!(taffy_style.scrollbar_width, 7.);
629        assert_eq!(taffy_style.gap.width, taffy::style::LengthPercentage::ZERO);
630        assert_eq!(taffy_style.gap.height, taffy::style::LengthPercentage::ZERO);
631        assert_eq!(
632            taffy_style.grid_auto_flow,
633            taffy::style::GridAutoFlow::ColumnDense
634        );
635        assert_eq!(
636            taffy_style.grid_template_rows,
637            vec![sh::length(10.0), sh::percent(0.5), sh::fr(1.0)]
638        );
639        assert_eq!(
640            taffy_style.grid_template_columns,
641            vec![sh::repeat(5, vec![sh::length(10.0)])]
642        );
643        assert_eq!(
644            taffy_style.grid_auto_rows,
645            vec![
646                sh::fit_content(taffy::style::LengthPercentage::Length(10.0)),
647                sh::fit_content(taffy::style::LengthPercentage::Percent(0.25)),
648                sh::minmax(sh::length(0.0), sh::fr(2.0)),
649            ]
650        );
651        assert_eq!(
652            taffy_style.grid_auto_columns,
653            vec![sh::auto(), sh::min_content(), sh::max_content()]
654        );
655        assert_eq!(
656            taffy_style.grid_column,
657            taffy::geometry::Line {
658                start: sh::line(4),
659                end: sh::span(1)
660            }
661        );
662        assert_eq!(taffy_style.grid_row, sh::span(3));
663    }
664
665    #[test]
666    fn test_into_length_percentage() {
667        use taffy::style::LengthPercentage;
668        let context = LayoutContext::new(2.0, Vec2::new(800., 600.));
669        let cases = [
670            (Val::Auto, LengthPercentage::Length(0.)),
671            (Val::Percent(1.), LengthPercentage::Percent(0.01)),
672            (Val::Px(1.), LengthPercentage::Length(2.)),
673            (Val::Vw(1.), LengthPercentage::Length(8.)),
674            (Val::Vh(1.), LengthPercentage::Length(6.)),
675            (Val::VMin(2.), LengthPercentage::Length(12.)),
676            (Val::VMax(2.), LengthPercentage::Length(16.)),
677        ];
678        for (val, length) in cases {
679            assert!(match (val.into_length_percentage(&context), length) {
680                (LengthPercentage::Length(a), LengthPercentage::Length(b))
681                | (LengthPercentage::Percent(a), LengthPercentage::Percent(b)) =>
682                    (a - b).abs() < 0.0001,
683                _ => false,
684            });
685        }
686    }
687}