tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 231Rust 10TOML 3CSS 1350 Definiciones

⎇ 66bcb10bff823bfde7828eeef133cb2fa7de7dba src/compute/mod.rs Rust · 150 líneas · 4.9 KB Historia Quién tocó qué crudo

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