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