tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Definiciones

Pass axis information when measuring a child's size (#575)

6d7f3cf86a923a02c9d7b67053096a8b3486f15f · por Nico Burns · (hace 2 años) · padre 278f5e39b · ver el árbol en este commit

Delta semántico · 17

src/compute/flexbox.rs

src/compute/grid/types/grid_item.rs

src/geometry.rs

src/style/flex.rs

src/tree/layout.rs

src/tree/mod.rs

6 archivos · +104 −35

diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs
index 94e543574..b5a4e0e7d 100644
--- a/src/compute/flexbox.rs
+++ b/src/compute/flexbox.rs
@@ -638,16 +638,15 @@ fn determine_flex_base_size(
                 )
                 .with_cross(dir, cross_axis_available_space);
 
-            break 'flex_basis tree
-                .measure_child_size(
-                    child.node,
-                    child_known_dimensions,
-                    child_parent_size,
-                    child_available_space,
-                    SizingMode::ContentSize,
-                    Line::FALSE,
-                )
-                .main(dir);
+            break 'flex_basis tree.measure_child_size(
+                child.node,
+                child_known_dimensions,
+                child_parent_size,
+                child_available_space,
+                SizingMode::ContentSize,
+                dir.main_axis(),
+                Line::FALSE,
+            );
         };
 
         // Floor flex-basis by the padding_border_sum (floors inner_flex_basis at zero)
@@ -686,7 +685,7 @@ fn determine_flex_base_size(
             child.min_size.or(child.overflow.map(Overflow::maybe_into_automatic_min_size).into()).main(dir);
 
         child.resolved_minimum_main_size = style_min_main_size.unwrap_or({
-            let min_content_size = {
+            let min_content_main_size = {
                 let child_available_space = Size::MIN_CONTENT.with_cross(dir, cross_axis_available_space);
 
                 tree.measure_child_size(
@@ -695,14 +694,16 @@ fn determine_flex_base_size(
                     child_parent_size,
                     child_available_space,
                     SizingMode::ContentSize,
+                    dir.main_axis(),
                     Line::FALSE,
                 )
             };
 
             // 4.5. Automatic Minimum Size of Flex Items
             // https://www.w3.org/TR/css-flexbox-1/#min-size-auto
-            let clamped_min_content_size = min_content_size.maybe_min(child.size).maybe_min(child.max_size);
-            clamped_min_content_size.maybe_max(padding_border_axes_sums).main(dir)
+            let clamped_min_content_size =
+                min_content_main_size.maybe_min(child.size.main(dir)).maybe_min(child.max_size.main(dir));
+            clamped_min_content_size.maybe_max(padding_border_axes_sums.main(dir))
         });
     }
 }
@@ -899,17 +900,15 @@ fn determine_container_main_size(
 
                                 // Either the min- or max- content size depending on which constraint we are sizing under.
                                 // TODO: Optimise by using already computed values where available
-                                let content_main_size = tree
-                                    .measure_child_size(
-                                        item.node,
-                                        Size::NONE,
-                                        constants.node_inner_size,
-                                        child_available_space,
-                                        SizingMode::InherentSize,
-                                        Line::FALSE,
-                                    )
-                                    .main(constants.dir)
-                                    + item.margin.main_axis_sum(constants.dir);
+                                let content_main_size = tree.measure_child_size(
+                                    item.node,
+                                    Size::NONE,
+                                    constants.node_inner_size,
+                                    child_available_space,
+                                    SizingMode::InherentSize,
+                                    dir.main_axis(),
+                                    Line::FALSE,
+                                ) + item.margin.main_axis_sum(constants.dir);
 
                                 // This is somewhat bizarre in that it's asymetrical depending whether the flex container is a column or a row.
                                 //
@@ -1231,9 +1230,9 @@ fn determine_hypothetical_cross_size(
                     height: if constants.is_row { child_available_cross } else { child_known_main },
                 },
                 SizingMode::ContentSize,
+                constants.dir.cross_axis(),
                 Line::FALSE,
             )
-            .cross(constants.dir)
             .maybe_clamp(child.min_size.cross(constants.dir), child.max_size.cross(constants.dir))
             .max(padding_border_sum)
         });
diff --git a/src/compute/grid/types/grid_item.rs b/src/compute/grid/types/grid_item.rs
index e80cd4c87..86c4a1284 100644
--- a/src/compute/grid/types/grid_item.rs
+++ b/src/compute/grid/types/grid_item.rs
@@ -347,9 +347,9 @@ impl GridItem {
                 None => AvailableSpace::MinContent,
             }),
             SizingMode::InherentSize,
+            axis.as_abs_naive(),
             Line::FALSE,
         )
