gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Definiciones

⎇ 89f50ccb7d37e4d4b78a8250eca82eeaf63ad3de src/style/mod.rs Rust · 1364 líneas · 46.4 KB Historia Quién tocó qué crudo

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