tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5364Rust 86Markdown 12TOML 91841 Definiciones

⎇ 6031fa21b5800de29385e8426daa4f4929754601 benches/src/yoga_helpers.rs Rust · 248 líneas · 10.0 KB Historia Quién tocó qué crudo

Refactor benchmarks (#472) 6031fa21b · Nico Burns ·

1#![allow(dead_code)]
2
3use rand::distributions::uniform::SampleRange;
4use rand::Rng;
5use rand_chacha::ChaCha8Rng;
6use slotmap::{DefaultKey, SlotMap};
7
8use super::{BuildTree, BuildTreeExt, GenStyle};
9
10pub mod yg {
11    pub use ordered_float::OrderedFloat;
12    pub use slotmap::{DefaultKey, SlotMap};
13    pub use yoga::types::*;
14    pub use yoga::Node;
15
16    pub type NodeId = DefaultKey;
17    pub type YogaTree = SlotMap<DefaultKey, Node>;
18}
19mod tf {
20    pub use taffy::prelude::*;
21}
22use tf::Style as TaffyStyle;
23
24pub struct YogaTreeBuilder<R: Rng, G: GenStyle<TaffyStyle>> {
25    rng: R,
26    style_generator: G,
27    tree: yg::YogaTree,
28    root: yg::DefaultKey,
29}
30
31// Implement the BuildTree trait
32impl<R: Rng, G: GenStyle<TaffyStyle>> BuildTree<R, G> for YogaTreeBuilder<R, G> {
33    type Tree = yg::YogaTree;
34    type Node = DefaultKey;
35
36    fn with_rng(mut rng: R, mut style_generator: G) -> Self {
37        let mut tree = SlotMap::new();
38        let root = create_yg_node(&mut tree, &style_generator.create_root_style(&mut rng), &[]);
39        YogaTreeBuilder { rng, style_generator, tree, root }
40    }
41
42    fn random_usize(&mut self, range: impl SampleRange<usize>) -> usize {
43        self.rng.gen_range(range)
44    }
45
46    fn create_leaf_node(&mut self) -> Self::Node {
47        let style = self.style_generator.create_leaf_style(&mut self.rng);
48        create_yg_node(&mut self.tree, &style, &[])
49    }
50
51    fn create_container_node(&mut self, children: &[Self::Node]) -> Self::Node {
52        let style = self.style_generator.create_container_style(&mut self.rng);
53        create_yg_node(&mut self.tree, &style, &children)
54    }
55
56    fn set_root_children(&mut self, children: &[Self::Node]) {
57        set_node_children(&mut self.tree, self.root, &children);
58    }
59
60    fn total_node_count(&mut self) -> usize {
61        self.tree.len()
62    }
63
64    fn into_tree_and_root(self) -> (Self::Tree, Self::Node) {
65        (self.tree, self.root)
66    }
67}
68
69impl<G: GenStyle<TaffyStyle>> BuildTreeExt<G> for YogaTreeBuilder<ChaCha8Rng, G> {}
70
71// impl<R: Rng, G: GenStyle<TaffyStyle>> YogaTreeBuilder<R, G> {
72//     /// Create a YogaTreeBuilder with a standard rng from a style generator
73//     fn new<NG: GenStyle<TaffyStyle>>(mut style_generator: NG) -> YogaTreeBuilder<ChaCha8Rng, NG> {
74//         let mut rng = ChaCha8Rng::seed_from_u64(STANDARD_RNG_SEED);
75//         let mut tree = SlotMap::new();
76//         let root = create_yg_node(&mut tree, &style_generator.create_root_style(&mut rng), &[]);
77//         YogaTreeBuilder { rng, style_generator, tree, root }
78//     }
79
80//     /// Create a YogaTreeBuilder with a standard rng from a style generator
81//     fn with_seed<NG: GenStyle<TaffyStyle>>(seed: u64, mut style_generator: NG) -> YogaTreeBuilder<ChaCha8Rng, NG> {
82//         let mut rng = ChaCha8Rng::seed_from_u64(seed);
83//         let mut tree = SlotMap::new();
84//         let root = create_yg_node(&mut tree, &style_generator.create_root_style(&mut rng), &[]);
85//         YogaTreeBuilder { rng, style_generator, tree, root }
86//     }
87
88//     /// Create a YogaTreeBuilder from a random number generator and a style generator
89//     fn with_rng<NR: Rng, NG: GenStyle<TaffyStyle>>(mut rng: NR, mut style_generator: NG) -> YogaTreeBuilder<NR, NG> {
90//         let mut tree = SlotMap::new();
91//         let root = create_yg_node(&mut tree, &style_generator.create_root_style(&mut rng), &[]);
92//         YogaTreeBuilder { rng, style_generator, tree, root }
93//     }
94// }
95
96fn create_yg_node(tree: &mut yg::YogaTree, style: &tf::Style, children: &[yg::DefaultKey]) -> yg::DefaultKey {
97    let mut node = yg::Node::new();
98    apply_taffy_style(&mut node, &style);
99    for (i, child) in children.into_iter().enumerate() {
100        node.insert_child(&mut tree[*child], i as u32);
101    }
102    tree.insert(node)
103}
104
105pub fn new_default_style_with_children(tree: &mut yg::YogaTree, children: &[yg::DefaultKey]) -> yg::DefaultKey {
106    let mut node = yg::Node::new();
107    for (i, child) in children.into_iter().enumerate() {
108        node.insert_child(&mut tree[*child], i as u32);
109    }
110    tree.insert(node)
111}
112
113fn set_node_children(tree: &mut yg::YogaTree, node_id: yg::DefaultKey, children: &[yg::DefaultKey]) {
114    // TODO: clear existing children.
115    for (i, child_id) in children.into_iter().enumerate() {
116        let [node, child] = tree.get_disjoint_mut([node_id, *child_id]).unwrap();
117        node.insert_child(child, i as u32);
118    }
119}
120
121fn into_yg_units(dim: impl Into<tf::Dimension>) -> yg::StyleUnit {
122    match dim.into() {
123        tf::Dimension::Auto => yg::StyleUnit::Auto,
124        tf::Dimension::Length(val) => yg::StyleUnit::Point(yg::OrderedFloat(val)),
125        tf::Dimension::Percent(val) => yg::StyleUnit::Percent(yg::OrderedFloat(val)),
126    }
127}
128
129fn into_pixels(dim: impl Into<tf::Dimension>) -> f32 {
130    dim.into().into_option().unwrap_or(0.0)
131}
132
133fn items_into_align(align: Option<tf::AlignSelf>) -> yg::Align {
134    match align {
135        None => yg::Align::Auto,
136        Some(tf::AlignSelf::FlexStart) => yg::Align::FlexStart,
137        Some(tf::AlignSelf::FlexEnd) => yg::Align::FlexEnd,
138        Some(tf::AlignSelf::Center) => yg::Align::Center,
139        Some(tf::AlignSelf::Baseline) => yg::Align::Baseline,
140        Some(tf::AlignSelf::Stretch) => yg::Align::Stretch,
141        Some(tf::AlignSelf::Start) => unimplemented!(),
142        Some(tf::AlignSelf::End) => unimplemented!(),
143    }
144}
145
146fn content_into_align(align: Option<tf::AlignContent>) -> yg::Align {
147    match align {
148        None => yg::Align::Auto,
149        Some(tf::AlignContent::FlexStart) => yg::Align::FlexStart,
150        Some(tf::AlignContent::Start) => yg::Align::FlexStart,
151        Some(tf::AlignContent::FlexEnd) => yg::Align::FlexEnd,
152        Some(tf::AlignContent::End) => yg::Align::FlexEnd,
153        Some(tf::AlignContent::Center) => yg::Align::Center,
154        Some(tf::AlignContent::Stretch) => yg::Align::Stretch,
155        Some(tf::AlignContent::SpaceBetween) => yg::Align::SpaceBetween,
156        Some(tf::AlignContent::SpaceAround) => yg::Align::SpaceAround,
157        Some(tf::AlignContent::SpaceEvenly) => unimplemented!(),
158    }
159}
160
161fn content_into_justify(align: Option<tf::JustifyContent>) -> yg::Justify {
162    match align {
163        None => yg::Justify::FlexStart,
164        Some(tf::JustifyContent::FlexStart) => yg::Justify::FlexStart,
165        Some(tf::JustifyContent::Start) => yg::Justify::FlexStart,
166        Some(tf::JustifyContent::FlexEnd) => yg::Justify::FlexEnd,
167        Some(tf::JustifyContent::End) => yg::Justify::FlexEnd,
168        Some(tf::JustifyContent::Center) => yg::Justify::Center,
169        Some(tf::JustifyContent::SpaceBetween) => yg::Justify::SpaceBetween,
170        Some(tf::JustifyContent::SpaceAround) => yg::Justify::SpaceAround,
171        Some(tf::JustifyContent::Stretch) => unimplemented!(),
172        Some(tf::JustifyContent::SpaceEvenly) => unimplemented!(),
173    }
174}
175
176fn apply_taffy_style(node: &mut yg::Node, style: &tf::Style) {
177    // display
178    node.set_display(match style.display {
179        tf::Display::None => yg::Display::None,
180        tf::Display::Flex => yg::Display::Flex,
181        tf::Display::Grid => panic!("Yoga does not support CSS Grid layout"),
182        tf::Display::Block => panic!("Yoga does not support CSS Block layout"),
183    });
184
185    // position
186    node.set_position_type(match style.position {
187        tf::Position::Relative => yg::PositionType::Relative,
188        tf::Position::Absolute => yg::PositionType::Absolute,
189    });
190    // inset
191    node.set_position(yg::Edge::Left, into_yg_units(style.inset.left));
192    node.set_position(yg::Edge::Right, into_yg_units(style.inset.right));
193    node.set_position(yg::Edge::Top, into_yg_units(style.inset.top));
194    node.set_position(yg::Edge::Bottom, into_yg_units(style.inset.bottom));
195
196    // sizes
197    node.set_width(into_yg_units(style.size.width));
198    node.set_height(into_yg_units(style.size.height));
199    node.set_min_width(into_yg_units(style.min_size.width));
200    node.set_min_height(into_yg_units(style.min_size.height));
201    node.set_max_width(into_yg_units(style.max_size.width));
202    node.set_max_height(into_yg_units(style.max_size.height));
203
204    // aspect_ratio
205    if let Some(aspect_ratio) = style.aspect_ratio {
206        node.set_aspect_ratio(aspect_ratio);
207    }
208
209    // spacing
210    node.set_padding(yg::Edge::Left, into_yg_units(style.padding.left));
211    node.set_padding(yg::Edge::Right, into_yg_units(style.padding.right));
212    node.set_padding(yg::Edge::Top, into_yg_units(style.padding.top));
213    node.set_padding(yg::Edge::Bottom, into_yg_units(style.padding.bottom));
214    node.set_margin(yg::Edge::Left, into_yg_units(style.margin.left));
215    node.set_margin(yg::Edge::Right, into_yg_units(style.margin.right));
216    node.set_margin(yg::Edge::Top, into_yg_units(style.margin.top));
217    node.set_margin(yg::Edge::Bottom, into_yg_units(style.margin.bottom));
218    node.set_border(yg::Edge::Left, into_pixels(style.border.left));
219    node.set_border(yg::Edge::Right, into_pixels(style.border.right));
220    node.set_border(yg::Edge::Top, into_pixels(style.border.top));
221    node.set_border(yg::Edge::Bottom, into_pixels(style.border.bottom));
222
223    // alignment
224    node.set_align_items(items_into_align(style.align_items));
225    node.set_align_self(items_into_align(style.align_self));
226    node.set_align_content(content_into_align(style.align_content));
227    node.set_justify_content(content_into_justify(style.justify_content));
228
229    // gap
230    node.set_column_gap(into_pixels(style.gap.width));
231    node.set_row_gap(into_pixels(style.gap.height));
232
233    // flex
234    node.set_flex_direction(match style.flex_direction {
235        tf::FlexDirection::Row => yg::FlexDirection::Row,
236        tf::FlexDirection::Column => yg::FlexDirection::Column,
237        tf::FlexDirection::RowReverse => yg::FlexDirection::RowReverse,
238        tf::FlexDirection::ColumnReverse => yg::FlexDirection::ColumnReverse,
239    });
240    node.set_flex_wrap(match style.flex_wrap {
241        tf::FlexWrap::NoWrap => yg::Wrap::NoWrap,
242        tf::FlexWrap::Wrap => yg::Wrap::Wrap,
243        tf::FlexWrap::WrapReverse => yg::Wrap::WrapReverse,
244    });
245    node.set_flex_basis(into_yg_units(style.flex_basis));
246    node.set_flex_grow(style.flex_grow);
247    node.set_flex_shrink(style.flex_shrink);
248}