telar_ui_tree/
render_node.rs1use std::cell::RefCell;
2use std::sync::Arc;
3
4use geometry_core::Rect;
5use renderer_core::{
6 BorderRadius, DrawCommand, PathData, PathStyle, RectStyle, TextRun, TextStyle,
7};
8
9thread_local! {
10 static NODE_VEC_POOL: RefCell<Vec<Vec<RenderNode>>> = const { RefCell::new(Vec::new()) };
11}
12
13pub struct NodeVec(Vec<RenderNode>);
14
15impl NodeVec {
16 pub fn collect(iter: impl IntoIterator<Item = RenderNode>) -> Self {
17 let mut v = NODE_VEC_POOL
18 .with_borrow_mut(|pool| pool.pop())
19 .unwrap_or_default();
20 v.extend(iter);
21 NodeVec(v)
22 }
23}
24
25impl Drop for NodeVec {
26 fn drop(&mut self) {
27 let mut v = std::mem::take(&mut self.0);
28 v.clear();
29 NODE_VEC_POOL.with_borrow_mut(|pool| {
30 if pool.len() < 32 {
31 pool.push(v);
32 }
33 });
34 }
35}
36
37impl std::ops::Deref for NodeVec {
38 type Target = [RenderNode];
39 fn deref(&self) -> &[RenderNode] {
40 &self.0
41 }
42}
43
44impl IntoIterator for NodeVec {
45 type Item = RenderNode;
46 type IntoIter = std::vec::IntoIter<RenderNode>;
47 fn into_iter(self) -> Self::IntoIter {
48 let mut md = std::mem::ManuallyDrop::new(self);
50 let v = std::mem::take(&mut md.0);
51 v.into_iter()
52 }
53}
54
55pub enum RenderNode {
56 Empty,
57 Primitive(DrawCommand),
58 Group {
59 children: NodeVec,
60 },
61 Transform {
62 matrix: [f32; 6],
63 children: NodeVec,
64 },
65 Clip {
66 rect: Rect,
67 radius: BorderRadius,
68 children: NodeVec,
69 },
70 Layer {
71 opacity: f32,
72 backdrop_blur: f32,
73 children: NodeVec,
74 },
75 Overlay {
79 children: NodeVec,
80 },
81 Boundary {
83 child: std::rc::Rc<crate::segment::Segment>,
84 },
85}
86
87impl RenderNode {
88 pub fn group(children: impl IntoIterator<Item = RenderNode>) -> Self {
89 Self::Group {
90 children: NodeVec::collect(children),
91 }
92 }
93
94 pub fn rect(rect: Rect, style: RectStyle) -> Self {
95 Self::Primitive(DrawCommand::Rect {
96 rect,
97 style: Arc::new(style),
98 })
99 }
100
101 pub fn text(text: impl Into<Arc<str>>, rect: Rect, style: TextStyle) -> Self {
102 Self::Primitive(DrawCommand::Text {
103 text: text.into(),
104 rect,
105 style: Arc::new(style),
106 })
107 }
108
109 pub fn rich_text(runs: Arc<[TextRun]>, rect: Rect, base: TextStyle) -> Self {
110 Self::Primitive(DrawCommand::RichText {
111 runs,
112 rect,
113 base: Arc::new(base),
114 })
115 }
116
117 pub fn path(data: Arc<PathData>, style: PathStyle) -> Self {
118 Self::Primitive(DrawCommand::Path {
119 data,
120 style: Arc::new(style),
121 })
122 }
123
124 pub fn transform_with(
125 matrix: [f32; 6],
126 children: impl IntoIterator<Item = RenderNode>,
127 ) -> Self {
128 Self::Transform {
129 matrix,
130 children: NodeVec::collect(children),
131 }
132 }
133
134 pub fn layer(
135 opacity: f32,
136 backdrop_blur: f32,
137 children: impl IntoIterator<Item = RenderNode>,
138 ) -> Self {
139 Self::Layer {
140 opacity,
141 backdrop_blur,
142 children: NodeVec::collect(children),
143 }
144 }
145
146 pub fn overlay(children: impl IntoIterator<Item = RenderNode>) -> Self {
148 Self::Overlay {
149 children: NodeVec::collect(children),
150 }
151 }
152}