tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 1077HTML 1008Markdown 12TOML 83209 Definitions

⎇ 6740b9e59f12d3d0e3decb1514817a794f83325f src/style/mod.rs Rust · 1066 lines · 35.9 KB History Who touched what raw

Move CompactLength into it's own module (#787) 6740b9e59 · Nico Burns ·

1//! A typed representation of [CSS style properties](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) in Rust. Used as input to layout computation.
2mod alignment;
3mod available_space;
4mod compact_length;
5mod dimension;
6
7#[cfg(feature = "block_layout")]
8mod block;
9#[cfg(feature = "flexbox")]
10mod flex;
11#[cfg(feature = "grid")]
12mod grid;
13
14pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf};
15pub use self::available_space::AvailableSpace;
16pub use self::compact_length::CompactLength;
17pub use self::dimension::{Dimension, LengthPercentage, LengthPercentageAuto};
18
19#[cfg(feature = "block_layout")]
20pub use self::block::{BlockContainerStyle, BlockItemStyle, TextAlign};
21#[cfg(feature = "flexbox")]
22pub use self::flex::{FlexDirection, FlexWrap, FlexboxContainerStyle, FlexboxItemStyle};
23#[cfg(feature = "grid")]
24pub(crate) use self::grid::{GenericGridPlacement, OriginZeroGridPlacement};
25#[cfg(feature = "grid")]
26pub use self::grid::{
27    GridAutoFlow, GridContainerStyle, GridItemStyle, GridPlacement, GridTrackRepetition, MaxTrackSizingFunction,
28    MinTrackSizingFunction, NonRepeatedTrackSizingFunction, TrackSizingFunction,
29};
30
31use crate::geometry::{Point, Rect, Size};
32use crate::style_helpers::TaffyAuto as _;
33
34#[cfg(feature = "grid")]
35use crate::geometry::Line;
36#[cfg(feature = "serde")]
37use crate::style_helpers;
38#[cfg(feature = "grid")]
39use crate::util::sys::GridTrackVec;
40
41/// The core set of styles that are shared between all CSS layout nodes
42///
43/// Note that all methods come with a default implementation which simply returns the default value for that style property
44/// but this is a just a convenience to save on boilerplate for styles that your implementation doesn't support. You will need
45/// to override the default implementation for each style property that your style type actually supports.
46pub trait CoreStyle {
47    /// Which box generation mode should be used
48    #[inline(always)]
49    fn box_generation_mode(&self) -> BoxGenerationMode {
50        BoxGenerationMode::DEFAULT
51    }
52    /// Is block layout?
53    #[inline(always)]
54    fn is_block(&self) -> bool {
55        false
56    }
57    /// Which box do size styles apply to
58    #[inline(always)]
59    fn box_sizing(&self) -> BoxSizing {
60        BoxSizing::BorderBox
61    }
62
63    // Overflow properties
64    /// How children overflowing their container should affect layout
65    #[inline(always)]
66    fn overflow(&self) -> Point<Overflow> {
67        Style::DEFAULT.overflow
68    }
69    /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
70    #[inline(always)]
71    fn scrollbar_width(&self) -> f32 {
72        0.0
73    }
74
75    // Position properties
76    /// What should the `position` value of this struct use as a base offset?
77    #[inline(always)]
78    fn position(&self) -> Position {
79        Style::DEFAULT.position
80    }
81    /// How should the position of this element be tweaked relative to the layout defined?
82    #[inline(always)]
83    fn inset(&self) -> Rect<LengthPercentageAuto> {
84        Style::DEFAULT.inset
85    }
86
87    // Size properies
88    /// Sets the initial size of the item
89    #[inline(always)]
90    fn size(&self) -> Size<Dimension> {
91        Style::DEFAULT.size
92    }
93    /// Controls the minimum size of the item
94    #[inline(always)]
95    fn min_size(&self) -> Size<Dimension> {
96        Style::DEFAULT.min_size
97    }
98    /// Controls the maximum size of the item
99    #[inline(always)]
100    fn max_size(&self) -> Size<Dimension> {
101        Style::DEFAULT.max_size
102    }
103    /// Sets the preferred aspect ratio for the item
104    /// The ratio is calculated as width divided by height.
105    #[inline(always)]
106    fn aspect_ratio(&self) -> Option<f32> {
107        Style::DEFAULT.aspect_ratio
108    }
109
110    // Spacing Properties
111    /// How large should the margin be on each side?
112    #[inline(always)]
113    fn margin(&self) -> Rect<LengthPercentageAuto> {
114        Style::DEFAULT.margin
115    }
116    /// How large should the padding be on each side?
117    #[inline(always)]
118    fn padding(&self) -> Rect<LengthPercentage> {
119        Style::DEFAULT.padding
120    }
121    /// How large should the border be on each side?
122    #[inline(always)]
123    fn border(&self) -> Rect<LengthPercentage> {
124        Style::DEFAULT.border
125    }
126}
127
128/// Sets the layout used for the children of this node
129///
130/// The default values depends on on which feature flags are enabled. The order of precedence is: Flex, Grid, Block, None.
131#[derive(Copy, Clone, PartialEq, Eq, Debug)]
132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
133pub enum Display {
134    /// The children will follow the block layout algorithm
135    #[cfg(feature = "block_layout")]
136    Block,
137    /// The children will follow the flexbox layout algorithm
138    #[cfg(feature = "flexbox")]
139    Flex,
140    /// The children will follow the CSS Grid layout algorithm
141    #[cfg(feature = "grid")]
142    Grid,
143    /// The node is hidden, and it's children will also be hidden
144    None,
145}
146
147impl Display {
148    /// The default Display mode
149    #[cfg(feature = "flexbox")]
150    pub const DEFAULT: Display = Display::Flex;
151
152    /// The default Display mode
153    #[cfg(all(feature = "grid", not(feature = "flexbox")))]
154    pub const DEFAULT: Display = Display::Grid;
155
156    /// The default Display mode
157    #[cfg(all(feature = "block_layout", not(feature = "flexbox"), not(feature = "grid")))]
158    pub const DEFAULT: Display = Display::Block;
159
160    /// The default Display mode
161    #[cfg(all(not(feature = "flexbox"), not(feature = "grid"), not(feature = "block_layout")))]
162    pub const DEFAULT: Display = Display::None;
163}
164
165impl Default for Display {
166    fn default() -> Self {
167        Self::DEFAULT
168    }
169}
170
171impl core::fmt::Display for Display {
172    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
173        match self {
174            Display::None => write!(f, "NONE"),
175            #[cfg(feature = "block_layout")]
176            Display::Block => write!(f, "BLOCK"),
177            #[cfg(feature = "flexbox")]
178            Display::Flex => write!(f, "FLEX"),
179            #[cfg(feature = "grid")]
180            Display::Grid => write!(f, "GRID"),
181        }
182    }
183}
184
185/// An abstracted version of the CSS `display` property where any value other than "none" is represented by "normal"
186/// See: <https://www.w3.org/TR/css-display-3/#box-generation>
187#[derive(Copy, Clone, PartialEq, Eq, Debug)]
188#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
189pub enum BoxGenerationMode {
190    /// The node generates a box in the regular way
191    Normal,
192    /// The node and it's descendants generate no boxes (they are hidden)
193    None,
194}
195
196impl BoxGenerationMode {
197    /// The default of BoxGenerationMode
198    pub const DEFAULT: BoxGenerationMode = BoxGenerationMode::Normal;
199}
200
201impl Default for BoxGenerationMode {
202    fn default() -> Self {
203        Self::DEFAULT
204    }
205}
206
207/// The positioning strategy for this item.
208///
209/// This controls both how the origin is determined for the [`Style::position`] field,
210/// and whether or not the item will be controlled by flexbox's layout algorithm.
211///
212/// WARNING: this enum follows the behavior of [CSS's `position` property](https://developer.mozilla.org/en-US/docs/Web/CSS/position),
213/// which can be unintuitive.
214///
215/// [`Position::Relative`] is the default value, in contrast to the default behavior in CSS.
216#[derive(Copy, Clone, PartialEq, Eq, Debug)]
217#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
218pub enum Position {
219    /// The offset is computed relative to the final position given by the layout algorithm.
220    /// Offsets do not affect the position of any other items; they are effectively a correction factor applied at the end.
221    Relative,
222    /// The offset is computed relative to this item's closest positioned ancestor, if any.
223    /// Otherwise, it is placed relative to the origin.
224    /// No space is created for the item in the page layout, and its size will not be altered.
225    ///
226    /// WARNING: to opt-out of layouting entirely, you must use [`Display::None`] instead on your [`Style`] object.
227    Absolute,
228}
229
230impl Default for Position {
231    fn default() -> Self {
232        Self::Relative
233    }
234}
235
236/// Specifies whether size styles for this node are assigned to the node's "content box" or "border box"
237///
238/// - The "content box" is the node's inner size excluding padding, border and margin
239/// - The "border box" is the node's outer size including padding and border (but still excluding margin)
240///
241/// This property modifies the application of the following styles:
242///
243///   - `size`
244///   - `min_size`
245///   - `max_size`
246///   - `flex_basis`
247///
248/// See h<ttps://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing>
249#[derive(Copy, Clone, PartialEq, Eq, Debug)]
250#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
251pub enum BoxSizing {
252    /// Size styles such size, min_size, max_size specify the box's "content box" (the size excluding padding/border/margin)
253    BorderBox,
254    /// Size styles such size, min_size, max_size specify the box's "border box" (the size excluding margin but including padding/border)
255    ContentBox,
256}
257
258impl Default for BoxSizing {
259    fn default() -> Self {
260        Self::BorderBox
261    }
262}
263
264/// How children overflowing their container should affect layout
265///
266/// In CSS the primary effect of this property is to control whether contents of a parent container that overflow that container should
267/// be displayed anyway, be clipped, or trigger the container to become a scroll container. However it also has secondary effects on layout,
268/// the main ones being:
269///
270///   - The automatic minimum size Flexbox/CSS Grid items with non-`Visible` overflow is `0` rather than being content based
271///   - `Overflow::Scroll` nodes have space in the layout reserved for a scrollbar (width controlled by the `scrollbar_width` property)
272///
273/// In Taffy, we only implement the layout related secondary effects as we are not concerned with drawing/painting. The amount of space reserved for
274/// a scrollbar is controlled by the `scrollbar_width` property. If this is `0` then `Scroll` behaves identically to `Hidden`.
275///
276/// <https://developer.mozilla.org/en-US/docs/Web/CSS/overflow>
277#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
278#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
279pub enum Overflow {
280    /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
281    /// Content that overflows this node *should* contribute to the scroll region of its parent.
282    #[default]
283    Visible,
284    /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
285    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
286    Clip,
287    /// The automatic minimum size of this node as a flexbox/grid item should be `0`.
288    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
289    Hidden,
290    /// The automatic minimum size of this node as a flexbox/grid item should be `0`. Additionally, space should be reserved
291    /// for a scrollbar. The amount of space reserved is controlled by the `scrollbar_width` property.
292    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
293    Scroll,
294}
295
296impl Overflow {
297    /// Returns true for overflow modes that contain their contents (`Overflow::Hidden`, `Overflow::Scroll`, `Overflow::Auto`)
298    /// or else false for overflow modes that allow their contains to spill (`Overflow::Visible`).
299    #[inline(always)]
300    pub(crate) fn is_scroll_container(self) -> bool {
301        match self {
302            Self::Visible | Self::Clip => false,
303            Self::Hidden | Self::Scroll => true,
304        }
305    }
306
307    /// Returns `Some(0.0)` if the overflow mode would cause the automatic minimum size of a Flexbox or CSS Grid item
308    /// to be `0`. Else returns None.
309    #[inline(always)]
310    pub(crate) fn maybe_into_automatic_min_size(self) -> Option<f32> {
311        match self.is_scroll_container() {
312            true => Some(0.0),
313            false => None,
314        }
315    }
316}
317
318/// A typed representation of the CSS style information for a single node.
319///
320/// The most important idea in flexbox is the notion of a "main" and "cross" axis, which are always perpendicular to each other.
321/// The orientation of these axes are controlled via the [`FlexDirection`] field of this struct.
322///
323/// This struct follows the [CSS equivalent](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox) directly;
324/// information about the behavior on the web should transfer directly.
325///
326/// Detailed information about the exact behavior of each of these fields
327/// can be found on [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS) by searching for the field name.
328/// The distinction between margin, padding and border is explained well in
329/// this [introduction to the box model](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model).
330///
331/// If the behavior does not match the flexbox layout algorithm on the web, please file a bug!
332#[derive(Clone, PartialEq, Debug)]
333#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
334#[cfg_attr(feature = "serde", serde(default))]
335pub struct Style {
336    /// What layout strategy should be used?
337    pub display: Display,
338    /// Whether a child is display:table or not. This affects children of block layouts.
339    /// This should really be part of `Display`, but it is currently seperate because table layout isn't implemented
340    pub item_is_table: bool,
341    /// Should size styles apply to the content box or the border box of the node
342    pub box_sizing: BoxSizing,
343
344    // Overflow properties
345    /// How children overflowing their container should affect layout
346    pub overflow: Point<Overflow>,
347    /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
348    pub scrollbar_width: f32,
349
350    // Position properties
351    /// What should the `position` value of this struct use as a base offset?
352    pub position: Position,
353    /// How should the position of this element be tweaked relative to the layout defined?
354    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
355    pub inset: Rect<LengthPercentageAuto>,
356
357    // Size properties
358    /// Sets the initial size of the item
359    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
360    pub size: Size<Dimension>,
361    /// Controls the minimum size of the item
362    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
363    pub min_size: Size<Dimension>,
364    /// Controls the maximum size of the item
365    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
366    pub max_size: Size<Dimension>,
367    /// Sets the preferred aspect ratio for the item
368    ///
369    /// The ratio is calculated as width divided by height.
370    pub aspect_ratio: Option<f32>,
371
372    // Spacing Properties
373    /// How large should the margin be on each side?
374    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
375    pub margin: Rect<LengthPercentageAuto>,
376    /// How large should the padding be on each side?
377    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
378    pub padding: Rect<LengthPercentage>,
379    /// How large should the border be on each side?
380    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
381    pub border: Rect<LengthPercentage>,
382
383    // Alignment properties
384    /// How this node's children aligned in the cross/block axis?
385    #[cfg(any(feature = "flexbox", feature = "grid"))]
386    pub align_items: Option<AlignItems>,
387    /// How this node should be aligned in the cross/block axis
388    /// Falls back to the parents [`AlignItems`] if not set
389    #[cfg(any(feature = "flexbox", feature = "grid"))]
390    pub align_self: Option<AlignSelf>,
391    /// How this node's children should be aligned in the inline axis
392    #[cfg(feature = "grid")]
393    pub justify_items: Option<AlignItems>,
394    /// How this node should be aligned in the inline axis
395    /// Falls back to the parents [`JustifyItems`] if not set
396    #[cfg(feature = "grid")]
397    pub justify_self: Option<AlignSelf>,
398    /// How should content contained within this item be aligned in the cross/block axis
399    #[cfg(any(feature = "flexbox", feature = "grid"))]
400    pub align_content: Option<AlignContent>,
401    /// How should content contained within this item be aligned in the main/inline axis
402    #[cfg(any(feature = "flexbox", feature = "grid"))]
403    pub justify_content: Option<JustifyContent>,
404    /// How large should the gaps between items in a grid or flex container be?
405    #[cfg(any(feature = "flexbox", feature = "grid"))]
406    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
407    pub gap: Size<LengthPercentage>,
408
409    // Block container properties
410    /// How items elements should aligned in the inline axis
411    #[cfg(feature = "block_layout")]
412    pub text_align: TextAlign,
413
414    // Flexbox container properties
415    /// Which direction does the main axis flow in?
416    #[cfg(feature = "flexbox")]
417    pub flex_direction: FlexDirection,
418    /// Should elements wrap, or stay in a single line?
419    #[cfg(feature = "flexbox")]
420    pub flex_wrap: FlexWrap,
421
422    // Flexbox item properties
423    /// Sets the initial main axis size of the item
424    #[cfg(feature = "flexbox")]
425    pub flex_basis: Dimension,
426    /// The relative rate at which this item grows when it is expanding to fill space
427    ///
428    /// 0.0 is the default value, and this value must be positive.
429    #[cfg(feature = "flexbox")]
430    pub flex_grow: f32,
431    /// The relative rate at which this item shrinks when it is contracting to fit into space
432    ///
433    /// 1.0 is the default value, and this value must be positive.
434    #[cfg(feature = "flexbox")]
435    pub flex_shrink: f32,
436
437    // Grid container properies
438    /// Defines the track sizing functions (heights) of the grid rows
439    #[cfg(feature = "grid")]
440    pub grid_template_rows: GridTrackVec<TrackSizingFunction>,
441    /// Defines the track sizing functions (widths) of the grid columns
442    #[cfg(feature = "grid")]
443    pub grid_template_columns: GridTrackVec<TrackSizingFunction>,
444    /// Defines the size of implicitly created rows
445    #[cfg(feature = "grid")]
446    pub grid_auto_rows: GridTrackVec<NonRepeatedTrackSizingFunction>,
447    /// Defined the size of implicitly created columns
448    #[cfg(feature = "grid")]
449    pub grid_auto_columns: GridTrackVec<NonRepeatedTrackSizingFunction>,
450    /// Controls how items get placed into the grid for auto-placed items
451    #[cfg(feature = "grid")]
452    pub grid_auto_flow: GridAutoFlow,
453
454    // Grid child properties
455    /// Defines which row in the grid the item should start and end at
456    #[cfg(feature = "grid")]
457    pub grid_row: Line<GridPlacement>,
458    /// Defines which column in the grid the item should start and end at
459    #[cfg(feature = "grid")]
460    pub grid_column: Line<GridPlacement>,
461}
462
463impl Style {
464    /// The [`Default`] layout, in a form that can be used in const functions
465    pub const DEFAULT: Style = Style {
466        display: Display::DEFAULT,
467        item_is_table: false,
468        box_sizing: BoxSizing::BorderBox,
469        overflow: Point { x: Overflow::Visible, y: Overflow::Visible },
470        scrollbar_width: 0.0,
471        position: Position::Relative,
472        inset: Rect::auto(),
473        margin: Rect::zero(),
474        padding: Rect::zero(),
475        border: Rect::zero(),
476        size: Size::auto(),
477        min_size: Size::auto(),
478        max_size: Size::auto(),
479        aspect_ratio: None,
480        #[cfg(any(feature = "flexbox", feature = "grid"))]
481        gap: Size::zero(),
482        // Alignment
483        #[cfg(any(feature = "flexbox", feature = "grid"))]
484        align_items: None,
485        #[cfg(any(feature = "flexbox", feature = "grid"))]
486        align_self: None,
487        #[cfg(feature = "grid")]
488        justify_items: None,
489        #[cfg(feature = "grid")]
490        justify_self: None,
491        #[cfg(any(feature = "flexbox", feature = "grid"))]
492        align_content: None,
493        #[cfg(any(feature = "flexbox", feature = "grid"))]
494        justify_content: None,
495        // Block
496        #[cfg(feature = "block_layout")]
497        text_align: TextAlign::Auto,
498        // Flexbox
499        #[cfg(feature = "flexbox")]
500        flex_direction: FlexDirection::Row,
501        #[cfg(feature = "flexbox")]
502        flex_wrap: FlexWrap::NoWrap,
503        #[cfg(feature = "flexbox")]
504        flex_grow: 0.0,
505        #[cfg(feature = "flexbox")]
506        flex_shrink: 1.0,
507        #[cfg(feature = "flexbox")]
508        flex_basis: Dimension::AUTO,
509        // Grid
510        #[cfg(feature = "grid")]
511        grid_template_rows: GridTrackVec::new(),
512        #[cfg(feature = "grid")]
513        grid_template_columns: GridTrackVec::new(),
514        #[cfg(feature = "grid")]
515        grid_auto_rows: GridTrackVec::new(),
516        #[cfg(feature = "grid")]
517        grid_auto_columns: GridTrackVec::new(),
518        #[cfg(feature = "grid")]
519        grid_auto_flow: GridAutoFlow::Row,
520        #[cfg(feature = "grid")]
521        grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
522        #[cfg(feature = "grid")]
523        grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
524    };
525}
526
527impl Default for Style {
528    fn default() -> Self {
529        Style::DEFAULT
530    }
531}
532
533impl CoreStyle for Style {
534    #[inline(always)]
535    fn box_generation_mode(&self) -> BoxGenerationMode {
536        match self.display {
537            Display::None => BoxGenerationMode::None,
538            _ => BoxGenerationMode::Normal,
539        }
540    }
541    #[inline(always)]
542    #[cfg(feature = "block_layout")]
543    fn is_block(&self) -> bool {
544        matches!(self.display, Display::Block)
545    }
546    #[inline(always)]
547    fn box_sizing(&self) -> BoxSizing {
548        self.box_sizing
549    }
550    #[inline(always)]
551    fn overflow(&self) -> Point<Overflow> {
552        self.overflow
553    }
554    #[inline(always)]
555    fn scrollbar_width(&self) -> f32 {
556        self.scrollbar_width
557    }
558    #[inline(always)]
559    fn position(&self) -> Position {
560        self.position
561    }
562    #[inline(always)]
563    fn inset(&self) -> Rect<LengthPercentageAuto> {
564        self.inset
565    }
566    #[inline(always)]
567    fn size(&self) -> Size<Dimension> {
568        self.size
569    }
570    #[inline(always)]
571    fn min_size(&self) -> Size<Dimension> {
572        self.min_size
573    }
574    #[inline(always)]
575    fn max_size(&self) -> Size<Dimension> {
576        self.max_size
577    }
578    #[inline(always)]
579    fn aspect_ratio(&self) -> Option<f32> {
580        self.aspect_ratio
581    }
582    #[inline(always)]
583    fn margin(&self) -> Rect<LengthPercentageAuto> {
584        self.margin
585    }
586    #[inline(always)]
587    fn padding(&self) -> Rect<LengthPercentage> {
588        self.padding
589    }
590    #[inline(always)]
591    fn border(&self) -> Rect<LengthPercentage> {
592        self.border
593    }
594}
595
596impl<T: CoreStyle> CoreStyle for &'_ T {
597    #[inline(always)]
598    fn box_generation_mode(&self) -> BoxGenerationMode {
599        (*self).box_generation_mode()
600    }
601    #[inline(always)]
602    fn is_block(&self) -> bool {
603        (*self).is_block()
604    }
605    #[inline(always)]
606    fn box_sizing(&self) -> BoxSizing {
607        (*self).box_sizing()
608    }
609    #[inline(always)]
610    fn overflow(&self) -> Point<Overflow> {
611        (*self).overflow()
612    }
613    #[inline(always)]
614    fn scrollbar_width(&self) -> f32 {
615        (*self).scrollbar_width()
616    }
617    #[inline(always)]
618    fn position(&self) -> Position {
619        (*self).position()
620    }
621    #[inline(always)]
622    fn inset(&self) -> Rect<LengthPercentageAuto> {
623        (*self).inset()
624    }
625    #[inline(always)]
626    fn size(&self) -> Size<Dimension> {
627        (*self).size()
628    }
629    #[inline(always)]
630    fn min_size(&self) -> Size<Dimension> {
631        (*self).min_size()
632    }
633    #[inline(always)]
634    fn max_size(&self) -> Size<Dimension> {
635        (*self).max_size()
636    }
637    #[inline(always)]
638    fn aspect_ratio(&self) -> Option<f32> {
639        (*self).aspect_ratio()
640    }
641    #[inline(always)]
642    fn margin(&self) -> Rect<LengthPercentageAuto> {
643        (*self).margin()
644    }
645    #[inline(always)]
646    fn padding(&self) -> Rect<LengthPercentage> {
647        (*self).padding()
648    }
649    #[inline(always)]
650    fn border(&self) -> Rect<LengthPercentage> {
651        (*self).border()
652    }
653}
654
655#[cfg(feature = "block_layout")]
656impl BlockContainerStyle for &Style {
657    #[inline(always)]
658    fn text_align(&self) -> TextAlign {
659        self.text_align
660    }
661}
662
663#[cfg(feature = "block_layout")]
664impl<T: BlockContainerStyle> BlockContainerStyle for &'_ T {
665    #[inline(always)]
666    fn text_align(&self) -> TextAlign {
667        (*self).text_align()
668    }
669}
670
671#[cfg(feature = "block_layout")]
672impl BlockItemStyle for Style {
673    #[inline(always)]
674    fn is_table(&self) -> bool {
675        self.item_is_table
676    }
677}
678
679#[cfg(feature = "block_layout")]
680impl<T: BlockItemStyle> BlockItemStyle for &'_ T {
681    #[inline(always)]
682    fn is_table(&self) -> bool {
683        (*self).is_table()
684    }
685}
686
687#[cfg(feature = "flexbox")]
688impl FlexboxContainerStyle for Style {
689    #[inline(always)]
690    fn flex_direction(&self) -> FlexDirection {
691        self.flex_direction
692    }
693    #[inline(always)]
694    fn flex_wrap(&self) -> FlexWrap {
695        self.flex_wrap
696    }
697    #[inline(always)]
698    fn gap(&self) -> Size<LengthPercentage> {
699        self.gap
700    }
701    #[inline(always)]
702    fn align_content(&self) -> Option<AlignContent> {
703        self.align_content
704    }
705    #[inline(always)]
706    fn align_items(&self) -> Option<AlignItems> {
707        self.align_items
708    }
709    #[inline(always)]
710    fn justify_content(&self) -> Option<JustifyContent> {
711        self.justify_content
712    }
713}
714
715#[cfg(feature = "flexbox")]
716impl<T: FlexboxContainerStyle> FlexboxContainerStyle for &'_ T {
717    #[inline(always)]
718    fn flex_direction(&self) -> FlexDirection {
719        (*self).flex_direction()
720    }
721    #[inline(always)]
722    fn flex_wrap(&self) -> FlexWrap {
723        (*self).flex_wrap()
724    }
725    #[inline(always)]
726    fn gap(&self) -> Size<LengthPercentage> {
727        (*self).gap()
728    }
729    #[inline(always)]
730    fn align_content(&self) -> Option<AlignContent> {
731        (*self).align_content()
732    }
733    #[inline(always)]
734    fn align_items(&self) -> Option<AlignItems> {
735        (*self).align_items()
736    }
737    #[inline(always)]
738    fn justify_content(&self) -> Option<JustifyContent> {
739        (*self).justify_content()
740    }
741}
742
743#[cfg(feature = "flexbox")]
744impl FlexboxItemStyle for Style {
745    #[inline(always)]
746    fn flex_basis(&self) -> Dimension {
747        self.flex_basis
748    }
749    #[inline(always)]
750    fn flex_grow(&self) -> f32 {
751        self.flex_grow
752    }
753    #[inline(always)]
754    fn flex_shrink(&self) -> f32 {
755        self.flex_shrink
756    }
757    #[inline(always)]
758    fn align_self(&self) -> Option<AlignSelf> {
759        self.align_self
760    }
761}
762
763#[cfg(feature = "flexbox")]
764impl<T: FlexboxItemStyle> FlexboxItemStyle for &'_ T {
765    #[inline(always)]
766    fn flex_basis(&self) -> Dimension {
767        (*self).flex_basis()
768    }
769    #[inline(always)]
770    fn flex_grow(&self) -> f32 {
771        (*self).flex_grow()
772    }
773    #[inline(always)]
774    fn flex_shrink(&self) -> f32 {
775        (*self).flex_shrink()
776    }
777    #[inline(always)]
778    fn align_self(&self) -> Option<AlignSelf> {
779        (*self).align_self()
780    }
781}
782
783#[cfg(feature = "grid")]
784impl GridContainerStyle for Style {
785    type TemplateTrackList<'a>
786        = &'a [TrackSizingFunction]
787    where
788        Self: 'a;
789    type AutoTrackList<'a>
790        = &'a [NonRepeatedTrackSizingFunction]
791    where
792        Self: 'a;
793
794    #[inline(always)]
795    fn grid_template_rows(&self) -> &[TrackSizingFunction] {
796        &self.grid_template_rows
797    }
798    #[inline(always)]
799    fn grid_template_columns(&self) -> &[TrackSizingFunction] {
800        &self.grid_template_columns
801    }
802    #[inline(always)]
803    fn grid_auto_rows(&self) -> &[NonRepeatedTrackSizingFunction] {
804        &self.grid_auto_rows
805    }
806    #[inline(always)]
807    fn grid_auto_columns(&self) -> &[NonRepeatedTrackSizingFunction] {
808        &self.grid_auto_columns
809    }
810    #[inline(always)]
811    fn grid_auto_flow(&self) -> GridAutoFlow {
812        self.grid_auto_flow
813    }
814    #[inline(always)]
815    fn gap(&self) -> Size<LengthPercentage> {
816        self.gap
817    }
818    #[inline(always)]
819    fn align_content(&self) -> Option<AlignContent> {
820        self.align_content
821    }
822    #[inline(always)]
823    fn justify_content(&self) -> Option<JustifyContent> {
824        self.justify_content
825    }
826    #[inline(always)]
827    fn align_items(&self) -> Option<AlignItems> {
828        self.align_items
829    }
830    #[inline(always)]
831    fn justify_items(&self) -> Option<AlignItems> {
832        self.justify_items
833    }
834}
835
836#[cfg(feature = "grid")]
837impl<T: GridContainerStyle> GridContainerStyle for &'_ T {
838    type TemplateTrackList<'a>
839        = T::TemplateTrackList<'a>
840    where
841        Self: 'a;
842    type AutoTrackList<'a>
843        = T::AutoTrackList<'a>
844    where
845        Self: 'a;
846
847    #[inline(always)]
848    fn grid_template_rows(&self) -> Self::TemplateTrackList<'_> {
849        (*self).grid_template_rows()
850    }
851    #[inline(always)]
852    fn grid_template_columns(&self) -> Self::TemplateTrackList<'_> {
853        (*self).grid_template_columns()
854    }
855    #[inline(always)]
856    fn grid_auto_rows(&self) -> Self::AutoTrackList<'_> {
857        (*self).grid_auto_rows()
858    }
859    #[inline(always)]
860    fn grid_auto_columns(&self) -> Self::AutoTrackList<'_> {
861        (*self).grid_auto_columns()
862    }
863    #[inline(always)]
864    fn grid_auto_flow(&self) -> GridAutoFlow {
865        (*self).grid_auto_flow()
866    }
867    #[inline(always)]
868    fn gap(&self) -> Size<LengthPercentage> {
869        (*self).gap()
870    }
871    #[inline(always)]
872    fn align_content(&self) -> Option<AlignContent> {
873        (*self).align_content()
874    }
875    #[inline(always)]
876    fn justify_content(&self) -> Option<JustifyContent> {
877        (*self).justify_content()
878    }
879    #[inline(always)]
880    fn align_items(&self) -> Option<AlignItems> {
881        (*self).align_items()
882    }
883    #[inline(always)]
884    fn justify_items(&self) -> Option<AlignItems> {
885        (*self).justify_items()
886    }
887}
888
889#[cfg(feature = "grid")]
890impl GridItemStyle for &'_ Style {
891    #[inline(always)]
892    fn grid_row(&self) -> Line<GridPlacement> {
893        self.grid_row
894    }
895    #[inline(always)]
896    fn grid_column(&self) -> Line<GridPlacement> {
897        self.grid_column
898    }
899    #[inline(always)]
900    fn align_self(&self) -> Option<AlignSelf> {
901        self.align_self
902    }
903    #[inline(always)]
904    fn justify_self(&self) -> Option<AlignSelf> {
905        self.justify_self
906    }
907}
908
909#[cfg(feature = "grid")]
910impl<T: GridItemStyle> GridItemStyle for &'_ T {
911    #[inline(always)]
912    fn grid_row(&self) -> Line<GridPlacement> {
913        (*self).grid_row()
914    }
915    #[inline(always)]
916    fn grid_column(&self) -> Line<GridPlacement> {
917        (*self).grid_column()
918    }
919    #[inline(always)]
920    fn align_self(&self) -> Option<AlignSelf> {
921        (*self).align_self()
922    }
923    #[inline(always)]
924    fn justify_self(&self) -> Option<AlignSelf> {
925        (*self).justify_self()
926    }
927}
928
929#[cfg(test)]
930mod tests {
931    use super::Style;
932    use crate::{geometry::*, style_helpers::TaffyAuto as _};
933
934    #[test]
935    fn defaults_match() {
936        #[cfg(feature = "grid")]
937        use super::GridPlacement;
938
939        let old_defaults = Style {
940            display: Default::default(),
941            item_is_table: false,
942            box_sizing: Default::default(),
943            overflow: Default::default(),
944            scrollbar_width: 0.0,
945            position: Default::default(),
946            #[cfg(feature = "flexbox")]
947            flex_direction: Default::default(),
948            #[cfg(feature = "flexbox")]
949            flex_wrap: Default::default(),
950            #[cfg(any(feature = "flexbox", feature = "grid"))]
951            align_items: Default::default(),
952            #[cfg(any(feature = "flexbox", feature = "grid"))]
953            align_self: Default::default(),
954            #[cfg(feature = "grid")]
955            justify_items: Default::default(),
956            #[cfg(feature = "grid")]
957            justify_self: Default::default(),
958            #[cfg(any(feature = "flexbox", feature = "grid"))]
959            align_content: Default::default(),
960            #[cfg(any(feature = "flexbox", feature = "grid"))]
961            justify_content: Default::default(),
962            inset: Rect::auto(),
963            margin: Rect::zero(),
964            padding: Rect::zero(),
965            border: Rect::zero(),
966            gap: Size::zero(),
967            #[cfg(feature = "block_layout")]
968            text_align: Default::default(),
969            #[cfg(feature = "flexbox")]
970            flex_grow: 0.0,
971            #[cfg(feature = "flexbox")]
972            flex_shrink: 1.0,
973            #[cfg(feature = "flexbox")]
974            flex_basis: super::Dimension::AUTO,
975            size: Size::auto(),
976            min_size: Size::auto(),
977            max_size: Size::auto(),
978            aspect_ratio: Default::default(),
979            #[cfg(feature = "grid")]
980            grid_template_rows: Default::default(),
981            #[cfg(feature = "grid")]
982            grid_template_columns: Default::default(),
983            #[cfg(feature = "grid")]
984            grid_auto_rows: Default::default(),
985            #[cfg(feature = "grid")]
986            grid_auto_columns: Default::default(),
987            #[cfg(feature = "grid")]
988            grid_auto_flow: Default::default(),
989            #[cfg(feature = "grid")]
990            grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
991            #[cfg(feature = "grid")]
992            grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
993        };
994
995        assert_eq!(Style::DEFAULT, Style::default());
996        assert_eq!(Style::DEFAULT, old_defaults);
997    }
998
999    // NOTE: Please feel free the update the sizes in this test as required. This test is here to prevent unintentional size changes
1000    // and to serve as accurate up-to-date documentation on the sizes.
1001    #[test]
1002    fn style_sizes() {
1003        use super::*;
1004
1005        fn assert_type_size<T>(expected_size: usize) {
1006            let name = ::core::any::type_name::<T>();
1007            let name = name.replace("taffy::geometry::", "");
1008            let name = name.replace("taffy::style::dimension::", "");
1009            let name = name.replace("taffy::style::alignment::", "");
1010            let name = name.replace("taffy::style::flex::", "");
1011            let name = name.replace("taffy::style::grid::", "");
1012
1013            assert_eq!(
1014                ::core::mem::size_of::<T>(),
1015                expected_size,
1016                "Expected {} for be {} byte(s) but it was {} byte(s)",
1017                name,
1018                expected_size,
1019                ::core::mem::size_of::<T>(),
1020            );
1021        }
1022
1023        // Display and Position
1024        assert_type_size::<Display>(1);
1025        assert_type_size::<BoxSizing>(1);
1026        assert_type_size::<Position>(1);
1027        assert_type_size::<Overflow>(1);
1028
1029        // Dimensions and aggregations of Dimensions
1030        assert_type_size::<f32>(4);
1031        assert_type_size::<LengthPercentage>(8);
1032        assert_type_size::<LengthPercentageAuto>(8);
1033        assert_type_size::<Dimension>(8);
1034        assert_type_size::<Size<LengthPercentage>>(16);
1035        assert_type_size::<Size<LengthPercentageAuto>>(16);
1036        assert_type_size::<Size<Dimension>>(16);
1037        assert_type_size::<Rect<LengthPercentage>>(32);
1038        assert_type_size::<Rect<LengthPercentageAuto>>(32);
1039        assert_type_size::<Rect<Dimension>>(32);
1040
1041        // Alignment
1042        assert_type_size::<AlignContent>(1);
1043        assert_type_size::<AlignItems>(1);
1044        assert_type_size::<Option<AlignItems>>(1);
1045
1046        // Flexbox Container
1047        assert_type_size::<FlexDirection>(1);
1048        assert_type_size::<FlexWrap>(1);
1049
1050        // CSS Grid Container
1051        assert_type_size::<GridAutoFlow>(1);
1052        assert_type_size::<MinTrackSizingFunction>(8);
1053        assert_type_size::<MaxTrackSizingFunction>(8);
1054        assert_type_size::<NonRepeatedTrackSizingFunction>(16);
1055        assert_type_size::<TrackSizingFunction>(32);
1056        assert_type_size::<Vec<NonRepeatedTrackSizingFunction>>(24);
1057        assert_type_size::<Vec<TrackSizingFunction>>(24);
1058
1059        // CSS Grid Item
1060        assert_type_size::<GridPlacement>(4);
1061        assert_type_size::<Line<GridPlacement>>(8);
1062
1063        // Overall
1064        assert_type_size::<Style>(352);
1065    }
1066}