Remove `cache_mut`, `needs_measure` and `measure_node` methods from `LayoutTree` trait (#431)
* Remove the measure_node and needs_measure methods from the LayoutTree trait
* Remove cache_mut method from the LayoutTree trait
* Update release notes
384b60bdadb6ac33f2117cc571e519d738885587 · por Nico Burns · 2023-04-11T09:33:21Z (hace 3 años) · padre 77a309162 · ver el árbol en este commit
diff --git a/RELEASES.md b/RELEASES.md
index e826e4359..f163070fb 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -5,7 +5,7 @@
### Removed
- `layout_flexbox()` has been removed from the prelude. Use `FlexboxAlgorithm::perform_layout()` instead.
-- The following methods have been removed from the `LayoutTree` trait: `parent`, `is_childless`, `layout`, and `mark_dirty`. These no longer need to be implemented in custom implementation of `LayoutTree`.
+- The following methods have been removed from the `LayoutTree` trait: `parent`, `is_childless`, `layout`, `measure_node`, `needs_measure`, `cache_mut` and `mark_dirty`. These no longer need to be implemented in custom implementation of `LayoutTree`.
### Changes
diff --git a/src/compute/leaf.rs b/src/compute/leaf.rs
index 4ee8373a2..cf92d5701 100644
--- a/src/compute/leaf.rs
+++ b/src/compute/leaf.rs
@@ -1,55 +1,52 @@
//! Computes size using styles and measure functions
-use crate::compute::LayoutAlgorithm;
use crate::geometry::{Point, Size};
use crate::layout::{SizeAndBaselines, SizingMode};
use crate::math::MaybeMath;
+use crate::node::Taffy;
use crate::resolve::{MaybeResolve, ResolveOrZero};
use crate::style::AvailableSpace;
use crate::sys::f32_max;
-use crate::tree::{LayoutTree, NodeId};
+use crate::tree::NodeId;
#[cfg(feature = "debug")]
use crate::debug::NODE_LOGGER;
-/// The public interface to Taffy's leaf node algorithm implementation
-pub(crate) struct LeafAlgorithm;
-impl LayoutAlgorithm for LeafAlgorithm {
- const NAME: &'static str = "LEAF";
-
- fn perform_layout(
- tree: &mut impl LayoutTree,
- node: NodeId,
- known_dimensions: Size<Option<f32>>,
- parent_size: Size<Option<f32>>,
- available_space: Size<AvailableSpace>,
- sizing_mode: SizingMode,
- ) -> SizeAndBaselines {
- compute(tree, node, known_dimensions, parent_size, available_space, sizing_mode)
- }
+/// Perform full layout on a leaf node
+pub(crate) fn perform_layout(
+ tree: &mut Taffy,
+ node: NodeId,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ sizing_mode: SizingMode,
+) -> SizeAndBaselines {
+ compute(tree, node, known_dimensions, parent_size, available_space, sizing_mode)
+}
- fn measure_size(
- tree: &mut impl LayoutTree,
- node: NodeId,
- known_dimensions: Size<Option<f32>>,
- parent_size: Size<Option<f32>>,
- available_space: Size<AvailableSpace>,
- sizing_mode: SizingMode,
- ) -> Size<f32> {
- compute(tree, node, known_dimensions, parent_size, available_space, sizing_mode).size
- }
+/// Measure a leaf node's size
+pub(crate) fn measure_size(
+ tree: &mut Taffy,
+ node: NodeId,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ sizing_mode: SizingMode,
+) -> Size<f32> {
+ compute(tree, node, known_dimensions, parent_size, available_space, sizing_mode).size
}
/// Compute the size of a leaf node (node with no children)
pub(crate) fn compute(
- tree: &mut impl LayoutTree,
+ tree: &mut Taffy,
node: NodeId,
known_dimensions: Size<Option<f32>>,
parent_size: Size<Option<f32>>,
available_space: Size<AvailableSpace>,
sizing_mode: SizingMode,
) -> SizeAndBaselines {
- let style = tree.style(node);
+ let key = node.into();
+ let style = tree.style(node).unwrap();
// Resolve node's preferred/min/max sizes (width/heights) against the available space (percentages resolve to pixel values)
// For ContentSize mode, we pretend that the node has no size styles as these should be ignored.
@@ -94,7 +91,7 @@ pub(crate) fn compute(
return SizeAndBaselines { size, first_baselines: Point::NONE };
};
- if tree.needs_measure(node) {
+ if tree.nodes[key].needs_measure {
// Compute available space
let available_space = Size {
width: available_space
@@ -110,7 +107,7 @@ pub(crate) fn compute(
};
// Measure node
- let measured_size = tree.measure_node(node, known_dimensions, available_space);
+ let measured_size = tree.measure_funcs[key].measure(known_dimensions, available_space);
let measured_size = Size {
width: measured_size.width,
diff --git a/src/compute/mod.rs b/src/compute/mod.rs
index b37c0e73d..bb8fd5e3b 100644
--- a/src/compute/mod.rs
+++ b/src/compute/mod.rs
@@ -23,7 +23,6 @@ use self::flexbox::FlexboxAlgorithm;
#[cfg(feature = "grid")]
use self::grid::CssGridAlgorithm;
-use self::leaf::LeafAlgorithm;
#[cfg(any(feature = "debug", feature = "profile"))]
use crate::debug::NODE_LOGGER;
@@ -35,7 +34,7 @@ pub fn compute_layout(
available_space: Size<AvailableSpace>,
) -> Result<(), TaffyError> {
// Recursively compute node layout
- let size_and_baselines = GenericAlgorithm::perform_layout(
+ let size_and_baselines = perform_node_layout(
taffy,
root,
Size::NONE,
@@ -81,55 +80,34 @@ pub(crate) trait LayoutAlgorithm {
) -> SizeAndBaselines;
}
-/// The public interface to a generic algorithm that abstracts over all of Taffy's algorithms
-/// and applies the correct one based on the `Display` style
-pub struct GenericAlgorithm;
-impl LayoutAlgorithm for GenericAlgorithm {
- const NAME: &'static str = "GENERIC";
-
- fn perform_layout(
- tree: &mut impl LayoutTree,
- node: NodeId,
- known_dimensions: Size<Option<f32>>,
- parent_size: Size<Option<f32>>,
- available_space: Size<AvailableSpace>,
- sizing_mode: SizingMode,
- ) -> SizeAndBaselines {
- compute_node_layout(
- tree,
- node,
- known_dimensions,
- parent_size,
- available_space,
- RunMode::PeformLayout,
- sizing_mode,
- )
- }
+/// Perform full layout on a node. Chooses which algorithm to use based on the `display` property.
+pub(crate) fn perform_node_layout(
+ tree: &mut Taffy,
+ node: NodeId,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ sizing_mode: SizingMode,
+) -> SizeAndBaselines {
+ compute_node_layout(tree, node, known_dimensions, parent_size, available_space, RunMode::PeformLayout, sizing_mode)
+}
- fn measure_size(
- tree: &mut impl LayoutTree,
- node: NodeId,
- known_dimensions: Size<Option<f32>>,
- parent_size: Size<Option<f32>>,
- available_space: Size<AvailableSpace>,
- sizing_mode: SizingMode,
- ) -> Size<f32> {
- compute_node_layout(
- tree,
- node,
- known_dimensions,
- parent_size,
- available_space,
- RunMode::ComputeSize,
- sizing_mode,
- )
+/// Measure a node's size. Chooses which algorithm to use based on the `display` property.
+pub(crate) fn measure_node_size(
+ tree: &mut Taffy,
+ node: NodeId,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ sizing_mode: SizingMode,
+) -> Size<f32> {
+ compute_node_layout(tree, node, known_dimensions, parent_size, available_space, RunMode::ComputeSize, sizing_mode)
.size
- }
}
/// Updates the stored layout of the provided `node` and its children
fn compute_node_layout(
- tree: &mut impl LayoutTree,
+ tree: &mut Taffy,
node: NodeId,
known_dimensions: Size<Option<f32>>,
parent_size: Size<Option<f32>>,
@@ -142,8 +120,11 @@ fn compute_node_layout(
#[cfg(feature = "debug")]
println!();
+ let node_key = node.into();
+ let has_children = !tree.children[node_key].is_empty();
+
// First we check if we have a cached result for the given input
- let cache_run_mode = if tree.child_count(node) == 0 { RunMode::PeformLayout } else { run_mode };
+ let cache_run_mode = if !has_children { RunMode::PeformLayout } else { run_mode };
if let Some(cached_size_and_baselines) =
compute_from_cache(tree, node, known_dimensions, available_space, cache_run_mode)
{
@@ -178,15 +159,12 @@ fn compute_node_layout(
Algorithm::perform_layout(tree, node, known_dimensions, parent_size, available_space, sizing_mode)
}
RunMode::ComputeSize => {
- let size =
- Algorithm::measure_size(tree, node, known_dimensions, parent_size, available_space, sizing_mode);
- SizeAndBaselines { size, first_baselines: Point::NONE }
+ Algorithm::measure_size(tree, node, known_dimensions, parent_size, available_space, sizing_mode).into()
}
}
}
- let display_mode = tree.style(node).display;
- let has_children = tree.child_count(node) != 0;
+ let display_mode = tree.nodes[node_key].style.display;
let computed_size_and_baselines = match (display_mode, has_children) {
(Display::None, _) => perform_computations::<HiddenAlgorithm>(
tree,
@@ -217,20 +195,19 @@ fn compute_node_layout(
run_mode,
sizing_mode,
),
- (_, false) => perform_computations::<LeafAlgorithm>(
- tree,
- node,
- known_dimensions,
- parent_size,
- available_space,
- run_mode,
- sizing_mode,
- ),
+ (_, false) => match run_mode {
+ RunMode::PeformLayout => {
+ leaf::perform_layout(tree, node, known_dimensions, parent_size, available_space, sizing_mode)
+ }
+ RunMode::ComputeSize => {
+ leaf::measure_size(tree, node, known_dimensions, parent_size, available_space, sizing_mode).into()
+ }
+ },
};
// Cache result
let cache_slot = compute_cache_slot(known_dimensions, available_space);
- *tree.cache_mut(node, cache_slot) = Some(Cache {
+ tree.nodes[node_key].size_cache[cache_slot] = Some(Cache {
known_dimensions,
available_space,
run_mode: cache_run_mode,
@@ -312,14 +289,15 @@ fn compute_cache_slot(known_dimensions: Size<Option<f32>>, available_space: Size
/// Try to get the computation result from the cache.
#[inline]
fn compute_from_cache(
- tree: &mut impl LayoutTree,
+ tree: &mut Taffy,
node: NodeId,
known_dimensions: Size<Option<f32>>,
available_space: Size<AvailableSpace>,
run_mode: RunMode,
) -> Option<SizeAndBaselines> {
+ let node_key = node.into();
for idx in 0..CACHE_SIZE {
- let entry = tree.cache_mut(node, idx);
+ let entry = tree.nodes[node_key].size_cache[idx];
if let Some(entry) = entry {
// Cached ComputeSize results are not valid if we are running in PerformLayout mode
if entry.run_mode == RunMode::ComputeSize && run_mode == RunMode::PeformLayout {
diff --git a/src/node.rs b/src/node.rs
index 8d1da7248..1e68c1094 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -3,11 +3,11 @@
//! Layouts are composed of multiple nodes, which live in a tree-like data structure.
use slotmap::{DefaultKey, SlotMap, SparseSecondaryMap};
-use crate::compute::{GenericAlgorithm, LayoutAlgorithm};
+use crate::compute::{measure_node_size, perform_node_layout};
use crate::data::NodeData;
use crate::error::{TaffyError, TaffyResult};
use crate::geometry::Size;
-use crate::layout::{Cache, Layout, SizeAndBaselines, SizingMode};
+use crate::layout::{Layout, SizeAndBaselines, SizingMode};
use crate::prelude::LayoutTree;
use crate::style::{AvailableSpace, Style};
#[cfg(any(feature = "std", feature = "alloc"))]
@@ -31,6 +31,18 @@ pub enum MeasureFunc {
Boxed(Box<dyn Measurable>),
}
+impl MeasureFunc {
+ /// Call the measure function to measure to the node
+ #[inline(always)]
+ pub fn measure(&self, known_dimensions: Size<Option<f32>>, available_space: Size<AvailableSpace>) -> Size<f32> {
+ match self {
+ MeasureFunc::Raw(measure) => measure(known_dimensions, available_space),
+ #[cfg(any(feature = "std", feature = "alloc"))]
+ MeasureFunc::Boxed(measure) => (measure as &dyn Fn(_, _) -> _)(known_dimensions, available_space),
+ }
+ }
+}
+
/// Global configuration values for a Taffy instance
pub(crate) struct TaffyConfig {
/// Whether to round layout values
@@ -104,29 +116,6 @@ impl LayoutTree for Taffy {
&mut self.nodes[node.into()].layout
}
- fn measure_node(
- &self,
- node: NodeId,
- known_dimensions: Size<Option<f32>>,
- available_space: Size<AvailableSpace>,
- ) -> Size<f32> {
- match &self.measure_funcs[node.into()] {
- MeasureFunc::Raw(measure) => measure(known_dimensions, available_space),
-
- #[cfg(any(feature = "std", feature = "alloc"))]
- MeasureFunc::Boxed(measure) => (measure as &dyn Fn(_, _) -> _)(known_dimensions, available_space),
- }
- }
-
- fn needs_measure(&self, node: NodeId) -> bool {
- let node = node.into();
- self.nodes[node].needs_measure && self.measure_funcs.get(node).is_some()
- }
-
- fn cache_mut(&mut self, node: NodeId, index: usize) -> &mut Option<Cache> {
- &mut self.nodes[node.into()].size_cache[index]
- }
-
#[inline(always)]
fn child(&self, node: NodeId, id: usize) -> NodeId {
self.children[node.into()][id]
@@ -141,7 +130,7 @@ impl LayoutTree for Taffy {
available_space: Size<AvailableSpace>,
sizing_mode: SizingMode,
) -> Size<f32> {
- GenericAlgorithm::measure_size(self, node, known_dimensions, parent_size, available_space, sizing_mode)
+ measure_node_size(self, node, known_dimensions, parent_size, available_space, sizing_mode)
}
#[inline(always)]
@@ -153,7 +142,7 @@ impl LayoutTree for Taffy {
available_space: Size<AvailableSpace>,
sizing_mode: SizingMode,
) -> SizeAndBaselines {
- GenericAlgorithm::perform_layout(self, node, known_dimensions, parent_size, available_space, sizing_mode)
+ perform_node_layout(self, node, known_dimensions, parent_size, available_space, sizing_mode)
}
}
diff --git a/src/tree.rs b/src/tree.rs
index 1b49e7244..fa7b8f182 100644
--- a/src/tree.rs
+++ b/src/tree.rs
@@ -1,6 +1,6 @@
//! The baseline requirements of any UI Tree so Taffy can efficiently calculate the layout
use crate::{
- layout::{Cache, Layout, SizeAndBaselines, SizingMode},
+ layout::{Layout, SizeAndBaselines, SizingMode},
prelude::*,
};
use slotmap::{DefaultKey, Key, KeyData};
@@ -77,20 +77,6 @@ pub trait LayoutTree {
/// Modify the node's output layout
fn layout_mut(&mut self, node: NodeId) -> &mut Layout;
- /// Measure a node. Taffy uses this to force reflows of things like text and overflowing content.
- fn measure_node(
- &self,
- node: NodeId,
- known_dimensions: Size<Option<f32>>,
- available_space: Size<AvailableSpace>,
- ) -> Size<f32>;
-
- /// Node needs to be measured
- fn needs_measure(&self, node: NodeId) -> bool;
-
- /// Get a cache entry for this Node by index
- fn cache_mut(&mut self, node: NodeId, index: usize) -> &mut Option<Cache>;
-
/// Compute the size of the node given the specified constraints
fn measure_child_size(
&mut self,