tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 231Rust 8TOML 3CSS 1317 Sutichaykuna

⎇ ff34f0b20b3bd97d2428b49fcb5eb9e3adcdb08c src/node.rs Rust · 234 siq'ikuna · 7.2 KB Ñawpa willay Pi imata llamkarqan ch'uya

Make the core algorithms be allocation free ff34f0b20 · David Flemström ·

1use core::ops::Drop;
2
3use crate::forest::Forest;
4use crate::geometry::Size;
5use crate::id::{self, NodeId};
6use crate::number::Number;
7use crate::result::Layout;
8use crate::style::*;
9use crate::sys;
10use crate::Error;
11
12pub type MeasureFunc = fn(Size<Number>) -> Size<f32>;
13
14lazy_static! {
15    /// Global stretch instance id allocator.
16    static ref INSTANCE_ALLOCATOR: id::Allocator = id::Allocator::new();
17}
18
19#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
20#[cfg_attr(not(any(feature = "std", feature = "alloc")), derive(hash32_derive::Hash32))]
21pub struct Node {
22    instance: id::Id,
23    local: id::Id,
24}
25
26pub struct Stretch {
27    id: id::Id,
28    nodes: id::Allocator,
29    nodes_to_ids: crate::sys::Map<Node, NodeId>,
30    ids_to_nodes: crate::sys::Map<NodeId, Node>,
31    forest: Forest,
32}
33
34impl Default for Stretch {
35    fn default() -> Self {
36        Stretch::with_capacity(16)
37    }
38}
39
40impl Stretch {
41    pub fn new() -> Self {
42        Default::default()
43    }
44
45    pub fn with_capacity(capacity: usize) -> Self {
46        Stretch {
47            id: INSTANCE_ALLOCATOR.allocate(),
48            nodes: id::Allocator::new(),
49            nodes_to_ids: crate::sys::new_map_with_capacity(capacity),
50            ids_to_nodes: crate::sys::new_map_with_capacity(capacity),
51            forest: Forest::with_capacity(capacity),
52        }
53    }
54
55    fn allocate_node(&mut self) -> Node {
56        let local = self.nodes.allocate();
57        Node { instance: self.id, local }
58    }
59
60    fn add_node(&mut self, node: Node, id: NodeId) {
61        let _ = self.nodes_to_ids.insert(node, id);
62        let _ = self.ids_to_nodes.insert(id, node);
63    }
64
65    // Find node in the forest.
66    fn find_node(&self, node: Node) -> Result<NodeId, Error> {
67        match self.nodes_to_ids.get(&node) {
68            Some(id) => Ok(*id),
69            None => Err(Error::InvalidNode(node)),
70        }
71    }
72
73    pub fn new_leaf(&mut self, style: Style, measure: MeasureFunc) -> Result<Node, Error> {
74        let node = self.allocate_node();
75        let id = self.forest.new_leaf(style, measure);
76        self.add_node(node, id);
77        Ok(node)
78    }
79
80    pub fn new_node(&mut self, style: Style, children: &[Node]) -> Result<Node, Error> {
81        let node = self.allocate_node();
82        let children =
83            children.iter().map(|child| self.find_node(*child)).collect::<Result<sys::ChildrenVec<_>, Error>>()?;
84        let id = self.forest.new_node(style, children);
85        self.add_node(node, id);
86        Ok(node)
87    }
88
89    /// Removes all nodes.
90    ///
91    /// All associated nodes will be invalid.
92    pub fn clear(&mut self) {
93        for node in self.nodes_to_ids.keys() {
94            self.nodes.free(&[node.local]);
95        }
96        self.nodes_to_ids.clear();
97        self.ids_to_nodes.clear();
98        self.forest.clear();
99    }
100
101    /// Remove nodes.
102    pub fn remove(&mut self, node: Node) {
103        let id = if let Ok(id) = self.find_node(node) { id } else { return };
104
105        self.nodes_to_ids.remove(&node);
106        self.ids_to_nodes.remove(&id);
107
108        if let Some(new_id) = self.forest.swap_remove(id) {
109            let new = self.ids_to_nodes.remove(&new_id).unwrap();
110            let _ = self.nodes_to_ids.insert(new, id);
111            let _ = self.ids_to_nodes.insert(id, new);
112        }
113    }
114
115    pub fn set_measure(&mut self, node: Node, measure: Option<MeasureFunc>) -> Result<(), Error> {
116        let id = self.find_node(node)?;
117        self.forest.nodes[id].measure = measure;
118        self.forest.mark_dirty(id);
119        Ok(())
120    }
121
122    pub fn add_child(&mut self, node: Node, child: Node) -> Result<(), Error> {
123        let node_id = self.find_node(node)?;
124        let child_id = self.find_node(child)?;
125
126        self.forest.add_child(node_id, child_id);
127        Ok(())
128    }
129
130    pub fn set_children(&mut self, node: Node, children: &[Node]) -> Result<(), Error> {
131        let node_id = self.find_node(node)?;
132        let children_id =
133            children.iter().map(|child| self.find_node(*child)).collect::<Result<sys::ChildrenVec<_>, _>>()?;
134
135        // Remove node as parent from all its current children.
136        for child in &self.forest.children[node_id] {
137            self.forest.parents[*child].retain(|p| *p != node_id);
138        }
139
140        // Build up relation node <-> child
141        for child in &children_id {
142            self.forest.parents[*child].push(node_id);
143        }
144        self.forest.children[node_id] = children_id;
145
146        self.forest.mark_dirty(node_id);
147        Ok(())
148    }
149
150    pub fn remove_child(&mut self, node: Node, child: Node) -> Result<Node, Error> {
151        let node_id = self.find_node(node)?;
152        let child_id = self.find_node(child)?;
153
154        let prev_id = unsafe { self.forest.remove_child(node_id, child_id) };
155        Ok(self.ids_to_nodes[&prev_id])
156    }
157
158    pub fn remove_child_at_index(&mut self, node: Node, index: usize) -> Result<Node, Error> {
159        let node_id = self.find_node(node)?;
160        // TODO: index check
161
162        let prev_id = self.forest.remove_child_at_index(node_id, index);
163        Ok(self.ids_to_nodes[&prev_id])
164    }
165
166    pub fn replace_child_at_index(&mut self, node: Node, index: usize, child: Node) -> Result<Node, Error> {
167        let node_id = self.find_node(node)?;
168        let child_id = self.find_node(child)?;
169        // TODO: index check
170
171        self.forest.parents[child_id].push(node_id);
172        let old_child = core::mem::replace(&mut self.forest.children[node_id][index], child_id);
173        self.forest.parents[old_child].retain(|p| *p != node_id);
174
175        self.forest.mark_dirty(node_id);
176
177        Ok(self.ids_to_nodes[&old_child])
178    }
179
180    pub fn children(&self, node: Node) -> Result<sys::Vec<Node>, Error> {
181        let id = self.find_node(node)?;
182        Ok(self.forest.children[id].iter().map(|child| self.ids_to_nodes[child]).collect())
183    }
184
185    pub fn child_at_index(&self, node: Node, index: usize) -> Result<Node, Error> {
186        let id = self.find_node(node)?;
187        Ok(self.ids_to_nodes[&self.forest.children[id][index]])
188    }
189
190    pub fn child_count(&self, node: Node) -> Result<usize, Error> {
191        let id = self.find_node(node)?;
192        Ok(self.forest.children[id].len())
193    }
194
195    pub fn set_style(&mut self, node: Node, style: Style) -> Result<(), Error> {
196        let id = self.find_node(node)?;
197        self.forest.nodes[id].style = style;
198        self.forest.mark_dirty(id);
199        Ok(())
200    }
201
202    pub fn style(&self, node: Node) -> Result<&Style, Error> {
203        let id = self.find_node(node)?;
204        Ok(&self.forest.nodes[id].style)
205    }
206
207    pub fn layout(&self, node: Node) -> Result<&Layout, Error> {
208        let id = self.find_node(node)?;
209        Ok(&self.forest.nodes[id].layout)
210    }
211
212    pub fn mark_dirty(&mut self, node: Node) -> Result<(), Error> {
213        let id = self.find_node(node)?;
214        self.forest.mark_dirty(id);
215        Ok(())
216    }
217
218    pub fn dirty(&self, node: Node) -> Result<bool, Error> {
219        let id = self.find_node(node)?;
220        Ok(self.forest.nodes[id].is_dirty)
221    }
222
223    pub fn compute_layout(&mut self, node: Node, size: Size<Number>) -> Result<(), Error> {
224        let id = self.find_node(node)?;
225        self.forest.compute_layout(id, size);
226        Ok(())
227    }
228}
229
230impl Drop for Stretch {
231    fn drop(&mut self) {
232        INSTANCE_ALLOCATOR.free(&[self.id]);
233    }
234}