tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 1061HTML 997Markdown 12TOML 83120 Definiciones

⎇ 416558f357c4205c4c7f99552f33a97faf41b142 src/style/mod.rs Rust · 1022 líneas · 34.7 KB Historia Quién tocó qué crudo

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