tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 1082HTML 1014Markdown 12TOML 83222 Definitions

⎇ units src/style/mod.rs Rust · 1373 lines · 46.4 KB History Who touched what raw

Fix serde feature with Units trait dff2beccf · 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 = "float_layout")]
12mod float;
13#[cfg(feature = "grid")]
14mod grid;
15
16pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf};
17pub use self::available_space::AvailableSpace;
18pub use self::compact_length::CompactLength;
19pub use self::dimension::{Dimension, LengthPercentage, LengthPercentageAuto};
20
21#[cfg(feature = "block_layout")]
22pub use self::block::{BlockContainerStyle, BlockItemStyle, TextAlign};
23#[cfg(feature = "flexbox")]
24pub use self::flex::{FlexDirection, FlexWrap, FlexboxContainerStyle, FlexboxItemStyle};
25#[cfg(feature = "float_layout")]
26pub use self::float::{Clear, Float, FloatDirection};
27#[cfg(feature = "grid")]
28pub use self::grid::{
29    GenericGridPlacement, GenericGridTemplateComponent, GenericRepetition, GridAutoFlow, GridAutoTracks,
30    GridContainerStyle, GridItemStyle, GridPlacement, GridTemplateComponent, GridTemplateRepetition,
31    GridTemplateTracks, MaxTrackSizingFunction, MinTrackSizingFunction, RepetitionCount, TrackSizingFunction,
32};
33#[cfg(feature = "grid")]
34pub(crate) use self::grid::{GridAreaAxis, GridAreaEnd};
35#[cfg(feature = "grid")]
36pub use self::grid::{GridTemplateArea, NamedGridLine, TemplateLineNames};
37#[cfg(feature = "grid")]
38pub(crate) use self::grid::{NonNamedGridPlacement, OriginZeroGridPlacement};
39
40use crate::geometry::{Point, Rect, Size};
41use crate::style_helpers::TaffyAuto as _;
42use core::fmt::Debug;
43
44#[cfg(feature = "grid")]
45use crate::geometry::Line;
46#[cfg(feature = "serde")]
47use crate::style_helpers;
48#[cfg(feature = "grid")]
49use crate::util::sys::GridTrackVec;
50
51use crate::sys::String;
52
53/// Trait that represents a cheaply clonable string. If you're unsure what to use here
54/// consider `Arc<str>` or `string_cache::Atom`.
55#[cfg(any(feature = "alloc", feature = "std"))]
56pub trait CheapCloneStr:
57    AsRef<str> + for<'a> From<&'a str> + From<String> + PartialEq + Eq + Clone + Default + Debug + 'static
58{
59}
60#[cfg(any(feature = "alloc", feature = "std"))]
61impl<T> CheapCloneStr for T where
62    T: AsRef<str> + for<'a> From<&'a str> + From<String> + PartialEq + Eq + Clone + Default + Debug + 'static
63{
64}
65
66/// Trait that represent a `calc()` expression
67pub trait Calc: Clone + Debug + 'static {}
68impl<T> Calc for T where T: Clone + Debug + 'static {}
69
70/// Allows Taffy to abstract of the types it uses to represent strings and calc expressions.
71/// In future it may be extended to abstract the scalar number type (currently f32)
72pub trait Units {
73    /// Trait that represents a cheaply clonable string. If you're unsure what to use here
74    /// consider `Arc<str>` or `string_cache::Atom`.
75    #[cfg(not(feature = "serde"))]
76    type Str: CheapCloneStr;
77    /// Trait that represents a cheaply clonable string. If you're unsure what to use here
78    /// consider `Arc<str>` or `string_cache::Atom`.
79    #[cfg(feature = "serde")]
80    type Str: CheapCloneStr + serde::Serialize + for<'a> serde::Deserialize<'a>;
81
82    /// Type representing a calc expression.
83    /// If you're not using Calc then you can just use `()`
84    type Calc: Calc;
85}
86
87/// A default implementation of the [`Units`] trait
88#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
89pub struct DefaultUnits;
90
91impl Units for DefaultUnits {
92    type Str = String;
93    type Calc = ();
94}
95
96/// Trait that represents a cheaply clonable string. If you're unsure what to use here
97/// consider `Arc<str>` or `string_cache::Atom`.
98#[cfg(not(any(feature = "alloc", feature = "std")))]
99pub trait CheapCloneStr {}
100#[cfg(not(any(feature = "alloc", feature = "std")))]
101impl<T> CheapCloneStr for T {}
102
103/// The core set of styles that are shared between all CSS layout nodes
104///
105/// Note that all methods come with a default implementation which simply returns the default value for that style property
106/// but this is a just a convenience to save on boilerplate for styles that your implementation doesn't support. You will need
107/// to override the default implementation for each style property that your style type actually supports.
108pub trait CoreStyle {
109    /// The type of custom identifiers used to identify named grid lines and areas
110    type Units: Units;
111
112    /// Which box generation mode should be used
113    #[inline(always)]
114    fn box_generation_mode(&self) -> BoxGenerationMode {
115        BoxGenerationMode::DEFAULT
116    }
117    /// Is block layout?
118    #[inline(always)]
119    fn is_block(&self) -> bool {
120        false
121    }
122    /// Is it a compressible replaced element?
123    /// <https://drafts.csswg.org/css-sizing-3/#min-content-zero>
124    #[inline(always)]
125    fn is_compressible_replaced(&self) -> bool {
126        false
127    }
128    /// Which box do size styles apply to
129    #[inline(always)]
130    fn box_sizing(&self) -> BoxSizing {
131        BoxSizing::BorderBox
132    }
133
134    /// The direction of text, table and grid columns, and horizontal overflow.
135    #[inline(always)]
136    fn direction(&self) -> Direction {
137        Direction::Ltr
138    }
139
140    // Overflow properties
141    /// How children overflowing their container should affect layout
142    #[inline(always)]
143    fn overflow(&self) -> Point<Overflow> {
144        Style::<Self::Units>::DEFAULT.overflow
145    }
146    /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
147    #[inline(always)]
148    fn scrollbar_width(&self) -> f32 {
149        0.0
150    }
151
152    // Position properties
153    /// What should the `position` value of this struct use as a base offset?
154    #[inline(always)]
155    fn position(&self) -> Position {
156        Style::<Self::Units>::DEFAULT.position
157    }
158    /// How should the position of this element be tweaked relative to the layout defined?
159    #[inline(always)]
160    fn inset(&self) -> Rect<LengthPercentageAuto> {
161        Style::<Self::Units>::DEFAULT.inset
162    }
163
164    // Size properies
165    /// Sets the initial size of the item
166    #[inline(always)]
167    fn size(&self) -> Size<Dimension> {
168        Style::<Self::Units>::DEFAULT.size
169    }
170    /// Controls the minimum size of the item
171    #[inline(always)]
172    fn min_size(&self) -> Size<Dimension> {
173        Style::<Self::Units>::DEFAULT.min_size
174    }
175    /// Controls the maximum size of the item
176    #[inline(always)]
177    fn max_size(&self) -> Size<Dimension> {
178        Style::<Self::Units>::DEFAULT.max_size
179    }
180    /// Sets the preferred aspect ratio for the item
181    /// The ratio is calculated as width divided by height.
182    #[inline(always)]
183    fn aspect_ratio(&self) -> Option<f32> {
184        Style::<Self::Units>::DEFAULT.aspect_ratio
185    }
186
187    // Spacing Properties
188    /// How large should the margin be on each side?
189    #[inline(always)]
190    fn margin(&self) -> Rect<LengthPercentageAuto> {
191        Style::<Self::Units>::DEFAULT.margin
192    }
193    /// How large should the padding be on each side?
194    #[inline(always)]
195    fn padding(&self) -> Rect<LengthPercentage> {
196        Style::<Self::Units>::DEFAULT.padding
197    }
198    /// How large should the border be on each side?
199    #[inline(always)]
200    fn border(&self) -> Rect<LengthPercentage> {
201        Style::<Self::Units>::DEFAULT.border
202    }
203}
204
205/// Sets the layout used for the children of this node
206///
207/// The default values depends on on which feature flags are enabled. The order of precedence is: Flex, Grid, Block, None.
208#[derive(Copy, Clone, PartialEq, Eq, Debug)]
209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
210pub enum Display {
211    /// The children will follow the block layout algorithm
212    #[cfg(feature = "block_layout")]
213    Block,
214    /// The children will follow the flexbox layout algorithm
215    #[cfg(feature = "flexbox")]
216    Flex,
217    /// The children will follow the CSS Grid layout algorithm
218    #[cfg(feature = "grid")]
219    Grid,
220    /// The node is hidden, and it's children will also be hidden
221    None,
222}
223
224impl Display {
225    /// The default Display mode
226    #[cfg(feature = "flexbox")]
227    pub const DEFAULT: Display = Display::Flex;
228
229    /// The default Display mode
230    #[cfg(all(feature = "grid", not(feature = "flexbox")))]
231    pub const DEFAULT: Display = Display::Grid;
232
233    /// The default Display mode
234    #[cfg(all(feature = "block_layout", not(feature = "flexbox"), not(feature = "grid")))]
235    pub const DEFAULT: Display = Display::Block;
236
237    /// The default Display mode
238    #[cfg(all(not(feature = "flexbox"), not(feature = "grid"), not(feature = "block_layout")))]
239    pub const DEFAULT: Display = Display::None;
240}
241
242impl Default for Display {
243    fn default() -> Self {
244        Self::DEFAULT
245    }
246}
247
248#[cfg(feature = "parse")]
249crate::util::parse::impl_parse_for_keyword_enum!(Display,
250    "none" => None,
251    #[cfg(feature = "flexbox")]
252    "flex" => Flex,
253    #[cfg(feature = "grid")]
254    "grid" => Grid,
255    #[cfg(feature = "block_layout")]
256    "block" => Block,
257);
258
259impl core::fmt::Display for Display {
260    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
261        match self {
262            Display::None => write!(f, "NONE"),
263            #[cfg(feature = "block_layout")]
264            Display::Block => write!(f, "BLOCK"),
265            #[cfg(feature = "flexbox")]
266            Display::Flex => write!(f, "FLEX"),
267            #[cfg(feature = "grid")]
268            Display::Grid => write!(f, "GRID"),
269        }
270    }
271}
272
273/// An abstracted version of the CSS `display` property where any value other than "none" is represented by "normal"
274/// See: <https://www.w3.org/TR/css-display-3/#box-generation>
275#[derive(Copy, Clone, PartialEq, Eq, Debug)]
276#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
277pub enum BoxGenerationMode {
278    /// The node generates a box in the regular way
279    Normal,
280    /// The node and it's descendants generate no boxes (they are hidden)
281    None,
282}
283
284impl BoxGenerationMode {
285    /// The default of BoxGenerationMode
286    pub const DEFAULT: BoxGenerationMode = BoxGenerationMode::Normal;
287}
288
289impl Default for BoxGenerationMode {
290    fn default() -> Self {
291        Self::DEFAULT
292    }
293}
294
295/// The positioning strategy for this item.
296///
297/// This controls both how the origin is determined for the [`Style::position`] field,
298/// and whether or not the item will be controlled by flexbox's layout algorithm.
299///
300/// WARNING: this enum follows the behavior of [CSS's `position` property](https://developer.mozilla.org/en-US/docs/Web/CSS/position),
301/// which can be unintuitive.
302///
303/// [`Position::Relative`] is the default value, in contrast to the default behavior in CSS.
304#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
305#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
306pub enum Position {
307    /// The offset is computed relative to the final position given by the layout algorithm.
308    /// Offsets do not affect the position of any other items; they are effectively a correction factor applied at the end.
309    #[default]
310    Relative,
311    /// The offset is computed relative to this item's closest positioned ancestor, if any.
312    /// Otherwise, it is placed relative to the origin.
313    /// No space is created for the item in the page layout, and its size will not be altered.
314    ///
315    /// WARNING: to opt-out of layouting entirely, you must use [`Display::None`] instead on your [`Style`] object.
316    Absolute,
317}
318
319#[cfg(feature = "parse")]
320crate::util::parse::impl_parse_for_keyword_enum!(Position,
321    "relative" => Relative,
322    "absolute" => Absolute,
323);
324
325/// Specifies whether size styles for this node are assigned to the node's "content box" or "border box"
326///
327/// - The "content box" is the node's inner size excluding padding, border and margin
328/// - The "border box" is the node's outer size including padding and border (but still excluding margin)
329///
330/// This property modifies the application of the following styles:
331///
332///   - `size`
333///   - `min_size`
334///   - `max_size`
335///   - `flex_basis`
336///
337/// See <https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing>
338#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
339#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
340pub enum BoxSizing {
341    /// Size styles such size, min_size, max_size specify the box's "border box" (the size excluding margin but including padding/border)
342    #[default]
343    BorderBox,
344    /// Size styles such size, min_size, max_size specify the box's "content box" (the size excluding padding/border/margin)
345    ContentBox,
346}
347
348#[cfg(feature = "parse")]
349crate::util::parse::impl_parse_for_keyword_enum!(BoxSizing,
350    "border-box" => BorderBox,
351    "content-box" => ContentBox,
352);
353
354/// How children overflowing their container should affect layout
355///
356/// In CSS the primary effect of this property is to control whether contents of a parent container that overflow that container should
357/// be displayed anyway, be clipped, or trigger the container to become a scroll container. However it also has secondary effects on layout,
358/// the main ones being:
359///
360///   - The automatic minimum size Flexbox/CSS Grid items with non-`Visible` overflow is `0` rather than being content based
361///   - `Overflow::Scroll` nodes have space in the layout reserved for a scrollbar (width controlled by the `scrollbar_width` property)
362///
363/// In Taffy, we only implement the layout related secondary effects as we are not concerned with drawing/painting. The amount of space reserved for
364/// a scrollbar is controlled by the `scrollbar_width` property. If this is `0` then `Scroll` behaves identically to `Hidden`.
365///
366/// <https://developer.mozilla.org/en-US/docs/Web/CSS/overflow>
367#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
368#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
369pub enum Overflow {
370    /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
371    /// Content that overflows this node *should* contribute to the scroll region of its parent.
372    #[default]
373    Visible,
374    /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
375    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
376    Clip,
377    /// The automatic minimum size of this node as a flexbox/grid item should be `0`.
378    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
379    Hidden,
380    /// The automatic minimum size of this node as a flexbox/grid item should be `0`. Additionally, space should be reserved
381    /// for a scrollbar. The amount of space reserved is controlled by the `scrollbar_width` property.
382    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
383    Scroll,
384}
385
386impl Overflow {
387    /// Returns true for overflow modes that contain their contents (`Overflow::Hidden`, `Overflow::Scroll`, `Overflow::Auto`)
388    /// or else false for overflow modes that allow their contains to spill (`Overflow::Visible`).
389    #[inline(always)]
390    pub fn is_scroll_container(self) -> bool {
391        match self {
392            Self::Visible | Self::Clip => false,
393            Self::Hidden | Self::Scroll => true,
394        }
395    }
396
397    /// Returns `Some(0.0)` if the overflow mode would cause the automatic minimum size of a Flexbox or CSS Grid item
398    /// to be `0`. Else returns None.
399    #[inline(always)]
400    pub(crate) fn maybe_into_automatic_min_size(self) -> Option<f32> {
401        match self.is_scroll_container() {
402            true => Some(0.0),
403            false => None,
404        }
405    }
406}
407
408#[cfg(feature = "parse")]
409crate::util::parse::impl_parse_for_keyword_enum!(Overflow,
410    "visible" => Visible,
411    "hidden" => Hidden,
412    "clip" => Clip,
413    "scroll" => Scroll,
414);
415
416/// Sets the direction of text, table and grid columns, and horizontal overflow.
417/// <https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/direction>
418#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
419#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
420pub enum Direction {
421    #[default]
422    /// Left-to-right
423    Ltr,
424    /// Right-to-left
425    Rtl,
426}
427
428impl Direction {
429    /// Returns true if the direction is right-to-left
430    #[inline]
431    pub(crate) fn is_rtl(&self) -> bool {
432        matches!(self, Direction::Rtl)
433    }
434}
435
436#[cfg(feature = "parse")]
437crate::util::parse::impl_parse_for_keyword_enum!(Direction,
438    "ltr" => Ltr,
439    "rtl" => Rtl,
440);
441
442/// A typed representation of the CSS style information for a single node.
443///
444/// The most important idea in flexbox is the notion of a "main" and "cross" axis, which are always perpendicular to each other.
445/// The orientation of these axes are controlled via the [`FlexDirection`] field of this struct.
446///
447/// This struct follows the [CSS equivalent](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox) directly;
448/// information about the behavior on the web should transfer directly.
449///
450/// Detailed information about the exact behavior of each of these fields
451/// can be found on [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS) by searching for the field name.
452/// The distinction between margin, padding and border is explained well in
453/// this [introduction to the box model](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model).
454///
455/// If the behavior does not match the flexbox layout algorithm on the web, please file a bug!
456#[derive(Clone, PartialEq, Debug)]
457#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
458#[cfg_attr(feature = "serde", serde(default))]
459pub struct Style<U: Units = DefaultUnits> {
460    /// This is a dummy field which is necessary to make Taffy compile with the `grid` feature disabled
461    /// It should always be set to `core::marker::PhantomData`.
462    pub dummy: core::marker::PhantomData<U>,
463    /// What layout strategy should be used?
464    pub display: Display,
465    /// Whether a child is display:table or not. This affects children of block layouts.
466    /// This should really be part of `Display`, but it is currently seperate because table layout isn't implemented
467    pub item_is_table: bool,
468    /// Is it a replaced element like an image or form field?
469    /// <https://drafts.csswg.org/css-sizing-3/#min-content-zero>
470    pub item_is_replaced: bool,
471    /// Should size styles apply to the content box or the border box of the node
472    pub box_sizing: BoxSizing,
473    /// Sets the direction of text, table and grid columns, and horizontal overflow.
474    pub direction: Direction,
475
476    // Overflow properties
477    /// How children overflowing their container should affect layout
478    pub overflow: Point<Overflow>,
479    /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
480    pub scrollbar_width: f32,
481
482    #[cfg(feature = "float_layout")]
483    /// Should the box be floated
484    pub float: Float,
485    #[cfg(feature = "float_layout")]
486    /// Should the box clear floats
487    pub clear: Clear,
488
489    // Position properties
490    /// What should the `position` value of this struct use as a base offset?
491    pub position: Position,
492    /// How should the position of this element be tweaked relative to the layout defined?
493    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
494    pub inset: Rect<LengthPercentageAuto>,
495
496    // Size properties
497    /// Sets the initial size of the item
498    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
499    pub size: Size<Dimension>,
500    /// Controls the minimum size of the item
501    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
502    pub min_size: Size<Dimension>,
503    /// Controls the maximum size of the item
504    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
505    pub max_size: Size<Dimension>,
506    /// Sets the preferred aspect ratio for the item
507    ///
508    /// The ratio is calculated as width divided by height.
509    pub aspect_ratio: Option<f32>,
510
511    // Spacing Properties
512    /// How large should the margin be on each side?
513    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
514    pub margin: Rect<LengthPercentageAuto>,
515    /// How large should the padding be on each side?
516    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
517    pub padding: Rect<LengthPercentage>,
518    /// How large should the border be on each side?
519    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
520    pub border: Rect<LengthPercentage>,
521
522    // Alignment properties
523    /// How this node's children aligned in the cross/block axis?
524    #[cfg(any(feature = "flexbox", feature = "grid"))]
525    pub align_items: Option<AlignItems>,
526    /// How this node should be aligned in the cross/block axis
527    /// Falls back to the parents [`AlignItems`] if not set
528    #[cfg(any(feature = "flexbox", feature = "grid"))]
529    pub align_self: Option<AlignSelf>,
530    /// How this node's children should be aligned in the inline axis
531    #[cfg(feature = "grid")]
532    pub justify_items: Option<AlignItems>,
533    /// How this node should be aligned in the inline axis
534    /// Falls back to the parents [`JustifyItems`] if not set
535    #[cfg(feature = "grid")]
536    pub justify_self: Option<AlignSelf>,
537    /// How should content contained within this item be aligned in the cross/block axis
538    #[cfg(any(feature = "flexbox", feature = "grid"))]
539    pub align_content: Option<AlignContent>,
540    /// How should content contained within this item be aligned in the main/inline axis
541    #[cfg(any(feature = "flexbox", feature = "grid"))]
542    pub justify_content: Option<JustifyContent>,
543    /// How large should the gaps between items in a grid or flex container be?
544    #[cfg(any(feature = "flexbox", feature = "grid"))]
545    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
546    pub gap: Size<LengthPercentage>,
547
548    // Block container properties
549    /// How items elements should aligned in the inline axis
550    #[cfg(feature = "block_layout")]
551    pub text_align: TextAlign,
552
553    // Flexbox container properties
554    /// Which direction does the main axis flow in?
555    #[cfg(feature = "flexbox")]
556    pub flex_direction: FlexDirection,
557    /// Should elements wrap, or stay in a single line?
558    #[cfg(feature = "flexbox")]
559    pub flex_wrap: FlexWrap,
560
561    // Flexbox item properties
562    /// Sets the initial main axis size of the item
563    #[cfg(feature = "flexbox")]
564    pub flex_basis: Dimension,
565    /// The relative rate at which this item grows when it is expanding to fill space
566    ///
567    /// 0.0 is the default value, and this value must be positive.
568    #[cfg(feature = "flexbox")]
569    pub flex_grow: f32,
570    /// The relative rate at which this item shrinks when it is contracting to fit into space
571    ///
572    /// 1.0 is the default value, and this value must be positive.
573    #[cfg(feature = "flexbox")]
574    pub flex_shrink: f32,
575
576    // Grid container properies
577    /// Defines the track sizing functions (heights) of the grid rows
578    #[cfg(feature = "grid")]
579    pub grid_template_rows: GridTrackVec<GridTemplateComponent<U::Str>>,
580    /// Defines the track sizing functions (widths) of the grid columns
581    #[cfg(feature = "grid")]
582    pub grid_template_columns: GridTrackVec<GridTemplateComponent<U::Str>>,
583    /// Defines the size of implicitly created rows
584    #[cfg(feature = "grid")]
585    pub grid_auto_rows: GridTrackVec<TrackSizingFunction>,
586    /// Defined the size of implicitly created columns
587    #[cfg(feature = "grid")]
588    pub grid_auto_columns: GridTrackVec<TrackSizingFunction>,
589    /// Controls how items get placed into the grid for auto-placed items
590    #[cfg(feature = "grid")]
591    pub grid_auto_flow: GridAutoFlow,
592
593    // Grid container named properties
594    /// Defines the rectangular grid areas
595    #[cfg(feature = "grid")]
596    pub grid_template_areas: GridTrackVec<GridTemplateArea<U::Str>>,
597    /// The named lines between the columns
598    #[cfg(feature = "grid")]
599    pub grid_template_column_names: GridTrackVec<GridTrackVec<U::Str>>,
600    /// The named lines between the rows
601    #[cfg(feature = "grid")]
602    pub grid_template_row_names: GridTrackVec<GridTrackVec<U::Str>>,
603
604    // Grid child properties
605    /// Defines which row in the grid the item should start and end at
606    #[cfg(feature = "grid")]
607    pub grid_row: Line<GridPlacement<U::Str>>,
608    /// Defines which column in the grid the item should start and end at
609    #[cfg(feature = "grid")]
610    pub grid_column: Line<GridPlacement<U::Str>>,
611}
612
613impl<U: Units> Style<U> {
614    /// The [`Default`] layout, in a form that can be used in const functions
615    pub const DEFAULT: Style<U> = Style {
616        dummy: core::marker::PhantomData,
617        display: Display::DEFAULT,
618        item_is_table: false,
619        item_is_replaced: false,
620        box_sizing: BoxSizing::BorderBox,
621        direction: Direction::Ltr,
622        overflow: Point { x: Overflow::Visible, y: Overflow::Visible },
623        scrollbar_width: 0.0,
624        #[cfg(feature = "float_layout")]
625        float: Float::None,
626        #[cfg(feature = "float_layout")]
627        clear: Clear::None,
628        position: Position::Relative,
629        inset: Rect::auto(),
630        margin: Rect::zero(),
631        padding: Rect::zero(),
632        border: Rect::zero(),
633        size: Size::auto(),
634        min_size: Size::auto(),
635        max_size: Size::auto(),
636        aspect_ratio: None,
637        #[cfg(any(feature = "flexbox", feature = "grid"))]
638        gap: Size::zero(),
639        // Alignment
640        #[cfg(any(feature = "flexbox", feature = "grid"))]
641        align_items: None,
642        #[cfg(any(feature = "flexbox", feature = "grid"))]
643        align_self: None,
644        #[cfg(feature = "grid")]
645        justify_items: None,
646        #[cfg(feature = "grid")]
647        justify_self: None,
648        #[cfg(any(feature = "flexbox", feature = "grid"))]
649        align_content: None,
650        #[cfg(any(feature = "flexbox", feature = "grid"))]
651        justify_content: None,
652        // Block
653        #[cfg(feature = "block_layout")]
654        text_align: TextAlign::Auto,
655        // Flexbox
656        #[cfg(feature = "flexbox")]
657        flex_direction: FlexDirection::Row,
658        #[cfg(feature = "flexbox")]
659        flex_wrap: FlexWrap::NoWrap,
660        #[cfg(feature = "flexbox")]
661        flex_grow: 0.0,
662        #[cfg(feature = "flexbox")]
663        flex_shrink: 1.0,
664        #[cfg(feature = "flexbox")]
665        flex_basis: Dimension::AUTO,
666        // Grid
667        #[cfg(feature = "grid")]
668        grid_template_rows: GridTrackVec::new(),
669        #[cfg(feature = "grid")]
670        grid_template_columns: GridTrackVec::new(),
671        #[cfg(feature = "grid")]
672        grid_template_areas: GridTrackVec::new(),
673        #[cfg(feature = "grid")]
674        grid_template_column_names: GridTrackVec::new(),
675        #[cfg(feature = "grid")]
676        grid_template_row_names: GridTrackVec::new(),
677        #[cfg(feature = "grid")]
678        grid_auto_rows: GridTrackVec::new(),
679        #[cfg(feature = "grid")]
680        grid_auto_columns: GridTrackVec::new(),
681        #[cfg(feature = "grid")]
682        grid_auto_flow: GridAutoFlow::Row,
683        #[cfg(feature = "grid")]
684        grid_row: Line { start: GridPlacement::<U::Str>::Auto, end: GridPlacement::<U::Str>::Auto },
685        #[cfg(feature = "grid")]
686        grid_column: Line { start: GridPlacement::<U::Str>::Auto, end: GridPlacement::<U::Str>::Auto },
687    };
688}
689
690impl<U: Units> Default for Style<U> {
691    fn default() -> Self {
692        Style::DEFAULT
693    }
694}
695
696impl<U: Units> CoreStyle for Style<U> {
697    type Units = U;
698
699    #[inline(always)]
700    fn box_generation_mode(&self) -> BoxGenerationMode {
701        match self.display {
702            Display::None => BoxGenerationMode::None,
703            _ => BoxGenerationMode::Normal,
704        }
705    }
706    #[inline(always)]
707    #[cfg(feature = "block_layout")]
708    fn is_block(&self) -> bool {
709        matches!(self.display, Display::Block)
710    }
711    #[inline(always)]
712    fn is_compressible_replaced(&self) -> bool {
713        self.item_is_replaced
714    }
715    #[inline(always)]
716    fn box_sizing(&self) -> BoxSizing {
717        self.box_sizing
718    }
719    #[inline(always)]
720    fn direction(&self) -> Direction {
721        self.direction
722    }
723    #[inline(always)]
724    fn overflow(&self) -> Point<Overflow> {
725        self.overflow
726    }
727    #[inline(always)]
728    fn scrollbar_width(&self) -> f32 {
729        self.scrollbar_width
730    }
731    #[inline(always)]
732    fn position(&self) -> Position {
733        self.position
734    }
735    #[inline(always)]
736    fn inset(&self) -> Rect<LengthPercentageAuto> {
737        self.inset
738    }
739    #[inline(always)]
740    fn size(&self) -> Size<Dimension> {
741        self.size
742    }
743    #[inline(always)]
744    fn min_size(&self) -> Size<Dimension> {
745        self.min_size
746    }
747    #[inline(always)]
748    fn max_size(&self) -> Size<Dimension> {
749        self.max_size
750    }
751    #[inline(always)]
752    fn aspect_ratio(&self) -> Option<f32> {
753        self.aspect_ratio
754    }
755    #[inline(always)]
756    fn margin(&self) -> Rect<LengthPercentageAuto> {
757        self.margin
758    }
759    #[inline(always)]
760    fn padding(&self) -> Rect<LengthPercentage> {
761        self.padding
762    }
763    #[inline(always)]
764    fn border(&self) -> Rect<LengthPercentage> {
765        self.border
766    }
767}
768
769impl<T: CoreStyle> CoreStyle for &'_ T {
770    type Units = T::Units;
771
772    #[inline(always)]
773    fn box_generation_mode(&self) -> BoxGenerationMode {
774        (*self).box_generation_mode()
775    }
776    #[inline(always)]
777    fn is_block(&self) -> bool {
778        (*self).is_block()
779    }
780    #[inline(always)]
781    fn is_compressible_replaced(&self) -> bool {
782        (*self).is_compressible_replaced()
783    }
784    #[inline(always)]
785    fn box_sizing(&self) -> BoxSizing {
786        (*self).box_sizing()
787    }
788    #[inline(always)]
789    fn direction(&self) -> Direction {
790        (*self).direction()
791    }
792    #[inline(always)]
793    fn overflow(&self) -> Point<Overflow> {
794        (*self).overflow()
795    }
796    #[inline(always)]
797    fn scrollbar_width(&self) -> f32 {
798        (*self).scrollbar_width()
799    }
800    #[inline(always)]
801    fn position(&self) -> Position {
802        (*self).position()
803    }
804    #[inline(always)]
805    fn inset(&self) -> Rect<LengthPercentageAuto> {
806        (*self).inset()
807    }
808    #[inline(always)]
809    fn size(&self) -> Size<Dimension> {
810        (*self).size()
811    }
812    #[inline(always)]
813    fn min_size(&self) -> Size<Dimension> {
814        (*self).min_size()
815    }
816    #[inline(always)]
817    fn max_size(&self) -> Size<Dimension> {
818        (*self).max_size()
819    }
820    #[inline(always)]
821    fn aspect_ratio(&self) -> Option<f32> {
822        (*self).aspect_ratio()
823    }
824    #[inline(always)]
825    fn margin(&self) -> Rect<LengthPercentageAuto> {
826        (*self).margin()
827    }
828    #[inline(always)]
829    fn padding(&self) -> Rect<LengthPercentage> {
830        (*self).padding()
831    }
832    #[inline(always)]
833    fn border(&self) -> Rect<LengthPercentage> {
834        (*self).border()
835    }
836}
837
838#[cfg(feature = "block_layout")]
839impl<U: Units> BlockContainerStyle for Style<U> {
840    #[inline(always)]
841    fn text_align(&self) -> TextAlign {
842        self.text_align
843    }
844}
845
846#[cfg(feature = "block_layout")]
847impl<T: BlockContainerStyle> BlockContainerStyle for &'_ T {
848    #[inline(always)]
849    fn text_align(&self) -> TextAlign {
850        (*self).text_align()
851    }
852}
853
854#[cfg(feature = "block_layout")]
855impl<U: Units> BlockItemStyle for Style<U> {
856    #[inline(always)]
857    fn is_table(&self) -> bool {
858        self.item_is_table
859    }
860
861    #[cfg(feature = "float_layout")]
862    #[inline(always)]
863    fn float(&self) -> Float {
864        self.float
865    }
866
867    #[cfg(feature = "float_layout")]
868    #[inline(always)]
869    fn clear(&self) -> Clear {
870        self.clear
871    }
872}
873
874#[cfg(feature = "block_layout")]
875impl<T: BlockItemStyle> BlockItemStyle for &'_ T {
876    #[inline(always)]
877    fn is_table(&self) -> bool {
878        (*self).is_table()
879    }
880
881    #[cfg(feature = "float_layout")]
882    #[inline(always)]
883    fn float(&self) -> Float {
884        (*self).float()
885    }
886
887    #[cfg(feature = "float_layout")]
888    #[inline(always)]
889    fn clear(&self) -> Clear {
890        (*self).clear()
891    }
892}
893
894#[cfg(feature = "flexbox")]
895impl<U: Units> FlexboxContainerStyle for Style<U> {
896    #[inline(always)]
897    fn flex_direction(&self) -> FlexDirection {
898        self.flex_direction
899    }
900    #[inline(always)]
901    fn flex_wrap(&self) -> FlexWrap {
902        self.flex_wrap
903    }
904    #[inline(always)]
905    fn gap(&self) -> Size<LengthPercentage> {
906        self.gap
907    }
908    #[inline(always)]
909    fn align_content(&self) -> Option<AlignContent> {
910        self.align_content
911    }
912    #[inline(always)]
913    fn align_items(&self) -> Option<AlignItems> {
914        self.align_items
915    }
916    #[inline(always)]
917    fn justify_content(&self) -> Option<JustifyContent> {
918        self.justify_content
919    }
920}
921
922#[cfg(feature = "flexbox")]
923impl<T: FlexboxContainerStyle> FlexboxContainerStyle for &'_ T {
924    #[inline(always)]
925    fn flex_direction(&self) -> FlexDirection {
926        (*self).flex_direction()
927    }
928    #[inline(always)]
929    fn flex_wrap(&self) -> FlexWrap {
930        (*self).flex_wrap()
931    }
932    #[inline(always)]
933    fn gap(&self) -> Size<LengthPercentage> {
934        (*self).gap()
935    }
936    #[inline(always)]
937    fn align_content(&self) -> Option<AlignContent> {
938        (*self).align_content()
939    }
940    #[inline(always)]
941    fn align_items(&self) -> Option<AlignItems> {
942        (*self).align_items()
943    }
944    #[inline(always)]
945    fn justify_content(&self) -> Option<JustifyContent> {
946        (*self).justify_content()
947    }
948}
949
950#[cfg(feature = "flexbox")]
951impl<U: Units> FlexboxItemStyle for Style<U> {
952    #[inline(always)]
953    fn flex_basis(&self) -> Dimension {
954        self.flex_basis
955    }
956    #[inline(always)]
957    fn flex_grow(&self) -> f32 {
958        self.flex_grow
959    }
960    #[inline(always)]
961    fn flex_shrink(&self) -> f32 {
962        self.flex_shrink
963    }
964    #[inline(always)]
965    fn align_self(&self) -> Option<AlignSelf> {
966        self.align_self
967    }
968}
969
970#[cfg(feature = "flexbox")]
971impl<T: FlexboxItemStyle> FlexboxItemStyle for &'_ T {
972    #[inline(always)]
973    fn flex_basis(&self) -> Dimension {
974        (*self).flex_basis()
975    }
976    #[inline(always)]
977    fn flex_grow(&self) -> f32 {
978        (*self).flex_grow()
979    }
980    #[inline(always)]
981    fn flex_shrink(&self) -> f32 {
982        (*self).flex_shrink()
983    }
984    #[inline(always)]
985    fn align_self(&self) -> Option<AlignSelf> {
986        (*self).align_self()
987    }
988}
989
990#[cfg(feature = "grid")]
991impl<U: Units> GridContainerStyle for Style<U> {
992    type Repetition<'a>
993        = &'a GridTemplateRepetition<U::Str>
994    where
995        Self: 'a;
996
997    type TemplateTrackList<'a>
998        = core::iter::Map<
999        core::slice::Iter<'a, GridTemplateComponent<U::Str>>,
1000        fn(
1001            &'a GridTemplateComponent<U::Str>,
1002        ) -> GenericGridTemplateComponent<U::Str, &'a GridTemplateRepetition<U::Str>>,
1003    >
1004    where
1005        Self: 'a;
1006
1007    type AutoTrackList<'a>
1008        = core::iter::Copied<core::slice::Iter<'a, TrackSizingFunction>>
1009    where
1010        Self: 'a;
1011
1012    #[cfg(feature = "grid")]
1013    type TemplateLineNames<'a>
1014        = core::iter::Map<
1015        core::slice::Iter<'a, GridTrackVec<U::Str>>,
1016        fn(&GridTrackVec<U::Str>) -> core::slice::Iter<'_, U::Str>,
1017    >
1018    where
1019        Self: 'a;
1020    #[cfg(feature = "grid")]
1021    type GridTemplateAreas<'a>
1022        = core::iter::Cloned<core::slice::Iter<'a, GridTemplateArea<U::Str>>>
1023    where
1024        Self: 'a;
1025
1026    #[inline(always)]
1027    fn grid_template_rows(&self) -> Option<Self::TemplateTrackList<'_>> {
1028        Some(self.grid_template_rows.iter().map(|c| c.as_component_ref()))
1029    }
1030    #[inline(always)]
1031    fn grid_template_columns(&self) -> Option<Self::TemplateTrackList<'_>> {
1032        Some(self.grid_template_columns.iter().map(|c| c.as_component_ref()))
1033    }
1034    #[inline(always)]
1035    fn grid_auto_rows(&self) -> Self::AutoTrackList<'_> {
1036        self.grid_auto_rows.iter().copied()
1037    }
1038    #[inline(always)]
1039    fn grid_auto_columns(&self) -> Self::AutoTrackList<'_> {
1040        self.grid_auto_columns.iter().copied()
1041    }
1042    #[inline(always)]
1043    fn grid_auto_flow(&self) -> GridAutoFlow {
1044        self.grid_auto_flow
1045    }
1046    #[inline(always)]
1047    fn gap(&self) -> Size<LengthPercentage> {
1048        self.gap
1049    }
1050    #[inline(always)]
1051    fn align_content(&self) -> Option<AlignContent> {
1052        self.align_content
1053    }
1054    #[inline(always)]
1055    fn justify_content(&self) -> Option<JustifyContent> {
1056        self.justify_content
1057    }
1058    #[inline(always)]
1059    fn align_items(&self) -> Option<AlignItems> {
1060        self.align_items
1061    }
1062    #[inline(always)]
1063    fn justify_items(&self) -> Option<AlignItems> {
1064        self.justify_items
1065    }
1066
1067    #[inline(always)]
1068    #[cfg(feature = "grid")]
1069    fn grid_template_areas(&self) -> Option<Self::GridTemplateAreas<'_>> {
1070        Some(self.grid_template_areas.iter().cloned())
1071    }
1072
1073    #[inline(always)]
1074    #[cfg(feature = "grid")]
1075    fn grid_template_column_names(&self) -> Option<Self::TemplateLineNames<'_>> {
1076        Some(self.grid_template_column_names.iter().map(|names| names.iter()))
1077    }
1078
1079    #[inline(always)]
1080    #[cfg(feature = "grid")]
1081    fn grid_template_row_names(&self) -> Option<Self::TemplateLineNames<'_>> {
1082        Some(self.grid_template_row_names.iter().map(|names| names.iter()))
1083    }
1084}
1085
1086#[cfg(feature = "grid")]
1087impl<T: GridContainerStyle> GridContainerStyle for &'_ T {
1088    type Repetition<'a>
1089        = T::Repetition<'a>
1090    where
1091        Self: 'a;
1092
1093    type TemplateTrackList<'a>
1094        = T::TemplateTrackList<'a>
1095    where
1096        Self: 'a;
1097
1098    type AutoTrackList<'a>
1099        = T::AutoTrackList<'a>
1100    where
1101        Self: 'a;
1102
1103    /// The type returned by grid_template_row_names and grid_template_column_names
1104    #[cfg(feature = "grid")]
1105    type TemplateLineNames<'a>
1106        = T::TemplateLineNames<'a>
1107    where
1108        Self: 'a;
1109    #[cfg(feature = "grid")]
1110    type GridTemplateAreas<'a>
1111        = T::GridTemplateAreas<'a>
1112    where
1113        Self: 'a;
1114
1115    #[inline(always)]
1116    fn grid_template_rows(&self) -> Option<Self::TemplateTrackList<'_>> {
1117        (*self).grid_template_rows()
1118    }
1119    #[inline(always)]
1120    fn grid_template_columns(&self) -> Option<Self::TemplateTrackList<'_>> {
1121        (*self).grid_template_columns()
1122    }
1123    #[inline(always)]
1124    fn grid_auto_rows(&self) -> Self::AutoTrackList<'_> {
1125        (*self).grid_auto_rows()
1126    }
1127    #[inline(always)]
1128    fn grid_auto_columns(&self) -> Self::AutoTrackList<'_> {
1129        (*self).grid_auto_columns()
1130    }
1131    #[cfg(feature = "grid")]
1132    #[inline(always)]
1133    fn grid_template_areas(&self) -> Option<Self::GridTemplateAreas<'_>> {
1134        (*self).grid_template_areas()
1135    }
1136    #[cfg(feature = "grid")]
1137    #[inline(always)]
1138    fn grid_template_column_names(&self) -> Option<Self::TemplateLineNames<'_>> {
1139        (*self).grid_template_column_names()
1140    }
1141    #[cfg(feature = "grid")]
1142    #[inline(always)]
1143    fn grid_template_row_names(&self) -> Option<Self::TemplateLineNames<'_>> {
1144        (*self).grid_template_row_names()
1145    }
1146    #[inline(always)]
1147    fn grid_auto_flow(&self) -> GridAutoFlow {
1148        (*self).grid_auto_flow()
1149    }
1150    #[inline(always)]
1151    fn gap(&self) -> Size<LengthPercentage> {
1152        (*self).gap()
1153    }
1154    #[inline(always)]
1155    fn align_content(&self) -> Option<AlignContent> {
1156        (*self).align_content()
1157    }
1158    #[inline(always)]
1159    fn justify_content(&self) -> Option<JustifyContent> {
1160        (*self).justify_content()
1161    }
1162    #[inline(always)]
1163    fn align_items(&self) -> Option<AlignItems> {
1164        (*self).align_items()
1165    }
1166    #[inline(always)]
1167    fn justify_items(&self) -> Option<AlignItems> {
1168        (*self).justify_items()
1169    }
1170}
1171
1172#[cfg(feature = "grid")]
1173impl<U: Units> GridItemStyle for Style<U> {
1174    #[inline(always)]
1175    fn grid_row(&self) -> Line<GridPlacement<U::Str>> {
1176        // TODO: Investigate eliminating clone
1177        self.grid_row.clone()
1178    }
1179    #[inline(always)]
1180    fn grid_column(&self) -> Line<GridPlacement<U::Str>> {
1181        // TODO: Investigate eliminating clone
1182        self.grid_column.clone()
1183    }
1184    #[inline(always)]
1185    fn align_self(&self) -> Option<AlignSelf> {
1186        self.align_self
1187    }
1188    #[inline(always)]
1189    fn justify_self(&self) -> Option<AlignSelf> {
1190        self.justify_self
1191    }
1192}
1193
1194#[cfg(feature = "grid")]
1195impl<T: GridItemStyle> GridItemStyle for &'_ T {
1196    #[inline(always)]
1197    fn grid_row(&self) -> Line<GridPlacement<<T::Units as Units>::Str>> {
1198        (*self).grid_row()
1199    }
1200    #[inline(always)]
1201    fn grid_column(&self) -> Line<GridPlacement<<T::Units as Units>::Str>> {
1202        (*self).grid_column()
1203    }
1204    #[inline(always)]
1205    fn align_self(&self) -> Option<AlignSelf> {
1206        (*self).align_self()
1207    }
1208    #[inline(always)]
1209    fn justify_self(&self) -> Option<AlignSelf> {
1210        (*self).justify_self()
1211    }
1212}
1213
1214#[cfg(test)]
1215mod tests {
1216    use std::sync::Arc;
1217
1218    use super::Style;
1219    use crate::DefaultUnits;
1220    use crate::{geometry::*, style_helpers::TaffyAuto as _};
1221
1222    #[test]
1223    fn defaults_match() {
1224        #[cfg(feature = "grid")]
1225        use super::GridPlacement;
1226
1227        let old_defaults: Style<DefaultUnits> = Style {
1228            dummy: core::marker::PhantomData,
1229            display: Default::default(),
1230            item_is_table: false,
1231            item_is_replaced: false,
1232            box_sizing: Default::default(),
1233            #[cfg(feature = "float_layout")]
1234            float: Default::default(),
1235            #[cfg(feature = "float_layout")]
1236            clear: Default::default(),
1237            direction: Default::default(),
1238            overflow: Default::default(),
1239            scrollbar_width: 0.0,
1240            position: Default::default(),
1241            #[cfg(feature = "flexbox")]
1242            flex_direction: Default::default(),
1243            #[cfg(feature = "flexbox")]
1244            flex_wrap: Default::default(),
1245            #[cfg(any(feature = "flexbox", feature = "grid"))]
1246            align_items: Default::default(),
1247            #[cfg(any(feature = "flexbox", feature = "grid"))]
1248            align_self: Default::default(),
1249            #[cfg(feature = "grid")]
1250            justify_items: Default::default(),
1251            #[cfg(feature = "grid")]
1252            justify_self: Default::default(),
1253            #[cfg(any(feature = "flexbox", feature = "grid"))]
1254            align_content: Default::default(),
1255            #[cfg(any(feature = "flexbox", feature = "grid"))]
1256            justify_content: Default::default(),
1257            inset: Rect::auto(),
1258            margin: Rect::zero(),
1259            padding: Rect::zero(),
1260            border: Rect::zero(),
1261            gap: Size::zero(),
1262            #[cfg(feature = "block_layout")]
1263            text_align: Default::default(),
1264            #[cfg(feature = "flexbox")]
1265            flex_grow: 0.0,
1266            #[cfg(feature = "flexbox")]
1267            flex_shrink: 1.0,
1268            #[cfg(feature = "flexbox")]
1269            flex_basis: super::Dimension::AUTO,
1270            size: Size::auto(),
1271            min_size: Size::auto(),
1272            max_size: Size::auto(),
1273            aspect_ratio: Default::default(),
1274            #[cfg(feature = "grid")]
1275            grid_template_rows: Default::default(),
1276            #[cfg(feature = "grid")]
1277            grid_template_columns: Default::default(),
1278            #[cfg(feature = "grid")]
1279            grid_template_row_names: Default::default(),
1280            #[cfg(feature = "grid")]
1281            grid_template_column_names: Default::default(),
1282            #[cfg(feature = "grid")]
1283            grid_template_areas: Default::default(),
1284            #[cfg(feature = "grid")]
1285            grid_auto_rows: Default::default(),
1286            #[cfg(feature = "grid")]
1287            grid_auto_columns: Default::default(),
1288            #[cfg(feature = "grid")]
1289            grid_auto_flow: Default::default(),
1290            #[cfg(feature = "grid")]
1291            grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
1292            #[cfg(feature = "grid")]
1293            grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
1294        };
1295
1296        assert_eq!(Style::DEFAULT, Style::<DefaultUnits>::default());
1297        assert_eq!(Style::DEFAULT, old_defaults);
1298    }
1299
1300    // NOTE: Please feel free the update the sizes in this test as required. This test is here to prevent unintentional size changes
1301    // and to serve as accurate up-to-date documentation on the sizes.
1302    #[test]
1303    fn style_sizes() {
1304        use super::*;
1305        type S = crate::sys::DefaultCheapStr;
1306
1307        fn assert_type_size<T>(expected_size: usize) {
1308            let name = ::core::any::type_name::<T>();
1309            let name = name.replace("taffy::geometry::", "");
1310            let name = name.replace("taffy::style::dimension::", "");
1311            let name = name.replace("taffy::style::alignment::", "");
1312            let name = name.replace("taffy::style::flex::", "");
1313            let name = name.replace("taffy::style::grid::", "");
1314
1315            assert_eq!(
1316                ::core::mem::size_of::<T>(),
1317                expected_size,
1318                "Expected {} for be {} byte(s) but it was {} byte(s)",
1319                name,
1320                expected_size,
1321                ::core::mem::size_of::<T>(),
1322            );
1323        }
1324
1325        // Display and Position
1326        assert_type_size::<Display>(1);
1327        assert_type_size::<BoxSizing>(1);
1328        assert_type_size::<Position>(1);
1329        assert_type_size::<Overflow>(1);
1330
1331        // Dimensions and aggregations of Dimensions
1332        assert_type_size::<f32>(4);
1333        assert_type_size::<LengthPercentage>(8);
1334        assert_type_size::<LengthPercentageAuto>(8);
1335        assert_type_size::<Dimension>(8);
1336        assert_type_size::<Size<LengthPercentage>>(16);
1337        assert_type_size::<Size<LengthPercentageAuto>>(16);
1338        assert_type_size::<Size<Dimension>>(16);
1339        assert_type_size::<Rect<LengthPercentage>>(32);
1340        assert_type_size::<Rect<LengthPercentageAuto>>(32);
1341        assert_type_size::<Rect<Dimension>>(32);
1342
1343        // Alignment
1344        assert_type_size::<AlignContent>(1);
1345        assert_type_size::<AlignItems>(1);
1346        assert_type_size::<Option<AlignItems>>(1);
1347
1348        // Flexbox Container
1349        assert_type_size::<FlexDirection>(1);
1350        assert_type_size::<FlexWrap>(1);
1351
1352        // CSS Grid Container
1353        assert_type_size::<GridAutoFlow>(1);
1354        assert_type_size::<MinTrackSizingFunction>(8);
1355        assert_type_size::<MaxTrackSizingFunction>(8);
1356        assert_type_size::<TrackSizingFunction>(16);
1357        assert_type_size::<Vec<TrackSizingFunction>>(24);
1358        assert_type_size::<Vec<GridTemplateComponent<S>>>(24);
1359
1360        // String-type dependent (String)
1361        assert_type_size::<GridTemplateComponent<String>>(56);
1362        assert_type_size::<GridPlacement<String>>(32);
1363        assert_type_size::<Line<GridPlacement<String>>>(64);
1364
1365        // String-type dependent (Arc<str>)
1366        assert_type_size::<GridTemplateComponent<Arc<str>>>(56);
1367        assert_type_size::<GridPlacement<Arc<str>>>(24);
1368        assert_type_size::<Line<GridPlacement<Arc<str>>>>(48);
1369
1370        // Overall size (default units)
1371        assert_type_size::<Style<DefaultUnits>>(536);
1372    }
1373}