• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Generic CSS alignment code that is shared between both the Flexbox and CSS Grid algorithms.
2 use crate::style::AlignContent;
3 
4 /// Implement fallback alignment.
5 ///
6 /// In addition to the spec at https://www.w3.org/TR/css-align-3/ this implementation follows
7 /// the resolution of https://github.com/w3c/csswg-drafts/issues/10154
apply_alignment_fallback( free_space: f32, num_items: usize, mut alignment_mode: AlignContent, mut is_safe: bool, ) -> AlignContent8 pub(crate) fn apply_alignment_fallback(
9     free_space: f32,
10     num_items: usize,
11     mut alignment_mode: AlignContent,
12     mut is_safe: bool,
13 ) -> AlignContent {
14     // Fallback occurs in two cases:
15 
16     // 1. If there is only a single item being aligned and alignment is a distributed alignment keyword
17     //    https://www.w3.org/TR/css-align-3/#distribution-values
18     if num_items <= 1 || free_space <= 0.0 {
19         (alignment_mode, is_safe) = match alignment_mode {
20             AlignContent::Stretch => (AlignContent::FlexStart, true),
21             AlignContent::SpaceBetween => (AlignContent::FlexStart, true),
22             AlignContent::SpaceAround => (AlignContent::Center, true),
23             AlignContent::SpaceEvenly => (AlignContent::Center, true),
24             _ => (alignment_mode, is_safe),
25         }
26     };
27 
28     // 2. If free space is negative the "safe" alignment variants all fallback to Start alignment
29     if free_space <= 0.0 && is_safe {
30         alignment_mode = AlignContent::Start;
31     }
32 
33     alignment_mode
34 }
35 
36 /// Generic alignment function that is used:
37 ///   - For both align-content and justify-content alignment
38 ///   - For both the Flexbox and CSS Grid algorithms
39 ///
40 /// CSS Grid does not apply gaps as part of alignment, so the gap parameter should
41 /// always be set to zero for CSS Grid.
compute_alignment_offset( free_space: f32, num_items: usize, gap: f32, alignment_mode: AlignContent, layout_is_flex_reversed: bool, is_first: bool, ) -> f3242 pub(crate) fn compute_alignment_offset(
43     free_space: f32,
44     num_items: usize,
45     gap: f32,
46     alignment_mode: AlignContent,
47     layout_is_flex_reversed: bool,
48     is_first: bool,
49 ) -> f32 {
50     if is_first {
51         match alignment_mode {
52             AlignContent::Start => 0.0,
53             AlignContent::FlexStart => {
54                 if layout_is_flex_reversed {
55                     free_space
56                 } else {
57                     0.0
58                 }
59             }
60             AlignContent::End => free_space,
61             AlignContent::FlexEnd => {
62                 if layout_is_flex_reversed {
63                     0.0
64                 } else {
65                     free_space
66                 }
67             }
68             AlignContent::Center => free_space / 2.0,
69             AlignContent::Stretch => 0.0,
70             AlignContent::SpaceBetween => 0.0,
71             AlignContent::SpaceAround => {
72                 if free_space >= 0.0 {
73                     (free_space / num_items as f32) / 2.0
74                 } else {
75                     free_space / 2.0
76                 }
77             }
78             AlignContent::SpaceEvenly => {
79                 if free_space >= 0.0 {
80                     free_space / (num_items + 1) as f32
81                 } else {
82                     free_space / 2.0
83                 }
84             }
85         }
86     } else {
87         let free_space = free_space.max(0.0);
88         gap + match alignment_mode {
89             AlignContent::Start => 0.0,
90             AlignContent::FlexStart => 0.0,
91             AlignContent::End => 0.0,
92             AlignContent::FlexEnd => 0.0,
93             AlignContent::Center => 0.0,
94             AlignContent::Stretch => 0.0,
95             AlignContent::SpaceBetween => free_space / (num_items - 1) as f32,
96             AlignContent::SpaceAround => free_space / num_items as f32,
97             AlignContent::SpaceEvenly => free_space / (num_items + 1) as f32,
98         }
99     }
100 }
101