gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 230Rust 8TOML 3CSS 1315 Sutichaykuna

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

Fix percentage height to be based on container height dce51aaa5 · Emil Sjölander ·

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 perform_layout: bool,
215
216    pub result: algo::ComputeResult,
217}
218
219pub struct Node {
220    pub display: Display,
221
222    pub position_type: PositionType,
223    pub direction: Direction,
224    pub flex_direction: FlexDirection,
225
226    pub flex_wrap: FlexWrap,
227    pub overflow: Overflow,
228
229    pub align_items: AlignItems,
230    pub align_self: AlignSelf,
231    pub align_content: AlignContent,
232
233    pub justify_content: JustifyContent,
234
235    pub position: Rect<Dimension>,
236    pub margin: Rect<Dimension>,
237    pub padding: Rect<Dimension>,
238    pub border: Rect<Dimension>,
239
240    pub flex_grow: f32,
241    pub flex_shrink: f32,
242    pub flex_basis: Dimension,
243
244    pub size: Size<Dimension>,
245    pub min_size: Size<Dimension>,
246    pub max_size: Size<Dimension>,
247
248    pub aspect_ratio: Number,
249    pub measure: Option<MeasureFunc>,
250
251    pub children: Vec<Node>,
252
253    pub layout_cache: core::cell::RefCell<Option<LayoutCache>>,
254}
255
256impl Default for Node {
257    fn default() -> Node {
258        Node {
259            display: Default::default(),
260
261            position_type: Default::default(),
262            direction: Default::default(),
263            flex_direction: Default::default(),
264
265            flex_wrap: Default::default(),
266            overflow: Default::default(),
267
268            align_items: Default::default(),
269            align_self: Default::default(),
270            align_content: Default::default(),
271
272            justify_content: Default::default(),
273
274            position: Default::default(),
275            margin: Default::default(),
276            padding: Default::default(),
277            border: Default::default(),
278
279            flex_grow: 0.0,
280            flex_shrink: 1.0,
281            flex_basis: Dimension::Auto,
282
283            size: Default::default(),
284            min_size: Default::default(),
285            max_size: Default::default(),
286
287            aspect_ratio: Default::default(),
288            measure: None,
289
290            children: vec![],
291
292            layout_cache: core::cell::RefCell::new(None),
293        }
294    }
295}
296
297impl Node {
298    pub(crate) fn min_main_size(&self, direction: FlexDirection) -> Dimension {
299        match direction {
300            FlexDirection::Row | FlexDirection::RowReverse => self.min_size.width,
301            FlexDirection::Column | FlexDirection::ColumnReverse => self.min_size.height,
302        }
303    }
304
305    pub(crate) fn max_main_size(&self, direction: FlexDirection) -> Dimension {
306        match direction {
307            FlexDirection::Row | FlexDirection::RowReverse => self.max_size.width,
308            FlexDirection::Column | FlexDirection::ColumnReverse => self.max_size.height,
309        }
310    }
311
312    pub(crate) fn main_margin_start(&self, direction: FlexDirection) -> Dimension {
313        match direction {
314            FlexDirection::Row | FlexDirection::RowReverse => self.margin.start,
315            FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.top,
316        }
317    }
318
319    pub(crate) fn main_margin_end(&self, direction: FlexDirection) -> Dimension {
320        match direction {
321            FlexDirection::Row | FlexDirection::RowReverse => self.margin.end,
322            FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.bottom,
323        }
324    }
325
326    pub(crate) fn cross_size(&self, direction: FlexDirection) -> Dimension {
327        match direction {
328            FlexDirection::Row | FlexDirection::RowReverse => self.size.height,
329            FlexDirection::Column | FlexDirection::ColumnReverse => self.size.width,
330        }
331    }
332
333    pub(crate) fn min_cross_size(&self, direction: FlexDirection) -> Dimension {
334        match direction {
335            FlexDirection::Row | FlexDirection::RowReverse => self.min_size.height,
336            FlexDirection::Column | FlexDirection::ColumnReverse => self.min_size.width,
337        }
338    }
339
340    pub(crate) fn max_cross_size(&self, direction: FlexDirection) -> Dimension {
341        match direction {
342            FlexDirection::Row | FlexDirection::RowReverse => self.max_size.height,
343            FlexDirection::Column | FlexDirection::ColumnReverse => self.max_size.width,
344        }
345    }
346
347    pub(crate) fn cross_margin_start(&self, direction: FlexDirection) -> Dimension {
348        match direction {
349            FlexDirection::Row | FlexDirection::RowReverse => self.margin.top,
350            FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.start,
351        }
352    }
353
354    pub(crate) fn cross_margin_end(&self, direction: FlexDirection) -> Dimension {
355        match direction {
356            FlexDirection::Row | FlexDirection::RowReverse => self.margin.bottom,
357            FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.end,
358        }
359    }
360
361    pub(crate) fn align_self(&self, parent: &Node) -> AlignSelf {
362        if self.align_self == AlignSelf::Auto {
363            match parent.align_items {
364                AlignItems::FlexStart => AlignSelf::FlexStart,
365                AlignItems::FlexEnd => AlignSelf::FlexEnd,
366                AlignItems::Center => AlignSelf::Center,
367                AlignItems::Baseline => AlignSelf::Baseline,
368                AlignItems::Stretch => AlignSelf::Stretch,
369            }
370        } else {
371            self.align_self
372        }
373    }
374}