tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 231Rust 9TOML 3CSS 1345 Definitions

⎇ 527e99e059c327b6c6be5a24c210dcba3e658fdf src/style/mod.rs Rust · 1064 lines · 35.8 KB History Who touched what raw

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