-        .get(axis)
     }
 
     /// Retrieve the item's min content contribution from the cache or compute it using the provided parameters
@@ -386,9 +386,9 @@ impl GridItem {
                 None => AvailableSpace::MaxContent,
             }),
             SizingMode::InherentSize,
+            axis.as_abs_naive(),
             Line::FALSE,
         )
-        .get(axis)
     }
 
     /// Retrieve the item's max content contribution from the cache or compute it using the provided parameters
diff --git a/src/geometry.rs b/src/geometry.rs
index 006a21491..8f781443f 100644
--- a/src/geometry.rs
+++ b/src/geometry.rs
@@ -61,12 +61,23 @@ pub enum AbstractAxis {
 
 impl AbstractAxis {
     /// Returns the other variant of the enum
+    #[inline]
     pub fn other(&self) -> AbstractAxis {
         match *self {
             AbstractAxis::Inline => AbstractAxis::Block,
             AbstractAxis::Block => AbstractAxis::Inline,
         }
     }
+
+    /// Convert an `AbstractAxis` into an `AbsoluteAxis` naively assuming that the Inline axis is Horizontal
+    /// This is currently always true, but will change if Taffy ever implements the `writing_mode` property
+    #[inline]
+    pub fn as_abs_naive(&self) -> AbsoluteAxis {
+        match self {
+            AbstractAxis::Inline => AbsoluteAxis::Horizontal,
+            AbstractAxis::Block => AbsoluteAxis::Vertical,
+        }
+    }
 }
 
 /// Container that holds an item in each absolute axis without specifying
diff --git a/src/style/flex.rs b/src/style/flex.rs
index 8cce6d051..c24f488d8 100644
--- a/src/style/flex.rs
+++ b/src/style/flex.rs
@@ -1,5 +1,7 @@
 //! Style types for Flexbox layout
 
+use crate::geometry::AbsoluteAxis;
+
 /// Controls whether flex items are forced onto one line or can wrap onto multiple lines.
 ///
 /// Defaults to [`FlexWrap::NoWrap`]
@@ -78,6 +80,24 @@ impl FlexDirection {
     pub(crate) fn is_reverse(self) -> bool {
         matches!(self, Self::RowReverse | Self::ColumnReverse)
     }
+
+    #[inline]
+    /// The `AbsoluteAxis` that corresponds to the main axis
+    pub(crate) fn main_axis(self) -> AbsoluteAxis {
+        match self {
+            Self::Row | Self::RowReverse => AbsoluteAxis::Horizontal,
+            Self::Column | Self::ColumnReverse => AbsoluteAxis::Vertical,
+        }
+    }
+
+    #[inline]
+    /// The `AbsoluteAxis` that corresponds to the cross axis
+    pub(crate) fn cross_axis(self) -> AbsoluteAxis {
+        match self {
+            Self::Row | Self::RowReverse => AbsoluteAxis::Vertical,
+            Self::Column | Self::ColumnReverse => AbsoluteAxis::Horizontal,
+        }
+    }
 }
 
 #[cfg(test)]
diff --git a/src/tree/layout.rs b/src/tree/layout.rs
index 27bd43571..2c43128f4 100644
--- a/src/tree/layout.rs
+++ b/src/tree/layout.rs
@@ -1,5 +1,5 @@
 //! Final data structures that represent the high-level UI layout
-use crate::geometry::{Line, Point, Size};
+use crate::geometry::{AbsoluteAxis, Line, Point, Size};
 use crate::prelude::TaffyMaxContent;
 use crate::style::AvailableSpace;
 use crate::util::sys::{f32_max, f32_min};
@@ -71,9 +71,46 @@ impl CollapsibleMarginSet {
     }
 }
 
