gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5364Rust 86Markdown 12TOML 91841 Definitions

⎇ fda1f88edd2bb6de8a7eb2611be94fc81485726d src/compute/mod.rs Rust · 154 lines · 5.0 KB History Who touched what raw

Add `taffy_tree` feature to opt-out of default Taffy tree (#448) fda1f88ed · Martijn Arts ·

1//! The layout algorithms themselves
2
3pub(crate) mod common;
4pub(crate) mod leaf;
5
6pub use leaf::compute;
7
8#[cfg(feature = "flexbox")]
9pub(crate) mod flexbox;
10
11#[cfg(feature = "grid")]
12pub(crate) mod grid;
13
14use crate::geometry::{Point, Size};
15use crate::style::AvailableSpace;
16use crate::tree::{Layout, LayoutTree, NodeId, SizeAndBaselines, SizingMode};
17
18#[cfg(feature = "flexbox")]
19pub use self::flexbox::FlexboxAlgorithm;
20
21#[cfg(feature = "grid")]
22pub use self::grid::CssGridAlgorithm;
23
24#[cfg(feature = "taffy_tree")]
25pub(crate) mod taffy_tree;
26
27#[cfg(any(feature = "debug", feature = "profile"))]
28use crate::util::debug::NODE_LOGGER;
29
30/// A common interface that all Taffy layout algorithms conform to
31pub trait LayoutAlgorithm {
32    /// The name of the algorithm (mainly used for debug purposes)
33    const NAME: &'static str;
34
35    /// Compute the size of the node given the specified constraints
36    fn measure_size(
37        tree: &mut impl LayoutTree,
38        node: NodeId,
39        known_dimensions: Size<Option<f32>>,
40        parent_size: Size<Option<f32>>,
41        available_space: Size<AvailableSpace>,
42        sizing_mode: SizingMode,
43    ) -> Size<f32>;
44
45    /// Perform a full layout on the node given the specified constraints
46    fn perform_layout(
47        tree: &mut impl LayoutTree,
48        node: NodeId,
49        known_dimensions: Size<Option<f32>>,
50        parent_size: Size<Option<f32>>,
51        available_space: Size<AvailableSpace>,
52        sizing_mode: SizingMode,
53    ) -> SizeAndBaselines;
54}
55
56#[cfg(feature = "debug")]
57fn debug_log_node(
58    known_dimensions: Size<Option<f32>>,
59    parent_size: Size<Option<f32>>,
60    available_space: Size<AvailableSpace>,
61    run_mode: RunMode,
62    sizing_mode: SizingMode,
63) {
64    NODE_LOGGER.debug_log(run_mode);
65    NODE_LOGGER.labelled_debug_log("sizing_mode", sizing_mode);
66    NODE_LOGGER.labelled_debug_log("known_dimensions", known_dimensions);
67    NODE_LOGGER.labelled_debug_log("parent_size", parent_size);
68    NODE_LOGGER.labelled_debug_log("available_space", available_space);
69}
70
71/// The public interface to Taffy's hidden node algorithm implementation
72pub struct HiddenAlgorithm;
73impl LayoutAlgorithm for HiddenAlgorithm {
74    const NAME: &'static str = "NONE";
75
76    fn perform_layout(
77        tree: &mut impl LayoutTree,
78        node: NodeId,
79        _known_dimensions: Size<Option<f32>>,
80        _parent_size: Size<Option<f32>>,
81        _available_space: Size<AvailableSpace>,
82        _sizing_mode: SizingMode,
83    ) -> SizeAndBaselines {
84        perform_hidden_layout(tree, node);
85        SizeAndBaselines { size: Size::ZERO, first_baselines: Point::NONE }
86    }
87
88    fn measure_size(
89        _tree: &mut impl LayoutTree,
90        _node: NodeId,
91        _known_dimensions: Size<Option<f32>>,
92        _parent_size: Size<Option<f32>>,
93        _available_space: Size<AvailableSpace>,
94        _sizing_mode: SizingMode,
95    ) -> Size<f32> {
96        Size::ZERO
97    }
98}
99
100/// Creates a layout for this node and its children, recursively.
101/// Each hidden node has zero size and is placed at the origin
102fn perform_hidden_layout(tree: &mut impl LayoutTree, node: NodeId) {
103    /// Recursive function to apply hidden layout to all descendents
104    fn perform_hidden_layout_inner(tree: &mut impl LayoutTree, node: NodeId, order: u32) {
105        *tree.layout_mut(node) = Layout::with_order(order);
106        for order in 0..tree.child_count(node) {
107            perform_hidden_layout_inner(tree, tree.child(node, order), order as _);
108        }
109    }
110
111    for order in 0..tree.child_count(node) {
112        perform_hidden_layout_inner(tree, tree.child(node, order), order as _);
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use super::perform_hidden_layout;
119    use crate::geometry::{Point, Size};
120    use crate::style::{Display, Style};
121    use crate::Taffy;
122
123    #[test]
124    fn hidden_layout_should_hide_recursively() {
125        let mut taffy = Taffy::new();
126
127        let style: Style = Style { display: Display::Flex, size: Size::from_points(50.0, 50.0), ..Default::default() };
128
129        let grandchild_00 = taffy.new_leaf(style.clone()).unwrap();
130        let grandchild_01 = taffy.new_leaf(style.clone()).unwrap();
131        let child_00 = taffy.new_with_children(style.clone(), &[grandchild_00, grandchild_01]).unwrap();
132
133        let grandchild_02 = taffy.new_leaf(style.clone()).unwrap();
134        let child_01 = taffy.new_with_children(style.clone(), &[grandchild_02]).unwrap();
135
136        let root = taffy
137            .new_with_children(
138                Style { display: Display::None, size: Size::from_points(50.0, 50.0), ..Default::default() },
139                &[child_00, child_01],
140            )
141            .unwrap();
142
143        perform_hidden_layout(&mut taffy, root.into());
144
145        // Whatever size and display-mode the nodes had previously,
146        // all layouts should resolve to ZERO due to the root's DISPLAY::NONE
147        for (node, _) in taffy.nodes.iter().filter(|(node, _)| *node != root.into()) {
148            if let Ok(layout) = taffy.layout(node.into()) {
149                assert_eq!(layout.size, Size::zero());
150                assert_eq!(layout.location, Point::zero());
151            }
152        }
153    }
154}