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