Skip to content

Commit

Permalink
Implement TaffyView
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoburns committed Aug 24, 2023
1 parent b20cda8 commit 3b0815d
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 71 deletions.
6 changes: 3 additions & 3 deletions src/compute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,12 @@ mod tests {
use super::perform_hidden_layout;
use crate::geometry::{Point, Size};
use crate::style::{Display, Style};
use crate::tree::MeasureFunc;
use crate::tree::TaffyView;
use crate::Taffy;

#[test]
fn hidden_layout_should_hide_recursively() {
let mut taffy: Taffy<MeasureFunc<()>> = Taffy::new();
let mut taffy: Taffy<()> = Taffy::new();

let style: Style = Style { display: Display::Flex, size: Size::from_lengths(50.0, 50.0), ..Default::default() };

Expand All @@ -133,7 +133,7 @@ mod tests {
)
.unwrap();

perform_hidden_layout(&mut taffy, root.into());
perform_hidden_layout(&mut TaffyView { taffy: &mut taffy, context: () }, root.into());

// Whatever size and display-mode the nodes had previously,
// all layouts should resolve to ZERO due to the root's DISPLAY::NONE
Expand Down
63 changes: 31 additions & 32 deletions src/compute/taffy_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::compute::{leaf, LayoutAlgorithm};
use crate::geometry::{Line, Point, Size};
use crate::style::{AvailableSpace, Display};
use crate::tree::{
Layout, LayoutTree, Measurable, NodeId, RunMode, SizeBaselinesAndMargins, SizingMode, Taffy, TaffyError,
Layout, LayoutTree, Measurable, NodeId, RunMode, SizeBaselinesAndMargins, SizingMode, Taffy, TaffyView, TaffyError,
};
use crate::util::sys::round;

Expand Down Expand Up @@ -37,15 +37,14 @@ fn debug_log_node(

/// Updates the stored layout of the provided `node` and its children
pub(crate) fn compute_layout<Measure: Measurable>(
taffy: &mut Taffy<Measure>,
taffy_view: &mut TaffyView<Measure>,
root: NodeId,
available_space: Size<AvailableSpace>,
) -> Result<(), TaffyError> {
taffy.is_layouting = true;

// Recursively compute node layout
let size_and_baselines = perform_node_layout(
taffy,
taffy_view,
root,
Size::NONE,
available_space.into_options(),
Expand All @@ -55,21 +54,19 @@ pub(crate) fn compute_layout<Measure: Measurable>(
);

let layout = Layout { order: 0, size: size_and_baselines.size, location: Point::ZERO };
*taffy.layout_mut(root) = layout;
*taffy_view.layout_mut(root) = layout;

// If rounding is enabled, recursively round the layout's of this node and all children
if taffy.config.use_rounding {
round_layout(taffy, root, 0.0, 0.0);
if taffy_view.taffy.config.use_rounding {
round_layout(taffy_view.taffy, root, 0.0, 0.0);
}

taffy.is_layouting = false;

Ok(())
}

/// Perform full layout on a node. Chooses which algorithm to use based on the `display` property.
pub(crate) fn perform_node_layout<Measure: Measurable>(
tree: &mut Taffy<Measure>,
taffy_view: &mut TaffyView<Measure>,
node: NodeId,
known_dimensions: Size<Option<f32>>,
parent_size: Size<Option<f32>>,
Expand All @@ -78,7 +75,7 @@ pub(crate) fn perform_node_layout<Measure: Measurable>(
vertical_margins_are_collapsible: Line<bool>,
) -> SizeBaselinesAndMargins {
compute_node_layout(
tree,
taffy_view,
node,
known_dimensions,
parent_size,
Expand All @@ -91,7 +88,7 @@ pub(crate) fn perform_node_layout<Measure: Measurable>(

/// Measure a node's size. Chooses which algorithm to use based on the `display` property.
pub(crate) fn measure_node_size<Measure: Measurable>(
tree: &mut Taffy<Measure>,
taffy_view: &mut TaffyView<Measure>,
node: NodeId,
known_dimensions: Size<Option<f32>>,
parent_size: Size<Option<f32>>,
Expand All @@ -100,7 +97,7 @@ pub(crate) fn measure_node_size<Measure: Measurable>(
vertical_margins_are_collapsible: Line<bool>,
) -> Size<f32> {
compute_node_layout(
tree,
taffy_view,
node,
known_dimensions,
parent_size,
Expand All @@ -115,7 +112,7 @@ pub(crate) fn measure_node_size<Measure: Measurable>(
/// Updates the stored layout of the provided `node` and its children
#[allow(clippy::too_many_arguments)]
fn compute_node_layout<Measure: Measurable>(
tree: &mut Taffy<Measure>,
taffy_view: &mut TaffyView<Measure>,
node: NodeId,
known_dimensions: Size<Option<f32>>,
parent_size: Size<Option<f32>>,
Expand All @@ -130,12 +127,12 @@ fn compute_node_layout<Measure: Measurable>(
println!();

let node_key = node.into();
let has_children = !tree.children[node_key].is_empty();
let has_children = !taffy_view.taffy.children[node_key].is_empty();

// First we check if we have a cached result for the given input
let cache_run_mode = if !has_children { RunMode::PerformLayout } else { run_mode };
if let Some(cached_size_and_baselines) =
tree.nodes[node_key].cache.get(known_dimensions, available_space, cache_run_mode)
taffy_view.taffy.nodes[node_key].cache.get(known_dimensions, available_space, cache_run_mode)
{
#[cfg(feature = "debug")]
NODE_LOGGER.labelled_debug_log("CACHE", cached_size_and_baselines.size);
Expand Down Expand Up @@ -188,15 +185,15 @@ fn compute_node_layout<Measure: Measurable>(
}
}

let display_mode = tree.nodes[node_key].style.display;
let display_mode = taffy_view.taffy.nodes[node_key].style.display;
let computed_size_and_baselines = match (display_mode, has_children) {
(Display::None, _) => {
perform_taffy_tree_hidden_layout(tree, node);
perform_taffy_tree_hidden_layout(taffy_view.taffy, node);
SizeBaselinesAndMargins::HIDDEN
}
#[cfg(feature = "block_layout")]
(Display::Block, true) => perform_computations::<BlockAlgorithm>(
tree,
taffy_view,
node,
known_dimensions,
parent_size,
Expand All @@ -207,7 +204,7 @@ fn compute_node_layout<Measure: Measurable>(
),
#[cfg(feature = "flexbox")]
(Display::Flex, true) => perform_computations::<FlexboxAlgorithm>(
tree,
taffy_view,
node,
known_dimensions,
parent_size,
Expand All @@ -218,7 +215,7 @@ fn compute_node_layout<Measure: Measurable>(
),
#[cfg(feature = "grid")]
(Display::Grid, true) => perform_computations::<CssGridAlgorithm>(
tree,
taffy_view,
node,
known_dimensions,
parent_size,
Expand All @@ -229,29 +226,29 @@ fn compute_node_layout<Measure: Measurable>(
),
(_, false) => match run_mode {
RunMode::PerformLayout => leaf::perform_layout(
&tree.nodes[node_key].style,
tree.nodes[node_key].needs_measure.then(|| &mut tree.measure_funcs[node_key]),
&taffy_view.taffy.nodes[node_key].style,
taffy_view.taffy.nodes[node_key].needs_measure.then(|| &mut taffy_view.taffy.measure_funcs[node_key]),
known_dimensions,
parent_size,
available_space,
sizing_mode,
tree.context.as_mut().unwrap(),
&mut taffy_view.context,
),
RunMode::ComputeSize => leaf::measure_size(
&tree.nodes[node_key].style,
tree.nodes[node_key].needs_measure.then(|| &mut tree.measure_funcs[node_key]),
&taffy_view.taffy.nodes[node_key].style,
taffy_view.taffy.nodes[node_key].needs_measure.then(|| &mut taffy_view.taffy.measure_funcs[node_key]),
known_dimensions,
parent_size,
available_space,
sizing_mode,
tree.context.as_mut().unwrap(),
&mut taffy_view.context,
)
.into(),
},
};

// Cache result
tree.nodes[node_key].cache.store(known_dimensions, available_space, cache_run_mode, computed_size_and_baselines);
taffy_view.taffy.nodes[node_key].cache.store(known_dimensions, available_space, cache_run_mode, computed_size_and_baselines);

#[cfg(feature = "debug")]
NODE_LOGGER.labelled_debug_log("RESULT", computed_size_and_baselines.size);
Expand All @@ -267,15 +264,17 @@ fn perform_taffy_tree_hidden_layout<Measure: Measurable>(tree: &mut Taffy<Measur
/// Recursive function to apply hidden layout to all descendents
fn perform_hidden_layout_inner<Measure: Measurable>(tree: &mut Taffy<Measure>, node: NodeId, order: u32) {
let node_key = node.into();
*tree.layout_mut(node) = Layout::with_order(order);
tree.nodes[node_key].unrounded_layout = Layout::with_order(order);
tree.nodes[node_key].final_layout = Layout::with_order(order);
tree.nodes[node_key].cache.clear();
for order in 0..tree.children[node_key].len() {
perform_hidden_layout_inner(tree, tree.child(node, order), order as _);
perform_hidden_layout_inner(tree, tree.children[node_key][order], order as _);
}
}

let node_key = node.into();
for order in 0..tree.children[node.into()].len() {
perform_hidden_layout_inner(tree, tree.child(node, order), order as _);
perform_hidden_layout_inner(tree, tree.children[node_key][order], order as _);
}
}

Expand Down Expand Up @@ -305,7 +304,7 @@ fn round_layout<Measure: Measurable>(tree: &mut Taffy<Measure>, node_id: NodeId,

let child_count = tree.child_count(node_id).unwrap();
for index in 0..child_count {
let child = tree.child(node_id, index);
let child = tree.children[node_id.into()][index];
round_layout(tree, child, cumulative_x, cumulative_y);
}
}
15 changes: 15 additions & 0 deletions src/tree/measure_func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,21 @@ impl<Context> MeasureFunc<Context> {
}
}

impl Measurable for () {
type Context = ();

/// Call the measure function to measure the node
#[inline(always)]
fn measure(
&mut self,
_known_dimensions: Size<Option<f32>>,
_available_space: Size<AvailableSpace>,
_context: &mut (),
) -> Size<f32> {
Size::ZERO
}
}

impl<Context> Measurable for MeasureFunc<Context> {
type Context = Context;

Expand Down
2 changes: 1 addition & 1 deletion src/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub use node::NodeId;
#[cfg(feature = "taffy_tree")]
mod taffy_tree;
#[cfg(feature = "taffy_tree")]
pub use taffy_tree::{Taffy, TaffyChildIter, TaffyError, TaffyResult};
pub use taffy_tree::{Taffy, TaffyView, TaffyChildIter, TaffyError, TaffyResult};
mod layout;
pub use layout::{CollapsibleMarginSet, Layout, RunMode, SizeBaselinesAndMargins, SizingMode};

Expand Down
2 changes: 1 addition & 1 deletion src/tree/taffy_tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ mod error;
mod tree;

pub use error::{TaffyError, TaffyResult};
pub use tree::{Taffy, TaffyChildIter};
pub use tree::{Taffy, TaffyView, TaffyChildIter};
54 changes: 28 additions & 26 deletions src/tree/taffy_tree/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,6 @@ where

/// Layout mode configuration
pub(crate) config: TaffyConfig,

/// Hack to allow the `LayoutTree::layout_mut` function to expose the `NodeData.unrounded_layout` of a node to
/// the layout algorithms during layout, while exposing the `NodeData.final_layout` when called by external users.
/// This allows us to fix <https://github.com/DioxusLabs/taffy/issues/501> without breaking backwards compatibility
pub(crate) is_layouting: bool,

/// Used to store the context during layout. Cleared before returning from `compute_layout`.
pub(crate) context: Option<Measure::Context>,
}

impl Default for Taffy {
Expand All @@ -73,45 +65,56 @@ impl<'a> Iterator for TaffyChildIter<'a> {
}
}

impl<Measure: Measurable> LayoutTree for Taffy<Measure> {
type ChildIter<'a> = TaffyChildIter<'a> where Measure: 'a;
pub struct TaffyView<'t, Measure: Measurable> {
pub (crate) taffy: &'t mut Taffy<Measure>,
pub (crate) context: Measure::Context,
}

impl <'t, Measure: Measurable> TaffyView<'t, Measure> {
pub (crate) fn config(&self) -> &TaffyConfig {
&self.taffy.config
}
}

impl <'t, Measure: Measurable> LayoutTree for TaffyView<'t, Measure> {
type ChildIter<'a> = TaffyChildIter<'a> where Measure: 'a, Self: 'a;

#[inline(always)]
fn children(&self, node: NodeId) -> Self::ChildIter<'_> {
TaffyChildIter(self.children[node.into()].iter())
TaffyChildIter(self.taffy.children[node.into()].iter())
}

#[inline(always)]
fn child_count(&self, node: NodeId) -> usize {
self.children[node.into()].len()
self.taffy.children[node.into()].len()
}

#[inline(always)]
fn style(&self, node: NodeId) -> &Style {
&self.nodes[node.into()].style
&self.taffy.nodes[node.into()].style
}

#[inline(always)]
fn layout(&self, node: NodeId) -> &Layout {
if self.is_layouting && self.config.use_rounding {
&self.nodes[node.into()].unrounded_layout
if self.taffy.config.use_rounding {
&self.taffy.nodes[node.into()].unrounded_layout
} else {
&self.nodes[node.into()].final_layout
&self.taffy.nodes[node.into()].final_layout
}
}

#[inline(always)]
fn layout_mut(&mut self, node: NodeId) -> &mut Layout {
if self.is_layouting && self.config.use_rounding {
&mut self.nodes[node.into()].unrounded_layout
if self.taffy.config.use_rounding {
&mut self.taffy.nodes[node.into()].unrounded_layout
} else {
&mut self.nodes[node.into()].final_layout
&mut self.taffy.nodes[node.into()].final_layout
}
}

#[inline(always)]
fn child(&self, node: NodeId, id: usize) -> NodeId {
self.children[node.into()][id]
self.taffy.children[node.into()][id]
}

#[inline(always)]
Expand Down Expand Up @@ -178,8 +181,6 @@ impl<Measure: Measurable> Taffy<Measure> {
parents: SlotMap::with_capacity(capacity),
measure_funcs: SparseSecondaryMap::with_capacity(capacity),
config: TaffyConfig::default(),
is_layouting: false,
context: None,
}
}

Expand Down Expand Up @@ -455,10 +456,11 @@ impl<Measure: Measurable> Taffy<Measure> {
available_space: Size<AvailableSpace>,
context: Measure::Context,
) -> Result<(), TaffyError> {
self.context = Some(context);
let result = compute_layout(self, node, available_space);
self.context = None;
result
let mut taffy_view = TaffyView {
taffy: self,
context,
};
compute_layout(&mut taffy_view, node, available_space)
}
}

Expand Down
Loading

0 comments on commit 3b0815d

Please sign in to comment.