• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
2 mod alignment;
3 mod dimension;
4 
5 #[cfg(feature = "block_layout")]
6 mod block;
7 #[cfg(feature = "flexbox")]
8 mod flex;
9 #[cfg(feature = "grid")]
10 mod grid;
11 
12 pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf};
13 pub use self::dimension::{AvailableSpace, Dimension, LengthPercentage, LengthPercentageAuto};
14 
15 #[cfg(feature = "block_layout")]
16 pub use self::block::{BlockContainerStyle, BlockItemStyle, TextAlign};
17 #[cfg(feature = "flexbox")]
18 pub use self::flex::{FlexDirection, FlexWrap, FlexboxContainerStyle, FlexboxItemStyle};
19 #[cfg(feature = "grid")]
20 pub(crate) use self::grid::{GenericGridPlacement, OriginZeroGridPlacement};
21 #[cfg(feature = "grid")]
22 pub use self::grid::{
23     GridAutoFlow, GridContainerStyle, GridItemStyle, GridPlacement, GridTrackRepetition, MaxTrackSizingFunction,
24     MinTrackSizingFunction, NonRepeatedTrackSizingFunction, TrackSizingFunction,
25 };
26 
27 use crate::geometry::{Point, Rect, Size};
28 
29 #[cfg(feature = "grid")]
30 use crate::geometry::Line;
31 #[cfg(feature = "serde")]
32 use crate::style_helpers;
33 #[cfg(feature = "grid")]
34 use 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.
41 pub trait CoreStyle {
42     /// Which box generation mode should be used
43     #[inline(always)]
box_generation_mode(&self) -> BoxGenerationMode44     fn box_generation_mode(&self) -> BoxGenerationMode {
45         BoxGenerationMode::DEFAULT
46     }
47     /// Is block layout?
48     #[inline(always)]
is_block(&self) -> bool49     fn is_block(&self) -> bool {
50         false
51     }
52     /// Which box do size styles apply to
53     #[inline(always)]
box_sizing(&self) -> BoxSizing54     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)]
overflow(&self) -> Point<Overflow>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)]
scrollbar_width(&self) -> f3266     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)]
position(&self) -> Position73     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)]
inset(&self) -> Rect<LengthPercentageAuto>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)]
size(&self) -> Size<Dimension>85     fn size(&self) -> Size<Dimension> {
86         Style::DEFAULT.size
87     }
88     /// Controls the minimum size of the item
89     #[inline(always)]
min_size(&self) -> Size<Dimension>90     fn min_size(&self) -> Size<Dimension> {
91         Style::DEFAULT.min_size
92     }
93     /// Controls the maximum size of the item
94     #[inline(always)]
max_size(&self) -> Size<Dimension>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)]
aspect_ratio(&self) -> Option<f32>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)]
margin(&self) -> Rect<LengthPercentageAuto>108     fn margin(&self) -> Rect<LengthPercentageAuto> {
109         Style::DEFAULT.margin
110     }
111     /// How large should the padding be on each side?
112     #[inline(always)]
padding(&self) -> Rect<LengthPercentage>113     fn padding(&self) -> Rect<LengthPercentage> {
114         Style::DEFAULT.padding
115     }
116     /// How large should the border be on each side?
117     #[inline(always)]
border(&self) -> Rect<LengthPercentage>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))]
128 pub 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 
142 impl 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 
160 impl Default for Display {
default() -> Self161     fn default() -> Self {
162         Self::DEFAULT
163     }
164 }
165 
166 impl core::fmt::Display for Display {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result167     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))]
184 pub 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 
191 impl BoxGenerationMode {
192     /// The default of BoxGenerationMode
193     pub const DEFAULT: BoxGenerationMode = BoxGenerationMode::Normal;
194 }
195 
196 impl Default for BoxGenerationMode {
default() -> Self197     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))]
213 pub 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 
225 impl Default for Position {
default() -> Self226     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))]
246 pub 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 
253 impl Default for BoxSizing {
default() -> Self254     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))]
274 pub 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 
291 impl 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)]
is_scroll_container(self) -> bool295     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)]
maybe_into_automatic_min_size(self) -> Option<f32>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))]
330 pub struct Style {
331     /// What layout strategy should be used?
332     pub display: Display,
333     /// Whether a child is display:table or not. This affects children of block layouts.
334     /// This should really be part of `Display`, but it is currently seperate because table layout isn't implemented
335     pub item_is_table: bool,
336     /// Should size styles apply to the content box or the border box of the node
337     pub box_sizing: BoxSizing,
338 
339     // Overflow properties
340     /// How children overflowing their container should affect layout
341     pub overflow: Point<Overflow>,
342     /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
343     pub scrollbar_width: f32,
344 
345     // Position properties
346     /// What should the `position` value of this struct use as a base offset?
347     pub position: Position,
348     /// How should the position of this element be tweaked relative to the layout defined?
349     #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
350     pub inset: Rect<LengthPercentageAuto>,
351 
352     // Size properties
353     /// Sets the initial size of the item
354     #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
355     pub size: Size<Dimension>,
356     /// Controls the minimum size of the item
357     #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
358     pub min_size: Size<Dimension>,
359     /// Controls the maximum size of the item
360     #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
361     pub max_size: Size<Dimension>,
362     /// Sets the preferred aspect ratio for the item
363     ///
364     /// The ratio is calculated as width divided by height.
365     pub aspect_ratio: Option<f32>,
366 
367     // Spacing Properties
368     /// How large should the margin be on each side?
369     #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
370     pub margin: Rect<LengthPercentageAuto>,
371     /// How large should the padding be on each side?
372     #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
373     pub padding: Rect<LengthPercentage>,
374     /// How large should the border be on each side?
375     #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
376     pub border: Rect<LengthPercentage>,
377 
378     // Alignment properties
379     /// How this node's children aligned in the cross/block axis?
380     #[cfg(any(feature = "flexbox", feature = "grid"))]
381     pub align_items: Option<AlignItems>,
382     /// How this node should be aligned in the cross/block axis
383     /// Falls back to the parents [`AlignItems`] if not set
384     #[cfg(any(feature = "flexbox", feature = "grid"))]
385     pub align_self: Option<AlignSelf>,
386     /// How this node's children should be aligned in the inline axis
387     #[cfg(feature = "grid")]
388     pub justify_items: Option<AlignItems>,
389     /// How this node should be aligned in the inline axis
390     /// Falls back to the parents [`JustifyItems`] if not set
391     #[cfg(feature = "grid")]
392     pub justify_self: Option<AlignSelf>,
393     /// How should content contained within this item be aligned in the cross/block axis
394     #[cfg(any(feature = "flexbox", feature = "grid"))]
395     pub align_content: Option<AlignContent>,
396     /// How should content contained within this item be aligned in the main/inline axis
397     #[cfg(any(feature = "flexbox", feature = "grid"))]
398     pub justify_content: Option<JustifyContent>,
399     /// How large should the gaps between items in a grid or flex container be?
400     #[cfg(any(feature = "flexbox", feature = "grid"))]
401     #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
402     pub gap: Size<LengthPercentage>,
403 
404     // Block container properties
405     /// How items elements should aligned in the inline axis
406     #[cfg(feature = "block_layout")]
407     pub text_align: TextAlign,
408 
409     // Flexbox container properties
410     /// Which direction does the main axis flow in?
411     #[cfg(feature = "flexbox")]
412     pub flex_direction: FlexDirection,
413     /// Should elements wrap, or stay in a single line?
414     #[cfg(feature = "flexbox")]
415     pub flex_wrap: FlexWrap,
416 
417     // Flexbox item properties
418     /// Sets the initial main axis size of the item
419     #[cfg(feature = "flexbox")]
420     pub flex_basis: Dimension,
421     /// The relative rate at which this item grows when it is expanding to fill space
422     ///
423     /// 0.0 is the default value, and this value must be positive.
424     #[cfg(feature = "flexbox")]
425     pub flex_grow: f32,
426     /// The relative rate at which this item shrinks when it is contracting to fit into space
427     ///
428     /// 1.0 is the default value, and this value must be positive.
429     #[cfg(feature = "flexbox")]
430     pub flex_shrink: f32,
431 
432     // Grid container properies
433     /// Defines the track sizing functions (heights) of the grid rows
434     #[cfg(feature = "grid")]
435     pub grid_template_rows: GridTrackVec<TrackSizingFunction>,
436     /// Defines the track sizing functions (widths) of the grid columns
437     #[cfg(feature = "grid")]
438     pub grid_template_columns: GridTrackVec<TrackSizingFunction>,
439     /// Defines the size of implicitly created rows
440     #[cfg(feature = "grid")]
441     pub grid_auto_rows: GridTrackVec<NonRepeatedTrackSizingFunction>,
442     /// Defined the size of implicitly created columns
443     #[cfg(feature = "grid")]
444     pub grid_auto_columns: GridTrackVec<NonRepeatedTrackSizingFunction>,
445     /// Controls how items get placed into the grid for auto-placed items
446     #[cfg(feature = "grid")]
447     pub grid_auto_flow: GridAutoFlow,
448 
449     // Grid child properties
450     /// Defines which row in the grid the item should start and end at
451     #[cfg(feature = "grid")]
452     pub grid_row: Line<GridPlacement>,
453     /// Defines which column in the grid the item should start and end at
454     #[cfg(feature = "grid")]
455     pub grid_column: Line<GridPlacement>,
456 }
457 
458 impl Style {
459     /// The [`Default`] layout, in a form that can be used in const functions
460     pub const DEFAULT: Style = Style {
461         display: Display::DEFAULT,
462         item_is_table: false,
463         box_sizing: BoxSizing::BorderBox,
464         overflow: Point { x: Overflow::Visible, y: Overflow::Visible },
465         scrollbar_width: 0.0,
466         position: Position::Relative,
467         inset: Rect::auto(),
468         margin: Rect::zero(),
469         padding: Rect::zero(),
470         border: Rect::zero(),
471         size: Size::auto(),
472         min_size: Size::auto(),
473         max_size: Size::auto(),
474         aspect_ratio: None,
475         #[cfg(any(feature = "flexbox", feature = "grid"))]
476         gap: Size::zero(),
477         // Alignment
478         #[cfg(any(feature = "flexbox", feature = "grid"))]
479         align_items: None,
480         #[cfg(any(feature = "flexbox", feature = "grid"))]
481         align_self: None,
482         #[cfg(feature = "grid")]
483         justify_items: None,
484         #[cfg(feature = "grid")]
485         justify_self: None,
486         #[cfg(any(feature = "flexbox", feature = "grid"))]
487         align_content: None,
488         #[cfg(any(feature = "flexbox", feature = "grid"))]
489         justify_content: None,
490         // Block
491         #[cfg(feature = "block_layout")]
492         text_align: TextAlign::Auto,
493         // Flexbox
494         #[cfg(feature = "flexbox")]
495         flex_direction: FlexDirection::Row,
496         #[cfg(feature = "flexbox")]
497         flex_wrap: FlexWrap::NoWrap,
498         #[cfg(feature = "flexbox")]
499         flex_grow: 0.0,
500         #[cfg(feature = "flexbox")]
501         flex_shrink: 1.0,
502         #[cfg(feature = "flexbox")]
503         flex_basis: Dimension::Auto,
504         // Grid
505         #[cfg(feature = "grid")]
506         grid_template_rows: GridTrackVec::new(),
507         #[cfg(feature = "grid")]
508         grid_template_columns: GridTrackVec::new(),
509         #[cfg(feature = "grid")]
510         grid_auto_rows: GridTrackVec::new(),
511         #[cfg(feature = "grid")]
512         grid_auto_columns: GridTrackVec::new(),
513         #[cfg(feature = "grid")]
514         grid_auto_flow: GridAutoFlow::Row,
515         #[cfg(feature = "grid")]
516         grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
517         #[cfg(feature = "grid")]
518         grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
519     };
520 }
521 
522 impl Default for Style {
default() -> Self523     fn default() -> Self {
524         Style::DEFAULT
525     }
526 }
527 
528 impl CoreStyle for Style {
529     #[inline(always)]
box_generation_mode(&self) -> BoxGenerationMode530     fn box_generation_mode(&self) -> BoxGenerationMode {
531         match self.display {
532             Display::None => BoxGenerationMode::None,
533             _ => BoxGenerationMode::Normal,
534         }
535     }
536     #[inline(always)]
537     #[cfg(feature = "block_layout")]
is_block(&self) -> bool538     fn is_block(&self) -> bool {
539         matches!(self.display, Display::Block)
540     }
541     #[inline(always)]
box_sizing(&self) -> BoxSizing542     fn box_sizing(&self) -> BoxSizing {
543         self.box_sizing
544     }
545     #[inline(always)]
overflow(&self) -> Point<Overflow>546     fn overflow(&self) -> Point<Overflow> {
547         self.overflow
548     }
549     #[inline(always)]
scrollbar_width(&self) -> f32550     fn scrollbar_width(&self) -> f32 {
551         self.scrollbar_width
552     }
553     #[inline(always)]
position(&self) -> Position554     fn position(&self) -> Position {
555         self.position
556     }
557     #[inline(always)]
inset(&self) -> Rect<LengthPercentageAuto>558     fn inset(&self) -> Rect<LengthPercentageAuto> {
559         self.inset
560     }
561     #[inline(always)]
size(&self) -> Size<Dimension>562     fn size(&self) -> Size<Dimension> {
563         self.size
564     }
565     #[inline(always)]
min_size(&self) -> Size<Dimension>566     fn min_size(&self) -> Size<Dimension> {
567         self.min_size
568     }
569     #[inline(always)]
max_size(&self) -> Size<Dimension>570     fn max_size(&self) -> Size<Dimension> {
571         self.max_size
572     }
573     #[inline(always)]
aspect_ratio(&self) -> Option<f32>574     fn aspect_ratio(&self) -> Option<f32> {
575         self.aspect_ratio
576     }
577     #[inline(always)]
margin(&self) -> Rect<LengthPercentageAuto>578     fn margin(&self) -> Rect<LengthPercentageAuto> {
579         self.margin
580     }
581     #[inline(always)]
padding(&self) -> Rect<LengthPercentage>582     fn padding(&self) -> Rect<LengthPercentage> {
583         self.padding
584     }
585     #[inline(always)]
border(&self) -> Rect<LengthPercentage>586     fn border(&self) -> Rect<LengthPercentage> {
587         self.border
588     }
589 }
590 
591 impl<T: CoreStyle> CoreStyle for &'_ T {
592     #[inline(always)]
box_generation_mode(&self) -> BoxGenerationMode593     fn box_generation_mode(&self) -> BoxGenerationMode {
594         (*self).box_generation_mode()
595     }
596     #[inline(always)]
is_block(&self) -> bool597     fn is_block(&self) -> bool {
598         (*self).is_block()
599     }
600     #[inline(always)]
box_sizing(&self) -> BoxSizing601     fn box_sizing(&self) -> BoxSizing {
602         (*self).box_sizing()
603     }
604     #[inline(always)]
overflow(&self) -> Point<Overflow>605     fn overflow(&self) -> Point<Overflow> {
606         (*self).overflow()
607     }
608     #[inline(always)]
scrollbar_width(&self) -> f32609     fn scrollbar_width(&self) -> f32 {
610         (*self).scrollbar_width()
611     }
612     #[inline(always)]
position(&self) -> Position613     fn position(&self) -> Position {
614         (*self).position()
615     }
616     #[inline(always)]
inset(&self) -> Rect<LengthPercentageAuto>617     fn inset(&self) -> Rect<LengthPercentageAuto> {
618         (*self).inset()
619     }
620     #[inline(always)]
size(&self) -> Size<Dimension>621     fn size(&self) -> Size<Dimension> {
622         (*self).size()
623     }
624     #[inline(always)]
min_size(&self) -> Size<Dimension>625     fn min_size(&self) -> Size<Dimension> {
626         (*self).min_size()
627     }
628     #[inline(always)]
max_size(&self) -> Size<Dimension>629     fn max_size(&self) -> Size<Dimension> {
630         (*self).max_size()
631     }
632     #[inline(always)]
aspect_ratio(&self) -> Option<f32>633     fn aspect_ratio(&self) -> Option<f32> {
634         (*self).aspect_ratio()
635     }
636     #[inline(always)]
margin(&self) -> Rect<LengthPercentageAuto>637     fn margin(&self) -> Rect<LengthPercentageAuto> {
638         (*self).margin()
639     }
640     #[inline(always)]
padding(&self) -> Rect<LengthPercentage>641     fn padding(&self) -> Rect<LengthPercentage> {
642         (*self).padding()
643     }
644     #[inline(always)]
border(&self) -> Rect<LengthPercentage>645     fn border(&self) -> Rect<LengthPercentage> {
646         (*self).border()
647     }
648 }
649 
650 #[cfg(feature = "block_layout")]
651 impl BlockContainerStyle for &Style {
652     #[inline(always)]
text_align(&self) -> TextAlign653     fn text_align(&self) -> TextAlign {
654         self.text_align
655     }
656 }
657 
658 #[cfg(feature = "block_layout")]
659 impl<T: BlockContainerStyle> BlockContainerStyle for &'_ T {
660     #[inline(always)]
text_align(&self) -> TextAlign661     fn text_align(&self) -> TextAlign {
662         (*self).text_align()
663     }
664 }
665 
666 #[cfg(feature = "block_layout")]
667 impl BlockItemStyle for Style {
668     #[inline(always)]
is_table(&self) -> bool669     fn is_table(&self) -> bool {
670         self.item_is_table
671     }
672 }
673 
674 #[cfg(feature = "block_layout")]
675 impl<T: BlockItemStyle> BlockItemStyle for &'_ T {
676     #[inline(always)]
is_table(&self) -> bool677     fn is_table(&self) -> bool {
678         (*self).is_table()
679     }
680 }
681 
682 #[cfg(feature = "flexbox")]
683 impl FlexboxContainerStyle for Style {
684     #[inline(always)]
flex_direction(&self) -> FlexDirection685     fn flex_direction(&self) -> FlexDirection {
686         self.flex_direction
687     }
688     #[inline(always)]
flex_wrap(&self) -> FlexWrap689     fn flex_wrap(&self) -> FlexWrap {
690         self.flex_wrap
691     }
692     #[inline(always)]
gap(&self) -> Size<LengthPercentage>693     fn gap(&self) -> Size<LengthPercentage> {
694         self.gap
695     }
696     #[inline(always)]
align_content(&self) -> Option<AlignContent>697     fn align_content(&self) -> Option<AlignContent> {
698         self.align_content
699     }
700     #[inline(always)]
align_items(&self) -> Option<AlignItems>701     fn align_items(&self) -> Option<AlignItems> {
702         self.align_items
703     }
704     #[inline(always)]
justify_content(&self) -> Option<JustifyContent>705     fn justify_content(&self) -> Option<JustifyContent> {
706         self.justify_content
707     }
708 }
709 
710 #[cfg(feature = "flexbox")]
711 impl<T: FlexboxContainerStyle> FlexboxContainerStyle for &'_ T {
712     #[inline(always)]
flex_direction(&self) -> FlexDirection713     fn flex_direction(&self) -> FlexDirection {
714         (*self).flex_direction()
715     }
716     #[inline(always)]
flex_wrap(&self) -> FlexWrap717     fn flex_wrap(&self) -> FlexWrap {
718         (*self).flex_wrap()
719     }
720     #[inline(always)]
gap(&self) -> Size<LengthPercentage>721     fn gap(&self) -> Size<LengthPercentage> {
722         (*self).gap()
723     }
724     #[inline(always)]
align_content(&self) -> Option<AlignContent>725     fn align_content(&self) -> Option<AlignContent> {
726         (*self).align_content()
727     }
728     #[inline(always)]
align_items(&self) -> Option<AlignItems>729     fn align_items(&self) -> Option<AlignItems> {
730         (*self).align_items()
731     }
732     #[inline(always)]
justify_content(&self) -> Option<JustifyContent>733     fn justify_content(&self) -> Option<JustifyContent> {
734         (*self).justify_content()
735     }
736 }
737 
738 #[cfg(feature = "flexbox")]
739 impl FlexboxItemStyle for Style {
740     #[inline(always)]
flex_basis(&self) -> Dimension741     fn flex_basis(&self) -> Dimension {
742         self.flex_basis
743     }
744     #[inline(always)]
flex_grow(&self) -> f32745     fn flex_grow(&self) -> f32 {
746         self.flex_grow
747     }
748     #[inline(always)]
flex_shrink(&self) -> f32749     fn flex_shrink(&self) -> f32 {
750         self.flex_shrink
751     }
752     #[inline(always)]
align_self(&self) -> Option<AlignSelf>753     fn align_self(&self) -> Option<AlignSelf> {
754         self.align_self
755     }
756 }
757 
758 #[cfg(feature = "flexbox")]
759 impl<T: FlexboxItemStyle> FlexboxItemStyle for &'_ T {
760     #[inline(always)]
flex_basis(&self) -> Dimension761     fn flex_basis(&self) -> Dimension {
762         (*self).flex_basis()
763     }
764     #[inline(always)]
flex_grow(&self) -> f32765     fn flex_grow(&self) -> f32 {
766         (*self).flex_grow()
767     }
768     #[inline(always)]
flex_shrink(&self) -> f32769     fn flex_shrink(&self) -> f32 {
770         (*self).flex_shrink()
771     }
772     #[inline(always)]
align_self(&self) -> Option<AlignSelf>773     fn align_self(&self) -> Option<AlignSelf> {
774         (*self).align_self()
775     }
776 }
777 
778 #[cfg(feature = "grid")]
779 impl GridContainerStyle for Style {
780     type TemplateTrackList<'a>
781         = &'a [TrackSizingFunction]
782     where
783         Self: 'a;
784     type AutoTrackList<'a>
785         = &'a [NonRepeatedTrackSizingFunction]
786     where
787         Self: 'a;
788 
789     #[inline(always)]
grid_template_rows(&self) -> &[TrackSizingFunction]790     fn grid_template_rows(&self) -> &[TrackSizingFunction] {
791         &self.grid_template_rows
792     }
793     #[inline(always)]
grid_template_columns(&self) -> &[TrackSizingFunction]794     fn grid_template_columns(&self) -> &[TrackSizingFunction] {
795         &self.grid_template_columns
796     }
797     #[inline(always)]
grid_auto_rows(&self) -> &[NonRepeatedTrackSizingFunction]798     fn grid_auto_rows(&self) -> &[NonRepeatedTrackSizingFunction] {
799         &self.grid_auto_rows
800     }
801     #[inline(always)]
grid_auto_columns(&self) -> &[NonRepeatedTrackSizingFunction]802     fn grid_auto_columns(&self) -> &[NonRepeatedTrackSizingFunction] {
803         &self.grid_auto_columns
804     }
805     #[inline(always)]
grid_auto_flow(&self) -> GridAutoFlow806     fn grid_auto_flow(&self) -> GridAutoFlow {
807         self.grid_auto_flow
808     }
809     #[inline(always)]
gap(&self) -> Size<LengthPercentage>810     fn gap(&self) -> Size<LengthPercentage> {
811         self.gap
812     }
813     #[inline(always)]
align_content(&self) -> Option<AlignContent>814     fn align_content(&self) -> Option<AlignContent> {
815         self.align_content
816     }
817     #[inline(always)]
justify_content(&self) -> Option<JustifyContent>818     fn justify_content(&self) -> Option<JustifyContent> {
819         self.justify_content
820     }
821     #[inline(always)]
align_items(&self) -> Option<AlignItems>822     fn align_items(&self) -> Option<AlignItems> {
823         self.align_items
824     }
825     #[inline(always)]
justify_items(&self) -> Option<AlignItems>826     fn justify_items(&self) -> Option<AlignItems> {
827         self.justify_items
828     }
829 }
830 
831 #[cfg(feature = "grid")]
832 impl<T: GridContainerStyle> GridContainerStyle for &'_ T {
833     type TemplateTrackList<'a>
834         = T::TemplateTrackList<'a>
835     where
836         Self: 'a;
837     type AutoTrackList<'a>
838         = T::AutoTrackList<'a>
839     where
840         Self: 'a;
841 
842     #[inline(always)]
grid_template_rows(&self) -> Self::TemplateTrackList<'_>843     fn grid_template_rows(&self) -> Self::TemplateTrackList<'_> {
844         (*self).grid_template_rows()
845     }
846     #[inline(always)]
grid_template_columns(&self) -> Self::TemplateTrackList<'_>847     fn grid_template_columns(&self) -> Self::TemplateTrackList<'_> {
848         (*self).grid_template_columns()
849     }
850     #[inline(always)]
grid_auto_rows(&self) -> Self::AutoTrackList<'_>851     fn grid_auto_rows(&self) -> Self::AutoTrackList<'_> {
852         (*self).grid_auto_rows()
853     }
854     #[inline(always)]
grid_auto_columns(&self) -> Self::AutoTrackList<'_>855     fn grid_auto_columns(&self) -> Self::AutoTrackList<'_> {
856         (*self).grid_auto_columns()
857     }
858     #[inline(always)]
grid_auto_flow(&self) -> GridAutoFlow859     fn grid_auto_flow(&self) -> GridAutoFlow {
860         (*self).grid_auto_flow()
861     }
862     #[inline(always)]
gap(&self) -> Size<LengthPercentage>863     fn gap(&self) -> Size<LengthPercentage> {
864         (*self).gap()
865     }
866     #[inline(always)]
align_content(&self) -> Option<AlignContent>867     fn align_content(&self) -> Option<AlignContent> {
868         (*self).align_content()
869     }
870     #[inline(always)]
justify_content(&self) -> Option<JustifyContent>871     fn justify_content(&self) -> Option<JustifyContent> {
872         (*self).justify_content()
873     }
874     #[inline(always)]
align_items(&self) -> Option<AlignItems>875     fn align_items(&self) -> Option<AlignItems> {
876         (*self).align_items()
877     }
878     #[inline(always)]
justify_items(&self) -> Option<AlignItems>879     fn justify_items(&self) -> Option<AlignItems> {
880         (*self).justify_items()
881     }
882 }
883 
884 #[cfg(feature = "grid")]
885 impl GridItemStyle for &'_ Style {
886     #[inline(always)]
grid_row(&self) -> Line<GridPlacement>887     fn grid_row(&self) -> Line<GridPlacement> {
888         self.grid_row
889     }
890     #[inline(always)]
grid_column(&self) -> Line<GridPlacement>891     fn grid_column(&self) -> Line<GridPlacement> {
892         self.grid_column
893     }
894     #[inline(always)]
align_self(&self) -> Option<AlignSelf>895     fn align_self(&self) -> Option<AlignSelf> {
896         self.align_self
897     }
898     #[inline(always)]
justify_self(&self) -> Option<AlignSelf>899     fn justify_self(&self) -> Option<AlignSelf> {
900         self.justify_self
901     }
902 }
903 
904 #[cfg(feature = "grid")]
905 impl<T: GridItemStyle> GridItemStyle for &'_ T {
906     #[inline(always)]
grid_row(&self) -> Line<GridPlacement>907     fn grid_row(&self) -> Line<GridPlacement> {
908         (*self).grid_row()
909     }
910     #[inline(always)]
grid_column(&self) -> Line<GridPlacement>911     fn grid_column(&self) -> Line<GridPlacement> {
912         (*self).grid_column()
913     }
914     #[inline(always)]
align_self(&self) -> Option<AlignSelf>915     fn align_self(&self) -> Option<AlignSelf> {
916         (*self).align_self()
917     }
918     #[inline(always)]
justify_self(&self) -> Option<AlignSelf>919     fn justify_self(&self) -> Option<AlignSelf> {
920         (*self).justify_self()
921     }
922 }
923 
924 #[cfg(test)]
925 mod tests {
926     use super::Style;
927     use crate::geometry::*;
928 
929     #[test]
defaults_match()930     fn defaults_match() {
931         #[cfg(feature = "grid")]
932         use super::GridPlacement;
933 
934         let old_defaults = Style {
935             display: Default::default(),
936             item_is_table: false,
937             box_sizing: Default::default(),
938             overflow: Default::default(),
939             scrollbar_width: 0.0,
940             position: Default::default(),
941             #[cfg(feature = "flexbox")]
942             flex_direction: Default::default(),
943             #[cfg(feature = "flexbox")]
944             flex_wrap: Default::default(),
945             #[cfg(any(feature = "flexbox", feature = "grid"))]
946             align_items: Default::default(),
947             #[cfg(any(feature = "flexbox", feature = "grid"))]
948             align_self: Default::default(),
949             #[cfg(feature = "grid")]
950             justify_items: Default::default(),
951             #[cfg(feature = "grid")]
952             justify_self: Default::default(),
953             #[cfg(any(feature = "flexbox", feature = "grid"))]
954             align_content: Default::default(),
955             #[cfg(any(feature = "flexbox", feature = "grid"))]
956             justify_content: Default::default(),
957             inset: Rect::auto(),
958             margin: Rect::zero(),
959             padding: Rect::zero(),
960             border: Rect::zero(),
961             gap: Size::zero(),
962             #[cfg(feature = "block_layout")]
963             text_align: Default::default(),
964             #[cfg(feature = "flexbox")]
965             flex_grow: 0.0,
966             #[cfg(feature = "flexbox")]
967             flex_shrink: 1.0,
968             #[cfg(feature = "flexbox")]
969             flex_basis: super::Dimension::Auto,
970             size: Size::auto(),
971             min_size: Size::auto(),
972             max_size: Size::auto(),
973             aspect_ratio: Default::default(),
974             #[cfg(feature = "grid")]
975             grid_template_rows: Default::default(),
976             #[cfg(feature = "grid")]
977             grid_template_columns: Default::default(),
978             #[cfg(feature = "grid")]
979             grid_auto_rows: Default::default(),
980             #[cfg(feature = "grid")]
981             grid_auto_columns: Default::default(),
982             #[cfg(feature = "grid")]
983             grid_auto_flow: Default::default(),
984             #[cfg(feature = "grid")]
985             grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
986             #[cfg(feature = "grid")]
987             grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
988         };
989 
990         assert_eq!(Style::DEFAULT, Style::default());
991         assert_eq!(Style::DEFAULT, old_defaults);
992     }
993 
994     // NOTE: Please feel free the update the sizes in this test as required. This test is here to prevent unintentional size changes
995     // and to serve as accurate up-to-date documentation on the sizes.
996     #[test]
style_sizes()997     fn style_sizes() {
998         use super::*;
999 
1000         fn assert_type_size<T>(expected_size: usize) {
1001             let name = ::core::any::type_name::<T>();
1002             let name = name.replace("taffy::geometry::", "");
1003             let name = name.replace("taffy::style::dimension::", "");
1004             let name = name.replace("taffy::style::alignment::", "");
1005             let name = name.replace("taffy::style::flex::", "");
1006             let name = name.replace("taffy::style::grid::", "");
1007 
1008             assert_eq!(
1009                 ::core::mem::size_of::<T>(),
1010                 expected_size,
1011                 "Expected {} for be {} byte(s) but it was {} byte(s)",
1012                 name,
1013                 expected_size,
1014                 ::core::mem::size_of::<T>(),
1015             );
1016         }
1017 
1018         // Display and Position
1019         assert_type_size::<Display>(1);
1020         assert_type_size::<BoxSizing>(1);
1021         assert_type_size::<Position>(1);
1022         assert_type_size::<Overflow>(1);
1023 
1024         // Dimensions and aggregations of Dimensions
1025         assert_type_size::<f32>(4);
1026         assert_type_size::<LengthPercentage>(8);
1027         assert_type_size::<LengthPercentageAuto>(8);
1028         assert_type_size::<Dimension>(8);
1029         assert_type_size::<Size<LengthPercentage>>(16);
1030         assert_type_size::<Size<LengthPercentageAuto>>(16);
1031         assert_type_size::<Size<Dimension>>(16);
1032         assert_type_size::<Rect<LengthPercentage>>(32);
1033         assert_type_size::<Rect<LengthPercentageAuto>>(32);
1034         assert_type_size::<Rect<Dimension>>(32);
1035 
1036         // Alignment
1037         assert_type_size::<AlignContent>(1);
1038         assert_type_size::<AlignItems>(1);
1039         assert_type_size::<Option<AlignItems>>(1);
1040 
1041         // Flexbox Container
1042         assert_type_size::<FlexDirection>(1);
1043         assert_type_size::<FlexWrap>(1);
1044 
1045         // CSS Grid Container
1046         assert_type_size::<GridAutoFlow>(1);
1047         assert_type_size::<MinTrackSizingFunction>(8);
1048         assert_type_size::<MaxTrackSizingFunction>(12);
1049         assert_type_size::<NonRepeatedTrackSizingFunction>(20);
1050         assert_type_size::<TrackSizingFunction>(32);
1051         assert_type_size::<Vec<NonRepeatedTrackSizingFunction>>(24);
1052         assert_type_size::<Vec<TrackSizingFunction>>(24);
1053 
1054         // CSS Grid Item
1055         assert_type_size::<GridPlacement>(4);
1056         assert_type_size::<Line<GridPlacement>>(8);
1057 
1058         // Overall
1059         assert_type_size::<Style>(352);
1060     }
1061 }
1062