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