gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 501HTML 254C 19JavaScript 81414 Sutichaykuna

⎇ 59cd7a4b3ab55aed5f1eb7cdf2dd4a739875345d src/style.rs Rust · 375 siq'ikuna · 9.0 KB Ñawpa willay Pi imata llamkarqan ch'uya

Add (nightly) no_std support 30c626da4 · Maximilian Goisser ·

1#[cfg(not(feature = "std"))]
2use alloc::boxed::Box;
3#[cfg(not(feature = "std"))]
4use alloc::{vec, vec::Vec};
5
6use crate::algo;
7use crate::geometry::{Rect, Size};
8use crate::number::Number;
9
10#[derive(Copy, Clone, PartialEq, Debug)]
11pub enum AlignItems {
12    FlexStart,
13    FlexEnd,
14    Center,
15    Baseline,
16    Stretch,
17}
18
19impl Default for AlignItems {
20    fn default() -> AlignItems {
21        AlignItems::Stretch
22    }
23}
24
25#[derive(Copy, Clone, PartialEq, Debug)]
26pub enum AlignSelf {
27    Auto,
28    FlexStart,
29    FlexEnd,
30    Center,
31    Baseline,
32    Stretch,
33}
34
35impl Default for AlignSelf {
36    fn default() -> AlignSelf {
37        AlignSelf::Auto
38    }
39}
40
41#[derive(Copy, Clone, PartialEq, Debug)]
42pub enum AlignContent {
43    FlexStart,
44    FlexEnd,
45    Center,
46    Stretch,
47    SpaceBetween,
48    SpaceAround,
49}
50
51impl Default for AlignContent {
52    fn default() -> AlignContent {
53        AlignContent::Stretch
54    }
55}
56
57#[derive(Copy, Clone, PartialEq, Debug)]
58pub enum Direction {
59    Inherit,
60    LTR,
61    RTL,
62}
63
64impl Default for Direction {
65    fn default() -> Direction {
66        Direction::Inherit
67    }
68}
69
70#[derive(Copy, Clone, PartialEq, Debug)]
71pub enum Display {
72    Flex,
73    None,
74}
75
76impl Default for Display {
77    fn default() -> Display {
78        Display::Flex
79    }
80}
81
82#[derive(Copy, Clone, PartialEq, Debug)]
83pub enum FlexDirection {
84    Row,
85    Column,
86    RowReverse,
87    ColumnReverse,
88}
89
90impl Default for FlexDirection {
91    fn default() -> FlexDirection {
92        FlexDirection::Row
93    }
94}
95
96impl FlexDirection {
97    pub(crate) fn is_row(self) -> bool {
98        self == FlexDirection::Row || self == FlexDirection::RowReverse
99    }
100
101    pub(crate) fn is_column(self) -> bool {
102        self == FlexDirection::Column || self == FlexDirection::ColumnReverse
103    }
104
105    pub(crate) fn is_reverse(self) -> bool {
106        self == FlexDirection::RowReverse || self == FlexDirection::ColumnReverse
107    }
108}
109
110#[derive(Copy, Clone, PartialEq, Debug)]
111pub enum JustifyContent {
112    FlexStart,
113    FlexEnd,
114    Center,
115    SpaceBetween,
116    SpaceAround,
117    SpaceEvenly,
118}
119
120impl Default for JustifyContent {
121    fn default() -> JustifyContent {
122        JustifyContent::FlexStart
123    }
124}
125
126#[derive(Copy, Clone, PartialEq, Debug)]
127pub enum Overflow {
128    Visible,
129    Hidden,
130    Scroll,
131}
132
133impl Default for Overflow {
134    fn default() -> Overflow {
135        Overflow::Visible
136    }
137}
138
139#[derive(Copy, Clone, PartialEq, Debug)]
140pub enum PositionType {
141    Relative,
142    Absolute,
143}
144
145impl Default for PositionType {
146    fn default() -> PositionType {
147        PositionType::Relative
148    }
149}
150
151#[derive(Copy, Clone, PartialEq, Debug)]
152pub enum FlexWrap {
153    NoWrap,
154    Wrap,
155    WrapReverse,
156}
157
158impl Default for FlexWrap {
159    fn default() -> FlexWrap {
160        FlexWrap::NoWrap
161    }
162}
163
164#[derive(Copy, Clone, PartialEq, Debug)]
165pub enum Dimension {
166    Undefined,
167    Auto,
168    Points(f32),
169    Percent(f32),
170}
171
172impl Default for Dimension {
173    fn default() -> Dimension {
174        Dimension::Undefined
175    }
176}
177
178impl Dimension {
179    pub(crate) fn resolve(self, parent_width: Number) -> Number {
180        match self {
181            Dimension::Points(points) => Number::Defined(points),
182            Dimension::Percent(percent) => parent_width * percent,
183            _ => Number::Undefined,
184        }
185    }
186
187    pub(crate) fn is_defined(self) -> bool {
188        match self {
189            Dimension::Points(_) => true,
190            Dimension::Percent(_) => true,
191            _ => false,
192        }
193    }
194}
195
196impl Default for Rect<Dimension> {
197    fn default() -> Rect<Dimension> {
198        Rect { start: Default::default(), end: Default::default(), top: Default::default(), bottom: Default::default() }
199    }
200}
201
202impl Default for Size<Dimension> {
203    fn default() -> Size<Dimension> {
204        Size { width: Dimension::Auto, height: Dimension::Auto }
205    }
206}
207
208type MeasureFunc = Box<Fn(Size<Number>) -> Size<f32>>;
209
210#[derive(Debug, Clone)]
211pub struct LayoutCache {
212    pub node_size: Size<Number>,
213    pub parent_size: Size<Number>,
214    pub percent_calc_base: Number,
215    pub perform_layout: bool,
216
217    pub result: algo::ComputeResult,
218}
219
220pub struct Node {
221    pub display: Display,
222
223    pub position_type: PositionType,
224    pub direction: Direction,
225    pub flex_direction: FlexDirection,
226
227    pub flex_wrap: FlexWrap,
228    pub overflow: Overflow,
229
230    pub align_items: AlignItems,
231    pub align_self: AlignSelf,
232    pub align_content: AlignContent,
233
234    pub justify_content: JustifyContent,
235
236    pub position: Rect<Dimension>,
237    pub margin: Rect<Dimension>,
238    pub padding: Rect<Dimension>,
239    pub border: Rect<Dimension>,
240
241    pub flex_grow: f32,
242    pub flex_shrink: f32,
243    pub flex_basis: Dimension,
244
245    pub size: Size<Dimension>,
246    pub min_size: Size<Dimension>,
247    pub max_size: Size<Dimension>,
248
249    pub aspect_ratio: Number,
250    pub measure: Option<MeasureFunc>,
251
252    pub children: Vec<Node>,
253
254    pub layout_cache: core::cell::RefCell<Option<LayoutCache>>,
255}
256
257impl Default for Node {
258    fn default() -> Node {
259        Node {
260            display: Default::default(),
261
262            position_type: Default::default(),
263            direction: Default::default(),
264            flex_direction: Default::default(),
265
266            flex_wrap: Default::default(),
267            overflow: Default::default(),
268
269            align_items: Default::default(),
270            align_self: Default::default(),
271            align_content: Default::default(),
272
273            justify_content: Default::default(),
274
275            position: Default::default(),
276            margin: Default::default(),
277            padding: Default::default(),
278            border: Default::default(),
279
280            flex_grow: 0.0,
281            flex_shrink: 1.0,
282            flex_basis: Dimension::Auto,
283
284            size: Default::default(),
285            min_size: Default::default(),
286            max_size: Default::default(),
287
288            aspect_ratio: Default::default(),
289            measure: None,
290
291            children: vec![],
292
293            layout_cache: core::cell::RefCell::new(None),
294        }
295    }
296}
297
298impl Node {
299    pub(crate) fn min_main_size(&self, direction: FlexDirection) -> Dimension {
300        match direction {
301            FlexDirection::Row | FlexDirection::RowReverse => self.min_size.width,
302            FlexDirection::Column | FlexDirection::ColumnReverse => self.min_size.height,
303        }
304    }
305
306    pub(crate) fn max_main_size(&self, direction: FlexDirection) -> Dimension {
307        match direction {
308            FlexDirection::Row | FlexDirection::RowReverse => self.max_size.width,
309            FlexDirection::Column | FlexDirection::ColumnReverse => self.max_size.height,
310        }
311    }
312
313    pub(crate) fn main_margin_start(&self, direction: FlexDirection) -> Dimension {
314        match direction {
315            FlexDirection::Row | FlexDirection::RowReverse => self.margin.start,
316            FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.top,
317        }
318    }
319
320    pub(crate) fn main_margin_end(&self, direction: FlexDirection) -> Dimension {
321        match direction {
322            FlexDirection::Row | FlexDirection::RowReverse => self.margin.end,
323            FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.bottom,
324        }
325    }
326
327    pub(crate) fn cross_size(&self, direction: FlexDirection) -> Dimension {
328        match direction {
329            FlexDirection::Row | FlexDirection::RowReverse => self.size.height,
330            FlexDirection::Column | FlexDirection::ColumnReverse => self.size.width,
331        }
332    }
333
334    pub(crate) fn min_cross_size(&self, direction: FlexDirection) -> Dimension {
335        match direction {
336            FlexDirection::Row | FlexDirection::RowReverse => self.min_size.height,
337            FlexDirection::Column | FlexDirection::ColumnReverse => self.min_size.width,
338        }
339    }
340
341    pub(crate) fn max_cross_size(&self, direction: FlexDirection) -> Dimension {
342        match direction {
343            FlexDirection::Row | FlexDirection::RowReverse => self.max_size.height,
344            FlexDirection::Column | FlexDirection::ColumnReverse => self.max_size.width,
345        }
346    }
347
348    pub(crate) fn cross_margin_start(&self, direction: FlexDirection) -> Dimension {
349        match direction {
350            FlexDirection::Row | FlexDirection::RowReverse => self.margin.top,
351            FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.start,
352        }
353    }
354
355    pub(crate) fn cross_margin_end(&self, direction: FlexDirection) -> Dimension {
356        match direction {
357            FlexDirection::Row | FlexDirection::RowReverse => self.margin.bottom,
358            FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.end,
359        }
360    }
361
362    pub(crate) fn align_self(&self, parent: &Node) -> AlignSelf {
363        if self.align_self == AlignSelf::Auto {
364            match parent.align_items {
365                AlignItems::FlexStart => AlignSelf::FlexStart,
366                AlignItems::FlexEnd => AlignSelf::FlexEnd,
367                AlignItems::Center => AlignSelf::Center,
368                AlignItems::Baseline => AlignSelf::Baseline,
369                AlignItems::Stretch => AlignSelf::Stretch,
370            }
371        } else {
372            self.align_self
373        }
374    }
375}