tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 790HTML 742Markdown 12TOML 62540 Definiciones

⎇ b1ea6794519524c818057af327f78c09ff379453 src/geometry.rs Rust · 258 líneas · 7.7 KB Historia Quién tocó qué crudo

Replace Number type with a simpler Option<f32> (#144) b1ea67945 · Alice Cecile ·

1//! Geometric primitives useful for layout
2
3use crate::style::{Dimension, FlexDirection};
4use core::ops::Add;
5
6/// An axis-aligned UI rectangle
7#[derive(Debug, Copy, Clone, PartialEq)]
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9#[cfg_attr(feature = "serde", serde(default))]
10pub struct Rect<T> {
11    /// This can represent either the x-coordinate of the starting edge,
12    /// or the amount of padding on the starting side.
13    ///
14    /// The starting edge is the left edge when working with LTR text,
15    /// and the right edge when working with RTL text.
16    pub start: T,
17    /// This can represent either the x-coordinate of the ending edge,
18    /// or the amount of padding on the ending side.
19    ///
20    /// The ending edge is the right edge when working with LTR text,
21    /// and the left edge when working with RTL text.
22    pub end: T,
23    /// This can represent either the y-coordinate of the top edge,
24    /// or the amount of padding on the top side.
25    pub top: T,
26    /// This can represent either the y-coordinate of the bottom edge,
27    /// or the amount of padding on the bottom side.
28    pub bottom: T,
29}
30
31impl<T> Rect<T> {
32    /// Applies the function `f` to all four sides of the [`Rect`]
33    ///
34    /// This is used to transform a `Rect<T>` into a `Rect<R>`.
35    pub(crate) fn map<R, F>(self, f: F) -> Rect<R>
36    where
37        F: Fn(T) -> R,
38    {
39        Rect { start: f(self.start), end: f(self.end), top: f(self.top), bottom: f(self.bottom) }
40    }
41
42    /// Applies the function `f` to all four sides of the rect
43    ///
44    /// When applied to the left and right sides, the width is used
45    /// as the second parameter of `f`.
46    /// When applied to the top or bottom sides, the height is used instead.
47    pub(crate) fn zip_size<R, F, U>(self, size: Size<U>, f: F) -> Rect<R>
48    where
49        F: Fn(T, U) -> R,
50        U: Copy,
51    {
52        Rect {
53            start: f(self.start, size.width),
54            end: f(self.end, size.width),
55            top: f(self.top, size.height),
56            bottom: f(self.bottom, size.height),
57        }
58    }
59}
60
61impl<T> Rect<T>
62where
63    T: Add<Output = T> + Copy + Clone,
64{
65    /// The sum of [`Rect.start`](Rect) and [`Rect.end`](Rect)
66    ///
67    /// This is typically used when computing total padding.
68    ///
69    /// **NOTE:** this is *not* the width of the rectangle.
70    pub(crate) fn horizontal_axis_sum(&self) -> T {
71        self.start + self.end
72    }
73
74    /// The sum of [`Rect.top`](Rect) and [`Rect.bottom`](Rect)
75    ///
76    /// This is typically used when computing total padding.
77    ///
78    /// **NOTE:** this is *not* the height of the rectangle.
79    pub(crate) fn vertical_axis_sum(&self) -> T {
80        self.top + self.bottom
81    }
82
83    /// The sum of the two fields of the [`Rect`] representing the main axis.
84    ///
85    /// This is typically used when computing total padding.
86    ///
87    /// If the [`FlexDirection`] is [`FlexDirection::Row`] or [`FlexDirection::RowReverse`], this is [`Rect::horizontal`].
88    /// Otherwise, this is [`Rect::vertical`].
89    pub(crate) fn main_axis_sum(&self, direction: FlexDirection) -> T {
90        if direction.is_row() {
91            self.horizontal_axis_sum()
92        } else {
93            self.vertical_axis_sum()
94        }
95    }
96
97    /// The sum of the two fields of the [`Rect`] representing the cross axis.
98    ///
99    /// If the [`FlexDirection`] is [`FlexDirection::Row`] or [`FlexDirection::RowReverse`], this is [`Rect::vertical`].
100    /// Otherwise, this is [`Rect::horizontal`].
101    pub(crate) fn cross_axis_sum(&self, direction: FlexDirection) -> T {
102        if direction.is_row() {
103            self.vertical_axis_sum()
104        } else {
105            self.horizontal_axis_sum()
106        }
107    }
108}
109
110impl<T> Rect<T>
111where
112    T: Copy + Clone,
113{
114    /// The `start` or `top` value of the [`Rect`], from the perspective of the main layout axis
115    pub(crate) fn main_start(&self, direction: FlexDirection) -> T {
116        if direction.is_row() {
117            self.start
118        } else {
119            self.top
120        }
121    }
122
123    /// The `end` or `bottom` value of the [`Rect`], from the perspective of the main layout axis
124    pub(crate) fn main_end(&self, direction: FlexDirection) -> T {
125        if direction.is_row() {
126            self.end
127        } else {
128            self.bottom
129        }
130    }
131
132    /// The `start` or `top` value of the [`Rect`], from the perspective of the cross layout axis
133    pub(crate) fn cross_start(&self, direction: FlexDirection) -> T {
134        if direction.is_row() {
135            self.top
136        } else {
137            self.start
138        }
139    }
140
141    /// The `end` or `bottom` value of the [`Rect`], from the perspective of the main layout axis
142    pub(crate) fn cross_end(&self, direction: FlexDirection) -> T {
143        if direction.is_row() {
144            self.bottom
145        } else {
146            self.end
147        }
148    }
149}
150
151/// The width and height of a [`Rect`]
152#[derive(Debug, Copy, Clone, PartialEq)]
153#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
154#[cfg_attr(feature = "serde", serde(default))]
155pub struct Size<T> {
156    /// The x extent of the rectangle
157    pub width: T,
158    /// The y extent of the rectangle
159    pub height: T,
160}
161
162impl Size<()> {
163    /// Generates a `Size<Option<f32>>` with undefined width and height
164    #[must_use]
165    pub fn undefined() -> Size<Option<f32>> {
166        Size { width: None, height: None }
167    }
168}
169
170impl<T> Size<T> {
171    /// Applies the function `f` to both the width and height
172    ///
173    /// This is used to transform a `Rect<T>` into a `Rect<R>`.
174    pub fn map<R, F>(self, f: F) -> Size<R>
175    where
176        F: Fn(T) -> R,
177    {
178        Size { width: f(self.width), height: f(self.height) }
179    }
180
181    /// Sets the extent of the main layout axis
182    ///
183    /// Whether this is the width or height depends on the `direction` provided
184    pub(crate) fn set_main(&mut self, direction: FlexDirection, value: T) {
185        if direction.is_row() {
186            self.width = value
187        } else {
188            self.height = value
189        }
190    }
191
192    /// Sets the extent of the cross layout axis
193    ///
194    /// Whether this is the width or height depends on the `direction` provided
195    pub(crate) fn set_cross(&mut self, direction: FlexDirection, value: T) {
196        if direction.is_row() {
197            self.height = value
198        } else {
199            self.width = value
200        }
201    }
202
203    /// Gets the extent of the main layout axis
204    ///
205    /// Whether this is the width or height depends on the `direction` provided
206    pub(crate) fn main(self, direction: FlexDirection) -> T {
207        if direction.is_row() {
208            self.width
209        } else {
210            self.height
211        }
212    }
213
214    /// Gets the extent of the cross layout axis
215    ///
216    /// Whether this is the width or height depends on the `direction` provided
217    pub(crate) fn cross(self, direction: FlexDirection) -> T {
218        if direction.is_row() {
219            self.height
220        } else {
221            self.width
222        }
223    }
224}
225
226impl Size<f32> {
227    /// A [`Size`] with zero width and height
228    #[must_use]
229    pub fn zero() -> Self {
230        Self { width: 0.0, height: 0.0 }
231    }
232}
233
234impl Size<Dimension> {
235    /// Converts any `parent`-relative values for size into an absolute size
236    pub(crate) fn resolve(&self, parent: Size<Option<f32>>) -> Size<Option<f32>> {
237        Size { width: self.width.resolve(parent.width), height: self.height.resolve(parent.height) }
238    }
239}
240
241/// A 2-dimensional coordinate.
242///
243/// When used in association with a [`Rect`], represents the bottom-left corner.
244#[derive(Debug, Copy, Clone, PartialEq)]
245pub struct Point<T> {
246    /// The x-coordinate
247    pub x: T,
248    /// The y-coordinate
249    pub y: T,
250}
251
252impl Point<f32> {
253    /// A [`Point`] with values (0,0), representing the origin
254    #[must_use]
255    pub fn zero() -> Self {
256        Self { x: 0.0, y: 0.0 }
257    }
258}