tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 1077HTML 1008Markdown 12TOML 83209 Sutichaykuna

⎇ a4b481f99f435f2b304ef63d272bbd49136d4f14 src/style/mod.rs Rust · 1085 siq'ikuna · 36.5 KB Ñawpa willay Pi imata llamkarqan ch'uya

Special-case "compressible replaced elements" in grid sizing algorithm (#807) a4b481f99 · Nico Burns ·

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