Implement `safe` and `unsafe` overflow-position alignment keywords (#952)
1use rand::distr::uniform::SampleRange;
2use rand::Rng;
3use rand_chacha::ChaCha8Rng;
4use taffy::style::Style as TaffyStyle;
5
6use super::{BuildTree, BuildTreeExt, GenStyle};
7
8pub struct Taffy03TreeBuilder<R: Rng, G: GenStyle<TaffyStyle>> {
9 rng: R,
10 style_generator: G,
11 tree: taffy_03::Taffy,
12 root: taffy_03::prelude::Node,
13}
14
15// Implement the BuildTree trait
16impl<R: Rng, G: GenStyle<TaffyStyle>> BuildTree<R, G> for Taffy03TreeBuilder<R, G> {
17 const NAME: &'static str = "Taffy 0.3";
18 type Tree = taffy_03::Taffy;
19 type Node = taffy_03::prelude::Node;
20
21 fn with_rng(mut rng: R, mut style_generator: G) -> Self {
22 let mut tree = taffy_03::Taffy::new();
23 let root = tree.new_leaf(convert_style(style_generator.create_root_style(&mut rng))).unwrap();
24 Taffy03TreeBuilder { rng, style_generator, tree, root }
25 }
26
27 fn compute_layout_inner(&mut self, available_width: Option<f32>, available_height: Option<f32>) {
28 let available_space =
29 taffy_03::geometry::Size { width: available_width.into(), height: available_height.into() };
30 self.tree.compute_layout(self.root, available_space).unwrap();
31 }
32
33 fn random_usize(&mut self, range: impl SampleRange<usize>) -> usize {
34 self.rng.random_range(range)
35 }
36
37 fn create_leaf_node(&mut self) -> Self::Node {
38 let style = self.style_generator.create_leaf_style(&mut self.rng);
39 self.tree.new_leaf(convert_style(style)).unwrap()
40 }
41
42 fn create_container_node(&mut self, children: &[Self::Node]) -> Self::Node {
43 let style = self.style_generator.create_container_style(&mut self.rng);
44 self.tree.new_with_children(convert_style(style), children).unwrap()
45 }
46
47 fn total_node_count(&mut self) -> usize {
48 self.tree.total_node_count()
49 }
50
51 fn set_root_children(&mut self, children: &[Self::Node]) {
52 self.tree.set_children(self.root, children).unwrap();
53 }
54
55 fn into_tree_and_root(self) -> (Self::Tree, Self::Node) {
56 (self.tree, self.root)
57 }
58}
59
60impl<G: GenStyle<TaffyStyle>> BuildTreeExt<G> for Taffy03TreeBuilder<ChaCha8Rng, G> {}
61
62fn convert_style(style: taffy::style::Style) -> taffy_03::style::Style {
63 taffy_03::style::Style {
64 display: convert_display(style.display),
65 position: convert_position(style.position),
66 inset: convert_rect(style.inset, convert_length_percentage_auto),
67 margin: convert_rect(style.margin, convert_length_percentage_auto),
68 padding: convert_rect(style.padding, convert_length_percentage),
69 border: convert_rect(style.border, convert_length_percentage),
70 size: convert_size(style.size, convert_dimension),
71 min_size: convert_size(style.min_size, convert_dimension),
72 max_size: convert_size(style.max_size, convert_dimension),
73 aspect_ratio: style.aspect_ratio,
74 gap: convert_size(style.gap, convert_length_percentage),
75 // Alignment
76 align_items: None,
77 align_self: None,
78 justify_items: None,
79 justify_self: None,
80 align_content: None,
81 justify_content: None,
82 // Flexbox
83 flex_direction: convert_flex_direction(style.flex_direction),
84 flex_wrap: convert_flex_wrap(style.flex_wrap),
85 flex_grow: style.flex_grow,
86 flex_shrink: style.flex_shrink,
87 flex_basis: convert_dimension(style.flex_basis),
88 // Grid
89 grid_template_rows: Vec::new(),
90 grid_template_columns: Vec::new(),
91 grid_auto_rows: Vec::new(),
92 grid_auto_columns: Vec::new(),
93 grid_auto_flow: taffy_03::style::GridAutoFlow::Row,
94 grid_row: taffy_03::geometry::Line {
95 start: taffy_03::style::GridPlacement::Auto,
96 end: taffy_03::style::GridPlacement::Auto,
97 },
98 grid_column: taffy_03::geometry::Line {
99 start: taffy_03::style::GridPlacement::Auto,
100 end: taffy_03::style::GridPlacement::Auto,
101 },
102 }
103}
104
105fn convert_rect<T, U, F: Fn(T) -> U>(input: taffy::geometry::Rect<T>, map: F) -> taffy_03::geometry::Rect<U> {
106 taffy_03::geometry::Rect {
107 left: map(input.left),
108 right: map(input.right),
109 top: map(input.top),
110 bottom: map(input.bottom),
111 }
112}
113
114fn convert_size<T, U, F: Fn(T) -> U>(input: taffy::geometry::Size<T>, map: F) -> taffy_03::geometry::Size<U> {
115 taffy_03::geometry::Size { width: map(input.width), height: map(input.height) }
116}
117
118fn convert_point<T, U, F: Fn(T) -> U>(input: taffy::geometry::Point<T>, map: F) -> taffy_03::geometry::Point<U> {
119 taffy_03::geometry::Point { x: map(input.x), y: map(input.y) }
120}
121
122fn convert_dimension(input: taffy::style::Dimension) -> taffy_03::style::Dimension {
123 let raw = input.into_raw();
124 match raw.tag() {
125 taffy::style::CompactLength::LENGTH_TAG => taffy_03::style::Dimension::Points(raw.value()),
126 taffy::style::CompactLength::PERCENT_TAG => taffy_03::style::Dimension::Percent(raw.value()),
127 taffy::style::CompactLength::AUTO_TAG => taffy_03::style::Dimension::Auto,
128 _ => panic!("unsupported Dimension variant"),
129 }
130}
131
132fn convert_length_percentage_auto(input: taffy::style::LengthPercentageAuto) -> taffy_03::style::LengthPercentageAuto {
133 let raw = input.into_raw();
134 match raw.tag() {
135 taffy::style::CompactLength::LENGTH_TAG => taffy_03::style::LengthPercentageAuto::Points(raw.value()),
136 taffy::style::CompactLength::PERCENT_TAG => taffy_03::style::LengthPercentageAuto::Percent(raw.value()),
137 taffy::style::CompactLength::AUTO_TAG => taffy_03::style::LengthPercentageAuto::Auto,
138 _ => panic!("unsupported LengthPercentageAuto variant"),
139 }
140}
141
142fn convert_length_percentage(input: taffy::style::LengthPercentage) -> taffy_03::style::LengthPercentage {
143 let raw = input.into_raw();
144 match raw.tag() {
145 taffy::style::CompactLength::LENGTH_TAG => taffy_03::style::LengthPercentage::Points(raw.value()),
146 taffy::style::CompactLength::PERCENT_TAG => taffy_03::style::LengthPercentage::Percent(raw.value()),
147 _ => panic!("unsupported LengthPercentage variant"),
148 }
149}
150
151fn convert_display(input: taffy::style::Display) -> taffy_03::style::Display {
152 match input {
153 taffy::style::Display::None => taffy_03::style::Display::None,
154 taffy::style::Display::Flex => taffy_03::style::Display::Flex,
155 taffy::style::Display::Grid => taffy_03::style::Display::Grid,
156 taffy::style::Display::Block => panic!("Block layout not implemented in taffy 0.3"),
157 }
158}
159
160fn convert_position(input: taffy::style::Position) -> taffy_03::style::Position {
161 match input {
162 taffy::style::Position::Relative => taffy_03::style::Position::Relative,
163 taffy::style::Position::Absolute => taffy_03::style::Position::Absolute,
164 }
165}
166
167fn convert_flex_direction(input: taffy::style::FlexDirection) -> taffy_03::style::FlexDirection {
168 match input {
169 taffy::style::FlexDirection::Row => taffy_03::style::FlexDirection::Row,
170 taffy::style::FlexDirection::Column => taffy_03::style::FlexDirection::Column,
171 taffy::style::FlexDirection::RowReverse => taffy_03::style::FlexDirection::RowReverse,
172 taffy::style::FlexDirection::ColumnReverse => taffy_03::style::FlexDirection::ColumnReverse,
173 }
174}
175
176fn convert_flex_wrap(input: taffy::style::FlexWrap) -> taffy_03::style::FlexWrap {
177 match input {
178 taffy::style::FlexWrap::NoWrap => taffy_03::style::FlexWrap::NoWrap,
179 taffy::style::FlexWrap::Wrap => taffy_03::style::FlexWrap::Wrap,
180 taffy::style::FlexWrap::WrapReverse => taffy_03::style::FlexWrap::WrapReverse,
181 }
182}