+/// An axis that layout algorithms can be requested to compute a size for
+#[derive(Debug, Copy, Clone)]
+pub enum RequestedAxis {
+    /// The horizontal axis
+    Horizontal,
+    /// The vertical axis
+    Vertical,
+    /// Both axes
+    Both,
+}
+
+impl From<AbsoluteAxis> for RequestedAxis {
+    fn from(value: AbsoluteAxis) -> Self {
+        match value {
+            AbsoluteAxis::Horizontal => RequestedAxis::Horizontal,
+            AbsoluteAxis::Vertical => RequestedAxis::Vertical,
+        }
+    }
+}
+impl TryFrom<RequestedAxis> for AbsoluteAxis {
+    type Error = ();
+    fn try_from(value: RequestedAxis) -> Result<Self, Self::Error> {
+        match value {
+            RequestedAxis::Horizontal => Ok(AbsoluteAxis::Horizontal),
+            RequestedAxis::Vertical => Ok(AbsoluteAxis::Vertical),
+            RequestedAxis::Both => Err(()),
+        }
+    }
+}
+
 /// A struct containing the inputs constraints/hints for laying out a node, which are passed in by the parent
 #[derive(Debug, Copy, Clone)]
 pub struct LayoutInput {
+    /// Whether we only need to know the Node's size, or whe
+    pub run_mode: RunMode,
+    /// Whether a Node's style sizes should be taken into account or ignored
+    pub sizing_mode: SizingMode,
+    /// Which axis we need the size of
+    pub axis: RequestedAxis,
+
     /// Known dimensions represent dimensions (width/height) which should be taken as fixed when performing layout.
     /// For example, if known_dimensions.width is set to Some(WIDTH) then this means something like:
     ///
@@ -89,10 +126,6 @@ pub struct LayoutInput {
     /// Available space represents an amount of space to layout into, and is used as a soft constraint
     /// for the purpose of wrapping.
     pub available_space: Size<AvailableSpace>,
-    /// Whether a Node's style sizes should be taken into account or ignored
-    pub sizing_mode: SizingMode,
-    /// Whether we only need to know the Node's size, or whe
-    pub run_mode: RunMode,
     /// Specific to CSS Block layout. Used for correctly computing margin collapsing. You probably want to set this to `Line::FALSE`.
     pub vertical_margins_are_collapsible: Line<bool>,
 }
@@ -107,6 +140,7 @@ impl LayoutInput {
         parent_size: Size::NONE,
         available_space: Size::MAX_CONTENT,
         sizing_mode: SizingMode::InherentSize,
+        axis: RequestedAxis::Both,
         vertical_margins_are_collapsible: Line::FALSE,
     };
 }
diff --git a/src/tree/mod.rs b/src/tree/mod.rs
index fb9fee7c5..d89ab1a23 100644
--- a/src/tree/mod.rs
+++ b/src/tree/mod.rs
@@ -1,6 +1,6 @@
 //! Contains both [a high-level interface to Taffy](crate::Taffy) using a ready-made node tree, and [a trait for defining a custom node trees](crate::tree::LayoutTree) / utility types to help with that.
 
-use crate::geometry::{Line, Size};
+use crate::geometry::{AbsoluteAxis, Line, Size};
 use crate::style::{AvailableSpace, Style};
 
 // Submodules
@@ -15,7 +15,7 @@ mod taffy_tree;
 #[cfg(feature = "taffy_tree")]
 pub use taffy_tree::{Taffy, TaffyError, TaffyResult};
 mod layout;
-pub use layout::{CollapsibleMarginSet, Layout, LayoutInput, LayoutOutput, RunMode, SizingMode};
+pub use layout::{CollapsibleMarginSet, Layout, LayoutInput, LayoutOutput, RequestedAxis, RunMode, SizingMode};
 
 /// This if the core abstraction in Taffy. Any type that *correctly* implements `PartialLayoutTree` can be laid out using Taffy's algorithms.
 ///
@@ -64,6 +64,7 @@ pub trait LayoutTree: PartialLayoutTree {
 pub(crate) trait PartialLayoutTreeExt: PartialLayoutTree {
     /// Compute the size of the node given the specified constraints
     #[inline(always)]
+    #[allow(clippy::too_many_arguments)]
     fn measure_child_size(
         &mut self,
         node_id: NodeId,
@@ -71,8 +72,9 @@ pub(crate) trait PartialLayoutTreeExt: PartialLayoutTree {
         parent_size: Size<Option<f32>>,
         available_space: Size<AvailableSpace>,
         sizing_mode: SizingMode,
+        axis: AbsoluteAxis,
         vertical_margins_are_collapsible: Line<bool>,
-    ) -> Size<f32> {
+    ) -> f32 {
         self.compute_child_layout(
             node_id,
             LayoutInput {
@@ -80,11 +82,13 @@ pub(crate) trait PartialLayoutTreeExt: PartialLayoutTree {
                 parent_size,
                 available_space,
                 sizing_mode,
+                axis: axis.into(),
                 run_mode: RunMode::ComputeSize,
                 vertical_margins_are_collapsible,
             },
         )
         .size
+        .get_abs(axis)
     }
 
     /// Perform a full layout on the node given the specified constraints
@@ -105,6 +109,7 @@ pub(crate) trait PartialLayoutTreeExt: PartialLayoutTree {
                 parent_size,
                 available_space,
                 sizing_mode,
+                axis: RequestedAxis::Both,
                 run_mode: RunMode::PerformLayout,
                 vertical_margins_are_collapsible,
             },