tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 1077HTML 1008Markdown 12TOML 83209 Definitions

⎇ 838c413a73c458a9a208d719f2082084e90a2cef src/compute/mod.rs Rust · 156 lines · 5.0 KB History Who touched what raw

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