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