tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 707HTML 660Markdown 12TOML 62344 Sutichaykuna

use geometry in flexitem props

badc72208966183d5d0d8d9ab8fc5763feeb8670 · ruwaq Emil Sjölander · (7 wata ñawpaq) · tayta f8eed829a · kay commitpi sach'ata qhaway

Semántico sayk'uy · 4

src/algo.rs

src/geometry.rs

2 qillqakuna · +139 −94

diff --git a/src/algo.rs b/src/algo.rs
index 6efb6f46a..d4b8f831b 100644
--- a/src/algo.rs
+++ b/src/algo.rs
@@ -28,21 +28,15 @@ struct FlexItem<'a> {
     padding: Rect<f32>,
     border: Rect<f32>,
 
-    // temporary values for main size determination
     flex_basis: f32,
     inner_flex_basis: f32,
-    hypothetical_inner_main_size: f32,
-    hypothetical_outer_main_size: f32,
-    target_main_size: f32,
-    outer_target_main_size: f32,
     violation: f32,
     frozen: bool,
 
-    // temporary values for cross size determination
-    hypothetical_inner_cross_size: f32,
-    hypothetical_outer_cross_size: f32,
-    target_cross_size: f32,
-    outer_target_cross_size: f32,
+    hypothetical_inner_size: Size<f32>,
+    hypothetical_outer_size: Size<f32>,
+    target_size: Size<f32>,
+    outer_target_size: Size<f32>,
 
     baseline: f32,
 
@@ -227,17 +221,13 @@ fn compute_internal(
 
             flex_basis: 0.0,
             inner_flex_basis: 0.0,
-            hypothetical_inner_main_size: 0.0,
-            hypothetical_outer_main_size: 0.0,
-            target_main_size: 0.0,
-            outer_target_main_size: 0.0,
             violation: 0.0,
             frozen: false,
 
-            hypothetical_inner_cross_size: 0.0,
-            hypothetical_outer_cross_size: 0.0,
-            target_cross_size: 0.0,
-            outer_target_cross_size: 0.0,
+            hypothetical_inner_size: Size { width: 0.0, height: 0.0 },
+            hypothetical_outer_size: Size { width: 0.0, height: 0.0 },
+            target_size: Size { width: 0.0, height: 0.0 },
+            outer_target_size: Size { width: 0.0, height: 0.0 },
 
             baseline: 0.0,
 
@@ -336,11 +326,15 @@ fn compute_internal(
             child.min_size.main(node.flex_direction)
         };
 
-        child.hypothetical_inner_main_size =
-            child.flex_basis.maybe_max(min_main).maybe_min(child.max_size.main(node.flex_direction));
+        child.hypothetical_inner_size.set_main(
+            node.flex_direction,
+            child.flex_basis.maybe_max(min_main).maybe_min(child.max_size.main(node.flex_direction)),
+        );
 
-        child.hypothetical_outer_main_size =
-            child.hypothetical_inner_main_size + child.margin.main(node.flex_direction);
+        child.hypothetical_outer_size.set_main(
+            node.flex_direction,
+            child.hypothetical_inner_size.main(node.flex_direction) + child.margin.main(node.flex_direction),
+        );
     });
 
     // 9.3. Main Size Determination
