gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 229Rust 8TOML 3CSS 1310 Definiciones

⎇ 9e53f03adea2b770d68954e404d2fa407dfc7d40 src/layout.rs Rust · 154 líneas · 5.4 KB Historia Quién tocó qué crudo

Layout algorithm decoupling, Sizing Constraints & Perf Improvements (#246) ba4cd3c3b · Nico Burns ·

1//! Final and cached data structures that represent the high-level UI layout
2
3use crate::geometry::{Point, Size};
4use crate::sys::abs;
5
6/// Whether we are performing a full layout, or we merely need to size the node
7#[derive(Copy, Clone, Debug, PartialEq, Eq)]
8pub enum RunMode {
9    /// A full layout for this node and all children should be computed
10    PeformLayout,
11    /// The layout algorithm should be executed such that an accurate container size for the node can be determined.
12    /// Layout steps that aren't necessary for determining the container size of the current node can be skipped.
13    ComputeSize,
14}
15
16/// Whether styles should be taken into account when computing size
17#[derive(Copy, Clone, Debug, PartialEq, Eq)]
18pub enum SizingMode {
19    /// Only content contributions should be taken into account
20    ContentSize,
21    /// Inherent size styles should be taken into account in addition to content contributions
22    InherentSize,
23}
24
25/// The amount of space available to a node in a given axis
26#[derive(Copy, Clone, Debug, PartialEq)]
27pub enum AvailableSpace {
28    /// The amount of space available is the specified number of pixels
29    Definite(f32),
30    /// The amount of space available is indefinite and the node should be laid out under a min-content constraint
31    MinContent,
32    /// The amount of space available is indefinite and the node should be laid out under a max-content constraint
33    MaxContent,
34}
35
36impl AvailableSpace {
37    /// A definite available space of zero
38    pub const ZERO: AvailableSpace = AvailableSpace::Definite(0.0);
39
40    /// Returns true for definite values, else false
41    pub fn is_definite(self) -> bool {
42        matches!(self, AvailableSpace::Definite(_))
43    }
44
45    /// Convert to Option
46    /// Definite values become Some(value). Contraints become None.
47    pub fn into_option(self) -> Option<f32> {
48        match self {
49            AvailableSpace::Definite(value) => Some(value),
50            _ => None,
51        }
52    }
53
54    /// Return the definite value or a default value
55    pub fn unwrap_or(self, default: f32) -> f32 {
56        self.into_option().unwrap_or(default)
57    }
58
59    /// Return the definite value. Panic is the value is not definite.
60    #[track_caller]
61    pub fn unwrap(self) -> f32 {
62        self.into_option().unwrap()
63    }
64
65    /// If passed value is Some then return AvailableSpace::Definite containing that value, else return self
66    pub fn maybe_set(self, value: Option<f32>) -> AvailableSpace {
67        match value {
68            Some(value) => AvailableSpace::Definite(value),
69            None => self,
70        }
71    }
72
73    /// Compare equality with another AvailableSpace, treating definite values
74    /// that are within f32::EPSILON of each other as equal
75    pub fn is_roughly_equal(self, other: AvailableSpace) -> bool {
76        use AvailableSpace::*;
77        match (self, other) {
78            (Definite(a), Definite(b)) => abs(a - b) < f32::EPSILON,
79            (MinContent, MinContent) => true,
80            (MaxContent, MaxContent) => true,
81            _ => false,
82        }
83    }
84}
85
86impl From<f32> for AvailableSpace {
87    fn from(value: f32) -> Self {
88        Self::Definite(value)
89    }
90}
91
92impl Size<AvailableSpace> {
93    /// A Size<AvailableSpace> containing a MaxContent constraint in both dimensions
94    pub const MAX_CONTENT: Size<AvailableSpace> =
95        Size { width: AvailableSpace::MaxContent, height: AvailableSpace::MaxContent };
96
97    /// A Size<AvailableSpace> containing a MinContent constraint in both dimensions
98    pub const MIN_CONTENT: Size<AvailableSpace> =
99        Size { width: AvailableSpace::MinContent, height: AvailableSpace::MinContent };
100
101    /// Convert Size<AvailableSpace> into Size<Option<f32>>
102    pub fn as_options(self) -> Size<Option<f32>> {
103        Size { width: self.width.into_option(), height: self.height.into_option() }
104    }
105}
106
107/// The final result of a layout algorithm for a single [`Node`](crate::node::Node).
108#[derive(Copy, Debug, Clone)]
109pub struct Layout {
110    /// The relative ordering of the node
111    ///
112    /// Nodes with a higher order should be rendered on top of those with a lower order.
113    /// This is effectively a topological sort of each tree.
114    pub order: u32,
115    /// The width and height of the node
116    pub size: Size<f32>,
117    /// The bottom-left corner of the node
118    pub location: Point<f32>,
119}
120
121impl Layout {
122    /// Creates a new zero-[`Layout`].
123    ///
124    /// The Zero-layout has size and location set to ZERO.
125    /// The `order` value of this layout is set to the minimum value of 0.
126    /// This means it should be rendered below all other [`Layout`]s.
127    #[must_use]
128    pub const fn new() -> Self {
129        Self { order: 0, size: Size::ZERO, location: Point::ZERO }
130    }
131
132    /// Creates a new zero-[`Layout`] with the supplied `order` value.
133    ///
134    /// Nodes with a higher order should be rendered on top of those with a lower order.
135    /// The Zero-layout has size and location set to ZERO.
136    #[must_use]
137    pub const fn with_order(order: u32) -> Self {
138        Self { order, size: Size::ZERO, location: Point::ZERO }
139    }
140}
141
142/// Cached intermediate layout results
143#[derive(Debug, Clone, Copy)]
144pub struct Cache {
145    /// The initial cached size of the node itself
146    pub(crate) known_dimensions: Size<Option<f32>>,
147    /// The initial cached size of the parent's node
148    pub(crate) available_space: Size<AvailableSpace>,
149    /// Whether or not layout should be recomputed
150    pub(crate) run_mode: RunMode,
151
152    /// The cached size of the item
153    pub(crate) cached_size: Size<f32>,
154}