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