tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 501HTML 254C 19JavaScript 81412 Sutichaykuna

⎇ d52ab8f8305292875fbbe1b672c12daf63dca3be src/compute/mod.rs Rust · 136 siq'ikuna · 4.4 KB Ñawpa willay Pi imata llamkarqan ch'uya

Fix `display:none` caching issue (#454) d52ab8f83 · Nico Burns ·

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