@@ -370,11 +364,11 @@ fn compute_internal(
             let mut line = FlexLine { items: vec![], cross_size: 0.0, offset_cross: 0.0 };
 
             for child in flex_items {
-                line_length += child.hypothetical_outer_main_size;
+                line_length += child.hypothetical_outer_size.main(node.flex_direction);
 
                 if let Defined(main) = available_space.main(node.flex_direction) {
                     if line_length > main && !line.items.is_empty() {
-                        line_length = child.hypothetical_outer_main_size;
+                        line_length = child.hypothetical_outer_size.main(node.flex_direction);
                         lines.push(line);
                         line = FlexLine { items: vec![], cross_size: 0.0, offset_cross: 0.0 };
                     }
@@ -400,7 +394,8 @@ fn compute_internal(
         //    use the flex grow factor for the rest of this algorithm; otherwise, use the
         //    flex shrink factor.
 
-        let used_flex_factor: f32 = line.items.iter().map(|child| child.hypothetical_outer_main_size).sum();
+        let used_flex_factor: f32 =
+            line.items.iter().map(|child| child.hypothetical_outer_size.main(node.flex_direction)).sum();
         let growing = used_flex_factor < node_inner_size.main(node.flex_direction).or_else(0.0);
         let shrinking = !growing;
 
@@ -415,31 +410,39 @@ fn compute_internal(
             // TODO - This is not found by reading the spec. Maybe this can be done in some other place
             // instead. This was found by trail and error fixing tests to align with webkit output.
             if node_inner_size.main(node.flex_direction).is_undefined() && is_row {
-                child.target_main_size = compute_internal(
-                    child.node,
-                    Size {
-                        width: child.size.width.maybe_max(child.min_size.width).maybe_min(child.max_size.width),
-                        height: child.size.height.maybe_max(child.min_size.height).maybe_min(child.max_size.height),
-                    },
-                    available_space,
-                    percent_calc_base_child,
-                )
-                .size
-                .main(node.flex_direction)
-                .maybe_max(child.min_size.main(node.flex_direction))
-                .maybe_min(child.max_size.main(node.flex_direction));
+                child.target_size.set_main(
+                    node.flex_direction,
+                    compute_internal(
+                        child.node,
+                        Size {
+                            width: child.size.width.maybe_max(child.min_size.width).maybe_min(child.max_size.width),
+                            height: child.size.height.maybe_max(child.min_size.height).maybe_min(child.max_size.height),
+                        },
+                        available_space,
+                        percent_calc_base_child,
+                    )
+                    .size
+                    .main(node.flex_direction)
+                    .maybe_max(child.min_size.main(node.flex_direction))
+                    .maybe_min(child.max_size.main(node.flex_direction)),
+                );
             } else {
-                child.target_main_size = child.hypothetical_inner_main_size;
+                child
+                    .target_size
+                    .set_main(node.flex_direction, child.hypothetical_inner_size.main(node.flex_direction));
             }
 
             // TODO this should really only be set inside the if-statement below but
             // that casues the target_main_size to never be set for some items
 
-            child.outer_target_main_size = child.target_main_size + child.margin.main(node.flex_direction);
+            child.outer_target_size.set_main(
+                node.flex_direction,
+                child.target_size.main(node.flex_direction) + child.margin.main(node.flex_direction),
+            );
 
             if (child.node.flex_grow == 0.0 && child.node.flex_shrink == 0.0)
-                || (growing && child.flex_basis > child.hypothetical_inner_main_size)
-                || (shrinking && child.flex_basis < child.hypothetical_inner_main_size)
+                || (growing && child.flex_basis > child.hypothetical_inner_size.main(node.flex_direction))
+                || (shrinking && child.flex_basis < child.hypothetical_inner_size.main(node.flex_direction))
             {
                 child.frozen = true;
             }
@@ -454,7 +457,7 @@ fn compute_internal(
             .iter()
             .map(|child| {
                 child.margin.main(node.flex_direction)
-                    + if child.frozen { child.target_main_size } else { child.flex_basis }
+                    + if child.frozen { child.target_size.main(node.flex_direction) } else { child.flex_basis }
             })
             .sum();
 
@@ -490,7 +493,7 @@ fn compute_internal(
             let used_space: f32 = Iterator::chain(frozen.iter(), unfrozen.iter())
                 .map(|child| {
                     child.margin.main(node.flex_direction)
-                        + if child.frozen { child.target_main_size } else { child.flex_basis }
+                        + if child.frozen { child.target_size.main(node.flex_direction) } else { child.flex_basis }
                 })
                 .sum();
 
@@ -527,7 +530,10 @@ fn compute_internal(
             if free_space.is_normal() {
                 if growing && sum_flex_grow > 0.0 {
                     unfrozen.iter_mut().for_each(|child| {
-                        child.target_main_size = child.flex_basis + free_space * (child.node.flex_grow / sum_flex_grow);
+                        child.target_size.set_main(
+                            node.flex_direction,
+                            child.flex_basis + free_space * (child.node.flex_grow / sum_flex_grow),
+                        );
                     });
                 } else if shrinking && sum_flex_shrink > 0.0 {
                     let sum_scaled_shrink_factor: f32 =
@@ -536,8 +542,10 @@ fn compute_internal(
                     if sum_scaled_shrink_factor > 0.0 {
                         unfrozen.iter_mut().for_each(|child| {
                             let scaled_shrink_factor = child.inner_flex_basis * child.node.flex_shrink;
-                            child.target_main_size =
-                                child.flex_basis + free_space * (scaled_shrink_factor / sum_scaled_shrink_factor);
+                            child.target_size.set_main(
+                                node.flex_direction,
+                                child.flex_basis + free_space * (scaled_shrink_factor / sum_scaled_shrink_factor),
+                            )
                         });
                     }
                 }
@@ -570,10 +578,14 @@ fn compute_internal(
                 };
 
                 let max_main = child.max_size.main(node.flex_direction);
-                let clamped = child.target_main_size.maybe_min(max_main).maybe_max(min_main).max(0.0);
-                child.violation = clamped - child.target_main_size;
-                child.target_main_size = clamped;
-                child.outer_target_main_size = child.target_main_size + child.margin.main(node.flex_direction);
+                let clamped =
+                    child.target_size.main(node.flex_direction).maybe_min(max_main).maybe_max(min_main).max(0.0);
+                child.violation = clamped - child.target_size.main(node.flex_direction);
+                child.target_size.set_main(node.flex_direction, clamped);
+                child.outer_target_size.set_main(
+                    node.flex_direction,
+                    child.target_size.main(node.flex_direction) + child.margin.main(node.flex_direction),
+                );
 
                 acc + child.violation
             });
@@ -600,7 +612,7 @@ fn compute_internal(
     // Not part of the spec from what i can see but seems correct
     let container_main_size = node_size.main(node.flex_direction).or_else({
         let longest_line = flex_lines.iter().fold(f32::MIN, |acc, line| {
-            let length: f32 = line.items.iter().map(|item| item.outer_target_main_size).sum();
+            let length: f32 = line.items.iter().map(|item| item.outer_target_size.main(node.flex_direction)).sum();
             acc.max(length)
         });
 
@@ -626,25 +638,38 @@ fn compute_internal(
                 .maybe_max(child.min_size.cross(node.flex_direction))
                 .maybe_min(child.max_size.cross(node.flex_direction));
 
-            child.hypothetical_inner_cross_size = compute_internal(
-                child.node,
-                Size {
-                    width: if is_row { child.target_main_size.to_number() } else { child_cross },
-                    height: if is_row { child_cross } else { child.target_main_size.to_number() },
-                },
-                Size {
-                    width: if is_row { container_main_size.to_number() } else { available_space.width },
-                    height: if is_row { available_space.height } else { container_main_size.to_number() },
-                },
-                percent_calc_base_child,
-            )
-            .size
-            .cross(node.flex_direction)
-            .maybe_max(child.min_size.cross(node.flex_direction))
-            .maybe_min(child.max_size.cross(node.flex_direction));
+            child.hypothetical_inner_size.set_cross(
+                node.flex_direction,
+                compute_internal(
+                    child.node,
+                    Size {
+                        width: if is_row {
+                            child.target_size.main(node.flex_direction).to_number()
+                        } else {
+                            child_cross
+                        },
+                        height: if is_row {
+                            child_cross
+                        } else {
+                            child.target_size.main(node.flex_direction).to_number()
+                        },
+                    },
+                    Size {
+                        width: if is_row { container_main_size.to_number() } else { available_space.width },
+                        height: if is_row { available_space.height } else { container_main_size.to_number() },
+                    },
+                    percent_calc_base_child,
+                )
+                .size
+                .cross(node.flex_direction)
+                .maybe_max(child.min_size.cross(node.flex_direction))
+                .maybe_min(child.max_size.cross(node.flex_direction)),
+            );
 
-            child.hypothetical_outer_cross_size =
-                child.hypothetical_inner_cross_size + child.margin.cross(node.flex_direction);
+            child.hypothetical_outer_size.set_cross(
+                node.flex_direction,
+                child.hypothetical_inner_size.cross(node.flex_direction) + child.margin.cross(node.flex_direction),
+            );
         });
     });
 
@@ -665,14 +690,14 @@ fn compute_internal(
                 child.node,
                 Size {
                     width: if is_row {
-                        child.target_main_size.to_number()
+                        child.target_size.main(node.flex_direction).to_number()
                     } else {
-                        child.hypothetical_inner_cross_size.to_number()
+                        child.hypothetical_inner_size.cross(node.flex_direction).to_number()
                     },
                     height: if is_row {
-                        child.hypothetical_inner_cross_size.to_number()
+                        child.hypothetical_inner_size.cross(node.flex_direction).to_number()
                     } else {
-                        child.target_main_size.to_number()
+                        child.target_size.main(node.flex_direction).to_number()
                     },
                 },
                 Size {
@@ -724,9 +749,9 @@ fn compute_internal(
                         && child.node.cross_margin_end(node.flex_direction) != Dimension::Auto
                         && child.node.cross_size(node.flex_direction) == Dimension::Auto
                     {
-                        max_baseline - child.baseline + child.hypothetical_outer_cross_size
+                        max_baseline - child.baseline + child.hypothetical_outer_size.cross(node.flex_direction)
                     } else {
-                        child.hypothetical_outer_cross_size
+                        child.hypothetical_outer_size.cross(node.flex_direction)
                     }
                 })
                 .fold(0.0, |acc, x| acc.max(x));
@@ -782,19 +807,25 @@ fn compute_internal(
         let line_cross_size = line.cross_size;
 
         line.items.iter_mut().for_each(|child| {
-            child.target_cross_size = if child.node.align_self(node) == AlignSelf::Stretch
-                && child.node.cross_margin_start(node.flex_direction) != Dimension::Auto
-                && child.node.cross_margin_end(node.flex_direction) != Dimension::Auto
-                && child.node.cross_size(node.flex_direction) == Dimension::Auto
-            {
-                (line_cross_size - child.margin.cross(node.flex_direction))
-                    .maybe_max(child.min_size.cross(node.flex_direction))
-                    .maybe_min(child.max_size.cross(node.flex_direction))
-            } else {
-                child.hypothetical_inner_cross_size
-            };
+            child.target_size.set_cross(
+                node.flex_direction,
+                if child.node.align_self(node) == AlignSelf::Stretch
+                    && child.node.cross_margin_start(node.flex_direction) != Dimension::Auto
+                    && child.node.cross_margin_end(node.flex_direction) != Dimension::Auto
+                    && child.node.cross_size(node.flex_direction) == Dimension::Auto
+                {
+                    (line_cross_size - child.margin.cross(node.flex_direction))
+                        .maybe_max(child.min_size.cross(node.flex_direction))
+                        .maybe_min(child.max_size.cross(node.flex_direction))
+                } else {
+                    child.hypothetical_inner_size.cross(node.flex_direction)
+                },
+            );
 
-            child.outer_target_cross_size = child.target_cross_size + child.margin.cross(node.flex_direction);
+            child.outer_target_size.set_cross(
+                node.flex_direction,
+                child.target_size.cross(node.flex_direction) + child.margin.cross(node.flex_direction),
+            );
         });
     });
 
@@ -807,7 +838,7 @@ fn compute_internal(
     //     2. Align the items along the main-axis per justify-content.
 
     flex_lines.iter_mut().for_each(|line| {
-        let used_space: f32 = line.items.iter().map(|child| child.outer_target_main_size).sum();
+        let used_space: f32 = line.items.iter().map(|child| child.outer_target_size.main(node.flex_direction)).sum();
         let free_space = inner_container_main_size - used_space;
         let mut num_auto_margins = 0;
 
@@ -909,7 +940,7 @@ fn compute_internal(
         let max_baseline: f32 = line.items.iter_mut().map(|child| child.baseline).fold(0.0, |acc, x| acc.max(x));
 
         line.items.iter_mut().for_each(|child| {
-            let free_space = line_cross_size - child.outer_target_cross_size;
+            let free_space = line_cross_size - child.outer_target_size.cross(node.flex_direction);
 
             if child.node.cross_margin_start(node.flex_direction) == Dimension::Auto
                 && child.node.cross_margin_end(node.flex_direction) == Dimension::Auto
@@ -1062,14 +1093,14 @@ fn compute_internal(
                     child.node,
                     Size {
                         width: if is_row {
-                            child.target_main_size.to_number()
+                            child.target_size.main(node.flex_direction).to_number()
                         } else {
-                            child.target_cross_size.to_number()
+                            child.target_size.cross(node.flex_direction).to_number()
                         },
                         height: if is_row {
-                            child.target_cross_size.to_number()
+                            child.target_size.cross(node.flex_direction).to_number()
                         } else {
-                            child.target_main_size.to_number()
+                            child.target_size.main(node.flex_direction).to_number()
                         },
                     },
                     Size { width: container_width.to_number(), height: container_height.to_number() },
diff --git a/src/geometry.rs b/src/geometry.rs
index 86c70dff8..c16ac19de 100644
--- a/src/geometry.rs
+++ b/src/geometry.rs
@@ -77,6 +77,20 @@ pub struct Size<T> {
 }
 
 impl<T> Size<T> {
+    pub(crate) fn set_main(&mut self, direction: style::FlexDirection, value: T) {
+        match direction {
+            style::FlexDirection::Row | style::FlexDirection::RowReverse => self.width = value,
+            style::FlexDirection::Column | style::FlexDirection::ColumnReverse => self.height = value,
+        }
+    }
+
+    pub(crate) fn set_cross(&mut self, direction: style::FlexDirection, value: T) {
+        match direction {
+            style::FlexDirection::Row | style::FlexDirection::RowReverse => self.height = value,
+            style::FlexDirection::Column | style::FlexDirection::ColumnReverse => self.width = value,
+        }
+    }
+
     pub(crate) fn main(self, direction: style::FlexDirection) -> T {
         match direction {
             style::FlexDirection::Row | style::FlexDirection::RowReverse => self.width,