gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 501HTML 254C 19JavaScript 81414 Sutichaykuna

⎇ caa0ce8629f858d791af8d50bd47d9d30d7aefc3 src/node.rs Rust · 166 siq'ikuna · 4.9 KB Ñawpa willay Pi imata llamkarqan ch'uya

Minor optimizations in node allocation caa0ce862 · Emil Sjölander ·

1#[cfg(not(feature = "std"))]
2use alloc::{vec, vec::Vec};
3
4use std::cell::RefCell;
5use std::fmt;
6use std::rc::Rc;
7use std::rc::Weak;
8
9use crate::algo;
10use crate::geometry::Size;
11use crate::number::Number;
12use crate::result::{Cache, Layout, Result};
13use crate::style::*;
14
15type MeasureFunc = Box<Fn(Size<Number>) -> Result<Size<f32>>>;
16
17pub(crate) struct InternalNode {
18    pub(crate) style: Style,
19    pub(crate) parents: Vec<Weak<RefCell<InternalNode>>>,
20    pub(crate) children: Vec<Rc<RefCell<InternalNode>>>,
21    pub(crate) measure: Option<MeasureFunc>,
22    pub(crate) layout_cache: RefCell<Option<Cache>>,
23}
24
25pub struct Node(Rc<RefCell<InternalNode>>);
26
27impl Node {
28    pub fn new_leaf(style: Style, measure: Option<MeasureFunc>) -> Node {
29        Node(Rc::new(RefCell::new(InternalNode {
30            style,
31            parents: Vec::with_capacity(1),
32            children: Vec::with_capacity(0),
33            measure,
34            layout_cache: RefCell::new(None),
35        })))
36    }
37
38    pub fn new(style: Style, children: Vec<&Node>) -> Node {
39        let parent = Node(Rc::new(RefCell::new(InternalNode {
40            style,
41            parents: Vec::with_capacity(1),
42            children: Vec::with_capacity(children.len()),
43            measure: None,
44            layout_cache: RefCell::new(None),
45        })));
46
47        for child in children {
48            child.0.borrow_mut().parents.push(Rc::downgrade(&parent.0));
49            parent.0.borrow_mut().children.push(Rc::clone(&child.0));
50        }
51
52        parent
53    }
54
55    pub fn add_child(&mut self, child: &Node) {
56        child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
57        self.0.borrow_mut().children.push(Rc::clone(&child.0));
58        self.mark_dirty();
59    }
60
61    pub fn set_children(&mut self, children: Vec<&Node>) {
62        for child in &self.0.borrow().children {
63            let position =
64                child.borrow().parents.iter().position(|x| Rc::ptr_eq(&x.upgrade().unwrap(), &self.0)).unwrap();
65            child.borrow_mut().parents.remove(position);
66        }
67
68        self.0.borrow_mut().children = Vec::with_capacity(children.len());
69
70        for child in children {
71            child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
72            self.0.borrow_mut().children.push(Rc::clone(&child.0));
73        }
74
75        self.mark_dirty();
76    }
77
78    pub fn remove_child(&mut self, child: &Node) -> Node {
79        self.remove_child_at_index({
80            let parent = self.0.borrow();
81            parent.children.iter().position(|x| Rc::ptr_eq(&x, &child.0)).unwrap()
82        })
83    }
84
85    pub fn remove_child_at_index(&mut self, index: usize) -> Node {
86        let child = {
87            let mut parent = self.0.borrow_mut();
88            let child = parent.children.remove(index);
89            let position =
90                child.borrow().parents.iter().position(|x| Rc::ptr_eq(&x.upgrade().unwrap(), &self.0)).unwrap();
91            child.borrow_mut().parents.remove(position);
92            child
93        };
94
95        self.mark_dirty();
96        Node(child)
97    }
98
99    pub fn replace_child_at_index(&mut self, index: usize, child: &Node) -> Node {
100        child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
101        let old_child = std::mem::replace(&mut self.0.borrow_mut().children[index], Rc::clone(&child.0));
102
103        let position =
104            old_child.borrow().parents.iter().position(|x| Rc::ptr_eq(&x.upgrade().unwrap(), &self.0)).unwrap();
105        old_child.borrow_mut().parents.remove(position);
106
107        self.mark_dirty();
108
109        Node(old_child)
110    }
111
112    pub fn children(&self) -> Vec<Node> {
113        let node = self.0.borrow_mut();
114        node.children.iter().map(|child| Node(Rc::clone(child))).collect()
115    }
116
117    pub fn set_style(&mut self, style: Style) {
118        self.0.borrow_mut().style = style;
119        self.mark_dirty();
120    }
121
122    pub fn style(&self) -> Style {
123        self.0.borrow().style
124    }
125
126    pub fn mark_dirty(&mut self) {
127        let node = self.0.borrow_mut();
128        node.layout_cache.replace(None);
129
130        for parent in &node.parents {
131            if let Some(parent) = parent.upgrade() {
132                Node(parent).mark_dirty();
133            }
134        }
135    }
136
137    pub fn is_dirty(&mut self) -> bool {
138        let node = self.0.borrow();
139        let layout_cache = node.layout_cache.borrow();
140        if let Some(_) = layout_cache.as_ref() {
141            false
142        } else {
143            true
144        }
145    }
146
147    pub fn compute_layout(&self, size: Size<Number>) -> Result<Layout> {
148        algo::compute(&self.0.borrow(), size)
149    }
150}
151
152impl fmt::Debug for Node {
153    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154        let style = &self.0.borrow().style;
155        let children: Vec<_> = self.0.borrow().children.iter().map(|c| Node(Rc::clone(c))).collect();
156        write!(f, "Node {{ style: {:?}, children: {:?} }}", style, children)
157    }
158}
159
160impl PartialEq for Node {
161    fn eq(&self, other: &Node) -> bool {
162        Rc::ptr_eq(&self.0, &other.0)
163    }
164}
165
166impl Eq for Node {}