diff --git a/examples/custom_tree_owned_partial.rs b/examples/custom_tree_owned_partial.rs index e69b26eb5..e4084e4ad 100644 --- a/examples/custom_tree_owned_partial.rs +++ b/examples/custom_tree_owned_partial.rs @@ -13,7 +13,7 @@ use common::image::{image_measure_function, ImageContext}; use common::text::{text_measure_function, FontMetrics, TextContext, WritingMode, LOREM_IPSUM}; use taffy::{ compute_cached_layout, compute_flexbox_layout, compute_grid_layout, compute_leaf_layout, compute_root_layout, - prelude::*, Cache, CacheTree, Layout, Style, + prelude::*, Cache, CacheTree, Layout, SizingMode, Style, }; #[derive(Debug, Copy, Clone)] @@ -192,9 +192,11 @@ impl CacheTree for Node { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: taffy::RunMode, + sizing_mode: SizingMode, ) -> Option { - self.node_from_id(node_id).cache.get(known_dimensions, available_space, run_mode) + self.node_from_id(node_id).cache.get(known_dimensions, available_space, parent_size, run_mode, sizing_mode) } fn cache_store( @@ -202,10 +204,19 @@ impl CacheTree for Node { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: taffy::RunMode, + sizing_mode: SizingMode, layout_output: taffy::LayoutOutput, ) { - self.node_from_id_mut(node_id).cache.store(known_dimensions, available_space, run_mode, layout_output) + self.node_from_id_mut(node_id).cache.store( + known_dimensions, + available_space, + parent_size, + run_mode, + sizing_mode, + layout_output, + ) } fn cache_clear(&mut self, node_id: NodeId) { diff --git a/examples/custom_tree_owned_unsafe.rs b/examples/custom_tree_owned_unsafe.rs index d0138ba95..ba0e20318 100644 --- a/examples/custom_tree_owned_unsafe.rs +++ b/examples/custom_tree_owned_unsafe.rs @@ -9,7 +9,7 @@ use taffy::tree::Cache; use taffy::util::print_tree; use taffy::{ compute_cached_layout, compute_flexbox_layout, compute_grid_layout, compute_leaf_layout, compute_root_layout, - prelude::*, round_layout, CacheTree, + prelude::*, round_layout, CacheTree, SizingMode, }; #[derive(Debug, Copy, Clone)] @@ -190,9 +190,17 @@ impl CacheTree for StatelessLayoutTree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: taffy::RunMode, + sizing_mode: SizingMode, ) -> Option { - unsafe { node_from_id(node_id) }.cache.get(known_dimensions, available_space, run_mode) + unsafe { node_from_id(node_id) }.cache.get( + known_dimensions, + available_space, + parent_size, + run_mode, + sizing_mode, + ) } fn cache_store( @@ -200,10 +208,19 @@ impl CacheTree for StatelessLayoutTree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: taffy::RunMode, + sizing_mode: SizingMode, layout_output: taffy::LayoutOutput, ) { - unsafe { node_from_id_mut(node_id) }.cache.store(known_dimensions, available_space, run_mode, layout_output) + unsafe { node_from_id_mut(node_id) }.cache.store( + known_dimensions, + available_space, + parent_size, + run_mode, + sizing_mode, + layout_output, + ) } fn cache_clear(&mut self, node_id: NodeId) { diff --git a/examples/custom_tree_vec.rs b/examples/custom_tree_vec.rs index 5659bd174..ccb2cf8c4 100644 --- a/examples/custom_tree_vec.rs +++ b/examples/custom_tree_vec.rs @@ -7,7 +7,7 @@ use common::text::{text_measure_function, FontMetrics, TextContext, WritingMode, use taffy::util::print_tree; use taffy::{ compute_cached_layout, compute_flexbox_layout, compute_grid_layout, compute_leaf_layout, compute_root_layout, - prelude::*, round_layout, Cache, CacheTree, + prelude::*, round_layout, Cache, CacheTree, SizingMode, }; #[derive(Debug, Copy, Clone)] @@ -198,9 +198,11 @@ impl CacheTree for Tree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: taffy::RunMode, + sizing_mode: SizingMode, ) -> Option { - self.node_from_id(node_id).cache.get(known_dimensions, available_space, run_mode) + self.node_from_id(node_id).cache.get(known_dimensions, available_space, parent_size, run_mode, sizing_mode) } fn cache_store( @@ -208,10 +210,19 @@ impl CacheTree for Tree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: taffy::RunMode, + sizing_mode: SizingMode, layout_output: taffy::LayoutOutput, ) { - self.node_from_id_mut(node_id).cache.store(known_dimensions, available_space, run_mode, layout_output) + self.node_from_id_mut(node_id).cache.store( + known_dimensions, + available_space, + parent_size, + run_mode, + sizing_mode, + layout_output, + ) } fn cache_clear(&mut self, node_id: NodeId) { diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs index 2cf25ae4b..f46a26c13 100644 --- a/src/compute/flexbox.rs +++ b/src/compute/flexbox.rs @@ -1060,6 +1060,7 @@ fn determine_container_main_size( child_known_dimensions, constants.node_inner_size, child_available_space, + // FIXME: apply "InherentSize" differences manually SizingMode::InherentSize, dir.main_axis(), Line::FALSE, diff --git a/src/compute/mod.rs b/src/compute/mod.rs index 9a13a2ee5..b0455d236 100644 --- a/src/compute/mod.rs +++ b/src/compute/mod.rs @@ -174,10 +174,10 @@ where ComputeFunction: FnOnce(&mut Tree, NodeId, LayoutInput) -> LayoutOutput, { debug_push_node!(node); - let LayoutInput { known_dimensions, available_space, run_mode, .. } = inputs; + let LayoutInput { known_dimensions, available_space, run_mode, parent_size, sizing_mode, .. } = inputs; // First we check if we have a cached result for the given input - let cache_entry = tree.cache_get(node, known_dimensions, available_space, run_mode); + let cache_entry = tree.cache_get(node, known_dimensions, available_space, parent_size, run_mode, sizing_mode); if let Some(cached_size_and_baselines) = cache_entry { debug_log_node!(known_dimensions, inputs.parent_size, available_space, run_mode, inputs.sizing_mode); debug_log!("RESULT (CACHED)", dbg:cached_size_and_baselines.size); @@ -190,7 +190,15 @@ where let computed_size_and_baselines = compute_uncached(tree, node, inputs); // Cache result - tree.cache_store(node, known_dimensions, available_space, run_mode, computed_size_and_baselines); + tree.cache_store( + node, + known_dimensions, + available_space, + parent_size, + run_mode, + sizing_mode, + computed_size_and_baselines, + ); debug_log!("RESULT", dbg:computed_size_and_baselines.size); debug_pop_node!(); diff --git a/src/style/available_space.rs b/src/style/available_space.rs index 844037e0a..29e8c7c6b 100644 --- a/src/style/available_space.rs +++ b/src/style/available_space.rs @@ -1,7 +1,6 @@ //! Style type for representing available space as a sizing constraint use crate::{ prelude::{FromLength, TaffyMaxContent, TaffyMinContent, TaffyZero}, - sys::abs, Size, }; @@ -103,18 +102,6 @@ impl AvailableSpace { AvailableSpace::Definite(available_space) => available_space - used_space, } } - - /// Compare equality with another AvailableSpace, treating definite values - /// that are within f32::EPSILON of each other as equal - pub fn is_roughly_equal(self, other: AvailableSpace) -> bool { - use AvailableSpace::*; - match (self, other) { - (Definite(a), Definite(b)) => abs(a - b) < f32::EPSILON, - (MinContent, MinContent) => true, - (MaxContent, MaxContent) => true, - _ => false, - } - } } impl From for AvailableSpace { diff --git a/src/tree/cache.rs b/src/tree/cache.rs index cff245d5e..2b866d7a4 100644 --- a/src/tree/cache.rs +++ b/src/tree/cache.rs @@ -3,6 +3,8 @@ use crate::geometry::Size; use crate::style::AvailableSpace; use crate::tree::{LayoutOutput, RunMode}; +use super::SizingMode; + /// The number of cache entries for each node in the tree const CACHE_SIZE: usize = 9; @@ -14,6 +16,10 @@ pub(crate) struct CacheEntry { known_dimensions: Size>, /// The initial cached size of the parent's node available_space: Size, + /// The initial cached size of the parent's node + parent_size: Size>, + /// The sizing mode + sizing_mode: SizingMode, /// The cached size and baselines of the item content: T, } @@ -112,40 +118,30 @@ impl Cache { &self, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, ) -> Option { match run_mode { RunMode::PerformLayout => self .final_layout_entry .filter(|entry| { - let cached_size = entry.content.size; - (known_dimensions.width == entry.known_dimensions.width - || known_dimensions.width == Some(cached_size.width)) - && (known_dimensions.height == entry.known_dimensions.height - || known_dimensions.height == Some(cached_size.height)) - && (known_dimensions.width.is_some() - || entry.available_space.width.is_roughly_equal(available_space.width)) - && (known_dimensions.height.is_some() - || entry.available_space.height.is_roughly_equal(available_space.height)) + known_dimensions == entry.known_dimensions + && available_space == entry.available_space + && parent_size == entry.parent_size + && sizing_mode == entry.sizing_mode }) .map(|e| e.content), RunMode::ComputeSize => { - for entry in self.measure_entries.iter().flatten() { - let cached_size = entry.content; - - if (known_dimensions.width == entry.known_dimensions.width - || known_dimensions.width == Some(cached_size.width)) - && (known_dimensions.height == entry.known_dimensions.height - || known_dimensions.height == Some(cached_size.height)) - && (known_dimensions.width.is_some() - || entry.available_space.width.is_roughly_equal(available_space.width)) - && (known_dimensions.height.is_some() - || entry.available_space.height.is_roughly_equal(available_space.height)) - { - return Some(LayoutOutput::from_outer_size(cached_size)); - } + let cache_slot = Self::compute_cache_slot(known_dimensions, available_space); + let entry = &self.measure_entries[cache_slot]?; + if known_dimensions == entry.known_dimensions + && available_space == entry.available_space + // && parent_size == entry.parent_size + && sizing_mode == entry.sizing_mode + { + return Some(LayoutOutput::from_outer_size(entry.content)); } - None } RunMode::PerformHiddenLayout => None, @@ -157,19 +153,32 @@ impl Cache { &mut self, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, layout_output: LayoutOutput, ) { match run_mode { RunMode::PerformLayout => { self.is_empty = false; - self.final_layout_entry = Some(CacheEntry { known_dimensions, available_space, content: layout_output }) + self.final_layout_entry = Some(CacheEntry { + known_dimensions, + available_space, + parent_size, + sizing_mode, + content: layout_output, + }) } RunMode::ComputeSize => { self.is_empty = false; let cache_slot = Self::compute_cache_slot(known_dimensions, available_space); - self.measure_entries[cache_slot] = - Some(CacheEntry { known_dimensions, available_space, content: layout_output.size }); + self.measure_entries[cache_slot] = Some(CacheEntry { + known_dimensions, + available_space, + parent_size, + sizing_mode, + content: layout_output.size, + }); } RunMode::PerformHiddenLayout => {} } diff --git a/src/tree/taffy_tree.rs b/src/tree/taffy_tree.rs index 785e97fa5..b2fd2b78d 100644 --- a/src/tree/taffy_tree.rs +++ b/src/tree/taffy_tree.rs @@ -34,6 +34,8 @@ use crate::compute::grid::DetailedGridInfo; #[cfg(feature = "detailed_layout_info")] use crate::tree::layout::DetailedLayoutInfo; +use super::SizingMode; + /// The error Taffy generates on invalid operations pub type TaffyResult = Result; @@ -215,9 +217,11 @@ impl CacheTree for TaffyTree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, ) -> Option { - self.nodes[node_id.into()].cache.get(known_dimensions, available_space, run_mode) + self.nodes[node_id.into()].cache.get(known_dimensions, available_space, parent_size, run_mode, sizing_mode) } fn cache_store( @@ -225,10 +229,19 @@ impl CacheTree for TaffyTree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, layout_output: LayoutOutput, ) { - self.nodes[node_id.into()].cache.store(known_dimensions, available_space, run_mode, layout_output) + self.nodes[node_id.into()].cache.store( + known_dimensions, + available_space, + parent_size, + run_mode, + sizing_mode, + layout_output, + ) } fn cache_clear(&mut self, node_id: NodeId) { @@ -432,9 +445,17 @@ where node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, ) -> Option { - self.taffy.nodes[node_id.into()].cache.get(known_dimensions, available_space, run_mode) + self.taffy.nodes[node_id.into()].cache.get( + known_dimensions, + available_space, + parent_size, + run_mode, + sizing_mode, + ) } fn cache_store( @@ -442,10 +463,19 @@ where node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, layout_output: LayoutOutput, ) { - self.taffy.nodes[node_id.into()].cache.store(known_dimensions, available_space, run_mode, layout_output) + self.taffy.nodes[node_id.into()].cache.store( + known_dimensions, + available_space, + parent_size, + run_mode, + sizing_mode, + layout_output, + ) } fn cache_clear(&mut self, node_id: NodeId) { diff --git a/src/tree/traits.rs b/src/tree/traits.rs index 194110ef5..0710f9e89 100644 --- a/src/tree/traits.rs +++ b/src/tree/traits.rs @@ -210,7 +210,9 @@ pub trait CacheTree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, ) -> Option; /// Store a computed size in the cache @@ -219,7 +221,9 @@ pub trait CacheTree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, layout_output: LayoutOutput, ); diff --git a/src/util/sys.rs b/src/util/sys.rs index f665190a8..0cbe99925 100644 --- a/src/util/sys.rs +++ b/src/util/sys.rs @@ -74,13 +74,6 @@ mod std { value.floor() } - /// Computes the absolute value - #[must_use] - #[inline(always)] - pub(crate) fn abs(value: f32) -> f32 { - value.abs() - } - /// Returns the largest of two f32 values #[inline(always)] pub(crate) fn f32_max(a: f32, b: f32) -> f32 { @@ -150,9 +143,6 @@ mod alloc { /// Rounds down to the nearest whole number pub(crate) use super::polyfill::floor; - /// Computes the absolute value - pub(crate) use super::polyfill::abs; - /// Returns the largest of two f32 values #[inline(always)] pub(crate) fn f32_max(a: f32, b: f32) -> f32 { @@ -211,9 +201,6 @@ mod core { /// Rounds to the nearest whole number pub(crate) use super::polyfill::round; - /// Computes the absolute value - pub(crate) use super::polyfill::abs; - /// Returns the largest of two f32 values #[inline(always)] pub(crate) fn f32_max(a: f32, b: f32) -> f32 { @@ -285,17 +272,4 @@ mod polyfill { value - f } } - - /// Computes the absolute value - #[must_use] - #[inline(always)] - pub(crate) fn abs(value: f32) -> f32 { - if value.is_sign_positive() { - return value; - } else if value.is_sign_negative() { - return -value; - } else { - f32::NAN - } - } } diff --git a/tests/caching.rs b/tests/caching.rs index c93423982..b14f7e6ae 100644 --- a/tests/caching.rs +++ b/tests/caching.rs @@ -18,7 +18,7 @@ mod caching { taffy.compute_layout_with_measure(node, Size::MAX_CONTENT, test_measure_function).unwrap(); - assert_eq!(taffy.get_node_context_mut(leaf).unwrap().count, 4); + assert_eq!(taffy.get_node_context_mut(leaf).unwrap().count, 7); } #[test] @@ -35,6 +35,6 @@ mod caching { } taffy.compute_layout_with_measure(node, Size::MAX_CONTENT, test_measure_function).unwrap(); - assert_eq!(taffy.get_node_context_mut(leaf).unwrap().count, 4); + assert_eq!(taffy.get_node_context_mut(leaf).unwrap().count, 7); } }