gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5364Rust 86Markdown 12TOML 91841 Definitions

⎇ 80cc4a0802770b70e83e28361e891c522f966f5b src/style/dimension.rs Rust · 284 lines · 9.6 KB History Who touched what raw

Add inherent method constructors to style dimension types (#788) 80cc4a080 · Nico Burns ·

1//! Style types for representing lengths / sizes
2use super::CompactLength;
3use crate::geometry::Rect;
4use crate::style_helpers::{FromLength, FromPercent, TaffyAuto, TaffyZero};
5
6/// A unit of linear measurement
7///
8/// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`](crate::geometry::Size).
9#[derive(Copy, Clone, PartialEq, Debug)]
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11pub struct LengthPercentage(pub(crate) CompactLength);
12impl TaffyZero for LengthPercentage {
13    const ZERO: Self = Self(CompactLength::ZERO);
14}
15impl FromLength for LengthPercentage {
16    fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
17        Self::length(value.into())
18    }
19}
20impl FromPercent for LengthPercentage {
21    fn from_percent<Input: Into<f32> + Copy>(value: Input) -> Self {
22        Self::percent(value.into())
23    }
24}
25impl LengthPercentage {
26    /// An absolute length in some abstract units. Users of Taffy may define what they correspond
27    /// to in their application (pixels, logical pixels, mm, etc) as they see fit.
28    #[inline(always)]
29    pub const fn length(val: f32) -> Self {
30        Self(CompactLength::length(val))
31    }
32
33    /// A percentage length relative to the size of the containing block.
34    ///
35    /// **NOTE: percentages are represented as a f32 value in the range [0.0, 1.0] NOT the range [0.0, 100.0]**
36    #[inline(always)]
37    pub const fn percent(val: f32) -> Self {
38        Self(CompactLength::percent(val))
39    }
40
41    /// A `calc()` value. The value passed here is treated as an opaque handle to
42    /// the actual calc representation and may be a pointer, index, etc.
43    ///
44    /// The low 3 bits are used as a tag value and will be returned as 0.
45    #[inline]
46    pub fn calc(ptr: *const ()) -> Self {
47        Self(CompactLength::calc(ptr))
48    }
49
50    /// Create a LengthPercentage from a raw `CompactLength`.
51    /// # Safety
52    /// CompactLength must represent a valid variant for LengthPercentage
53    #[allow(unsafe_code)]
54    pub unsafe fn from_raw(val: CompactLength) -> Self {
55        Self(val)
56    }
57
58    /// Get the underlying `CompactLength` representation of the value
59    pub fn into_raw(self) -> CompactLength {
60        self.0
61    }
62}
63
64/// A unit of linear measurement
65///
66/// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`](crate::geometry::Size).
67#[derive(Copy, Clone, PartialEq, Debug)]
68#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
69pub struct LengthPercentageAuto(pub(crate) CompactLength);
70impl TaffyZero for LengthPercentageAuto {
71    const ZERO: Self = Self(CompactLength::ZERO);
72}
73impl TaffyAuto for LengthPercentageAuto {
74    const AUTO: Self = Self(CompactLength::AUTO);
75}
76impl FromLength for LengthPercentageAuto {
77    fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
78        Self::length(value.into())
79    }
80}
81impl FromPercent for LengthPercentageAuto {
82    fn from_percent<Input: Into<f32> + Copy>(value: Input) -> Self {
83        Self::percent(value.into())
84    }
85}
86impl From<LengthPercentage> for LengthPercentageAuto {
87    fn from(input: LengthPercentage) -> Self {
88        Self(input.0)
89    }
90}
91
92impl LengthPercentageAuto {
93    /// An absolute length in some abstract units. Users of Taffy may define what they correspond
94    /// to in their application (pixels, logical pixels, mm, etc) as they see fit.
95    #[inline(always)]
96    pub const fn length(val: f32) -> Self {
97        Self(CompactLength::length(val))
98    }
99
100    /// A percentage length relative to the size of the containing block.
101    ///
102    /// **NOTE: percentages are represented as a f32 value in the range [0.0, 1.0] NOT the range [0.0, 100.0]**
103    #[inline(always)]
104    pub const fn percent(val: f32) -> Self {
105        Self(CompactLength::percent(val))
106    }
107
108    /// The dimension should be automatically computed according to algorithm-specific rules
109    /// regarding the default size of boxes.
110    #[inline(always)]
111    pub const fn auto() -> Self {
112        Self(CompactLength::auto())
113    }
114
115    /// A `calc()` value. The value passed here is treated as an opaque handle to
116    /// the actual calc representation and may be a pointer, index, etc.
117    ///
118    /// The low 3 bits are used as a tag value and will be returned as 0.
119    #[inline]
120    pub fn calc(ptr: *const ()) -> Self {
121        Self(CompactLength::calc(ptr))
122    }
123
124    /// Create a LengthPercentageAuto from a raw `CompactLength`.
125    /// # Safety
126    /// CompactLength must represent a valid variant for LengthPercentageAuto
127    #[allow(unsafe_code)]
128    pub unsafe fn from_raw(val: CompactLength) -> Self {
129        Self(val)
130    }
131
132    /// Get the underlying `CompactLength` representation of the value
133    pub fn into_raw(self) -> CompactLength {
134        self.0
135    }
136
137    /// Returns:
138    ///   - Some(length) for Length variants
139    ///   - Some(resolved) using the provided context for Percent variants
140    ///   - None for Auto variants
141    #[inline(always)]
142    pub fn resolve_to_option(self, context: f32, calc_resolver: impl Fn(u64, f32) -> f32) -> Option<f32> {
143        match self.0.tag() {
144            CompactLength::LENGTH_TAG => Some(self.0.value()),
145            CompactLength::PERCENT_TAG => Some(context * self.0.value()),
146            CompactLength::AUTO_TAG => None,
147            _ if self.0.is_calc() => Some(calc_resolver(self.0.calc_value(), context)),
148            _ => unreachable!("LengthPercentageAuto values cannot be constructed with other tags"),
149        }
150    }
151
152    /// Returns true if value is LengthPercentageAuto::Auto
153    #[inline(always)]
154    pub fn is_auto(self) -> bool {
155        self.0.is_auto()
156    }
157}
158
159/// A unit of linear measurement
160///
161/// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`](crate::geometry::Size).
162#[derive(Copy, Clone, PartialEq, Debug)]
163#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
164pub struct Dimension(pub(crate) CompactLength);
165impl TaffyZero for Dimension {
166    const ZERO: Self = Self(CompactLength::ZERO);
167}
168impl TaffyAuto for Dimension {
169    const AUTO: Self = Self(CompactLength::AUTO);
170}
171impl FromLength for Dimension {
172    fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
173        Self::length(value.into())
174    }
175}
176impl FromPercent for Dimension {
177    fn from_percent<Input: Into<f32> + Copy>(value: Input) -> Self {
178        Self::percent(value.into())
179    }
180}
181impl From<LengthPercentage> for Dimension {
182    fn from(input: LengthPercentage) -> Self {
183        Self(input.0)
184    }
185}
186impl From<LengthPercentageAuto> for Dimension {
187    fn from(input: LengthPercentageAuto) -> Self {
188        Self(input.0)
189    }
190}
191
192impl Dimension {
193    /// An absolute length in some abstract units. Users of Taffy may define what they correspond
194    /// to in their application (pixels, logical pixels, mm, etc) as they see fit.
195    #[inline(always)]
196    pub const fn length(val: f32) -> Self {
197        Self(CompactLength::length(val))
198    }
199
200    /// A percentage length relative to the size of the containing block.
201    ///
202    /// **NOTE: percentages are represented as a f32 value in the range [0.0, 1.0] NOT the range [0.0, 100.0]**
203    #[inline(always)]
204    pub const fn percent(val: f32) -> Self {
205        Self(CompactLength::percent(val))
206    }
207
208    /// The dimension should be automatically computed according to algorithm-specific rules
209    /// regarding the default size of boxes.
210    #[inline(always)]
211    pub const fn auto() -> Self {
212        Self(CompactLength::auto())
213    }
214
215    /// A `calc()` value. The value passed here is treated as an opaque handle to
216    /// the actual calc representation and may be a pointer, index, etc.
217    ///
218    /// The low 3 bits are used as a tag value and will be returned as 0.
219    #[inline]
220    pub fn calc(ptr: *const ()) -> Self {
221        Self(CompactLength::calc(ptr))
222    }
223
224    /// Create a LengthPercentageAuto from a raw `CompactLength`.
225    /// # Safety
226    /// CompactLength must represent a valid variant for LengthPercentageAuto
227    #[allow(unsafe_code)]
228    pub unsafe fn from_raw(val: CompactLength) -> Self {
229        Self(val)
230    }
231
232    /// Get the underlying `CompactLength` representation of the value
233    pub fn into_raw(self) -> CompactLength {
234        self.0
235    }
236
237    /// Get Length value if value is Length variant
238    #[cfg(feature = "grid")]
239    pub fn into_option(self) -> Option<f32> {
240        match self.0.tag() {
241            CompactLength::LENGTH_TAG => Some(self.0.value()),
242            _ => None,
243        }
244    }
245    /// Returns true if value is Auto
246    #[inline(always)]
247    pub fn is_auto(self) -> bool {
248        self.0.is_auto()
249    }
250
251    /// Get the raw `CompactLength` tag
252    pub fn tag(self) -> u64 {
253        self.0.tag()
254    }
255
256    /// Get the raw `CompactLength` value for non-calc variants that have a numeric parameter
257    pub fn value(self) -> f32 {
258        self.0.value()
259    }
260}
261
262impl Rect<Dimension> {
263    /// Create a new Rect with length values
264    #[must_use]
265    pub const fn from_length(start: f32, end: f32, top: f32, bottom: f32) -> Self {
266        Rect {
267            left: Dimension(CompactLength::length(start)),
268            right: Dimension(CompactLength::length(end)),
269            top: Dimension(CompactLength::length(top)),
270            bottom: Dimension(CompactLength::length(bottom)),
271        }
272    }
273
274    /// Create a new Rect with percentage values
275    #[must_use]
276    pub const fn from_percent(start: f32, end: f32, top: f32, bottom: f32) -> Self {
277        Rect {
278            left: Dimension(CompactLength::percent(start)),
279            right: Dimension(CompactLength::percent(end)),
280            top: Dimension(CompactLength::percent(top)),
281            bottom: Dimension(CompactLength::percent(bottom)),
282        }
283    }
284}