geometry.rs

  1use bytemuck::{Pod, Zeroable};
  2use core::fmt::Debug;
  3use derive_more::{Add, AddAssign, Div, Mul, Sub, SubAssign};
  4use refineable::Refineable;
  5use std::ops::{Add, AddAssign, Mul, Sub, SubAssign};
  6
  7#[derive(
  8    Refineable, Default, Add, AddAssign, Sub, SubAssign, Mul, Div, Copy, Debug, PartialEq, Eq, Hash,
  9)]
 10#[refineable(debug)]
 11#[repr(C)]
 12pub struct Point<T: Clone + Debug> {
 13    pub x: T,
 14    pub y: T,
 15}
 16
 17pub fn point<T: Clone + Debug>(x: T, y: T) -> Point<T> {
 18    Point { x, y }
 19}
 20
 21impl<T: Clone + Debug> Point<T> {
 22    pub fn new(x: T, y: T) -> Self {
 23        Self { x, y }
 24    }
 25
 26    pub fn map<U: Clone + Debug, F: Fn(T) -> U>(&self, f: F) -> Point<U> {
 27        Point {
 28            x: f(self.x.clone()),
 29            y: f(self.y.clone()),
 30        }
 31    }
 32}
 33
 34impl<T: Clone + Debug + Sub<Output = T>> SubAssign<Size<T>> for Point<T> {
 35    fn sub_assign(&mut self, rhs: Size<T>) {
 36        self.x = self.x.clone() - rhs.width;
 37        self.y = self.y.clone() - rhs.height;
 38    }
 39}
 40
 41impl<T: Clone + Debug + Add<Output = T> + Copy> AddAssign<T> for Point<T> {
 42    fn add_assign(&mut self, rhs: T) {
 43        self.x = self.x.clone() + rhs;
 44        self.y = self.y.clone() + rhs;
 45    }
 46}
 47
 48impl<T: Clone + Debug + std::cmp::PartialOrd> Point<T> {
 49    pub fn max(&self, other: &Self) -> Self {
 50        Point {
 51            x: if self.x >= other.x {
 52                self.x.clone()
 53            } else {
 54                other.x.clone()
 55            },
 56            y: if self.y >= other.y {
 57                self.y.clone()
 58            } else {
 59                other.y.clone()
 60            },
 61        }
 62    }
 63}
 64
 65impl<T: Clone + Debug> Clone for Point<T> {
 66    fn clone(&self) -> Self {
 67        Self {
 68            x: self.x.clone(),
 69            y: self.y.clone(),
 70        }
 71    }
 72}
 73
 74unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Point<T> {}
 75unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Point<T> {}
 76
 77#[derive(Refineable, Default, Clone, Copy, Debug, PartialEq)]
 78#[refineable(debug)]
 79#[repr(C)]
 80pub struct Size<T: Clone + Debug> {
 81    pub width: T,
 82    pub height: T,
 83}
 84
 85unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Size<T> {}
 86unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Size<T> {}
 87
 88pub fn size<T: Clone + Debug>(width: T, height: T) -> Size<T> {
 89    Size { width, height }
 90}
 91
 92impl<T: Clone + Debug> Size<T> {
 93    pub fn map<U: Clone + Debug, F: Fn(T) -> U>(&self, f: F) -> Size<U> {
 94        Size {
 95            width: f(self.width.clone()),
 96            height: f(self.height.clone()),
 97        }
 98    }
 99}
100
101impl From<Size<Option<Pixels>>> for Size<Option<f32>> {
102    fn from(val: Size<Option<Pixels>>) -> Self {
103        Size {
104            width: val.width.map(|p| p.0 as f32),
105            height: val.height.map(|p| p.0 as f32),
106        }
107    }
108}
109
110impl Size<Length> {
111    pub fn full() -> Self {
112        Self {
113            width: relative(1.).into(),
114            height: relative(1.).into(),
115        }
116    }
117}
118
119impl Size<DefiniteLength> {
120    pub fn zero() -> Self {
121        Self {
122            width: px(0.).into(),
123            height: px(0.).into(),
124        }
125    }
126}
127
128impl Size<Length> {
129    pub fn auto() -> Self {
130        Self {
131            width: Length::Auto,
132            height: Length::Auto,
133        }
134    }
135}
136
137#[derive(Refineable, Clone, Default, Debug, PartialEq)]
138#[refineable(debug)]
139#[repr(C)]
140pub struct Bounds<T: Clone + Debug> {
141    pub origin: Point<T>,
142    pub size: Size<T>,
143}
144
145unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Bounds<T> {}
146unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Bounds<T> {}
147
148impl<T: Clone + Debug + Copy + Add<T, Output = T>> Bounds<T> {
149    pub fn upper_right(&self) -> Point<T> {
150        Point {
151            x: self.origin.x + self.size.width,
152            y: self.origin.y,
153        }
154    }
155
156    pub fn lower_right(&self) -> Point<T> {
157        Point {
158            x: self.origin.x + self.size.width,
159            y: self.origin.y + self.size.height,
160        }
161    }
162}
163
164impl<T: Clone + Debug + Copy + PartialOrd + Add<T, Output = T>> Bounds<T> {
165    pub fn contains_point(&self, point: Point<T>) -> bool {
166        point.x >= self.origin.x
167            && point.x <= self.origin.x + self.size.width
168            && point.y >= self.origin.y
169            && point.y <= self.origin.y + self.size.height
170    }
171}
172
173impl<T: Clone + Debug + Copy> Copy for Bounds<T> {}
174
175#[derive(Refineable, Clone, Default, Debug)]
176#[refineable(debug)]
177#[repr(C)]
178pub struct Edges<T: Clone + Debug> {
179    pub top: T,
180    pub right: T,
181    pub bottom: T,
182    pub left: T,
183}
184
185impl<T: Clone + Debug + Copy> Copy for Edges<T> {}
186
187unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Edges<T> {}
188
189unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Edges<T> {}
190
191impl Edges<Length> {
192    pub fn auto() -> Self {
193        Self {
194            top: Length::Auto,
195            right: Length::Auto,
196            bottom: Length::Auto,
197            left: Length::Auto,
198        }
199    }
200
201    pub fn zero() -> Self {
202        Self {
203            top: px(0.).into(),
204            right: px(0.).into(),
205            bottom: px(0.).into(),
206            left: px(0.).into(),
207        }
208    }
209}
210
211impl Edges<DefiniteLength> {
212    pub fn zero() -> Self {
213        Self {
214            top: px(0.).into(),
215            right: px(0.).into(),
216            bottom: px(0.).into(),
217            left: px(0.).into(),
218        }
219    }
220}
221
222impl Edges<AbsoluteLength> {
223    pub fn zero() -> Self {
224        Self {
225            top: px(0.).into(),
226            right: px(0.).into(),
227            bottom: px(0.).into(),
228            left: px(0.).into(),
229        }
230    }
231
232    pub fn to_pixels(&self, rem_size: Pixels) -> Edges<Pixels> {
233        Edges {
234            top: self.top.to_pixels(rem_size),
235            right: self.right.to_pixels(rem_size),
236            bottom: self.bottom.to_pixels(rem_size),
237            left: self.left.to_pixels(rem_size),
238        }
239    }
240}
241
242impl Edges<Pixels> {
243    pub fn is_empty(&self) -> bool {
244        self.top == px(0.) && self.right == px(0.) && self.bottom == px(0.) && self.left == px(0.)
245    }
246}
247
248#[derive(Refineable, Clone, Default, Debug)]
249#[refineable(debug)]
250#[repr(C)]
251pub struct Corners<T: Clone + Debug> {
252    pub top_left: T,
253    pub top_right: T,
254    pub bottom_right: T,
255    pub bottom_left: T,
256}
257
258impl<T: Clone + Debug + Copy> Copy for Corners<T> {}
259
260unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Corners<T> {}
261
262unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Corners<T> {}
263
264#[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd)]
265#[repr(transparent)]
266pub struct Pixels(pub(crate) f32);
267
268#[derive(
269    Clone, Copy, Debug, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd,
270)]
271#[repr(transparent)]
272pub struct DevicePixels(pub(crate) u32);
273
274impl From<DevicePixels> for u32 {
275    fn from(device_pixels: DevicePixels) -> Self {
276        device_pixels.0
277    }
278}
279
280impl Pixels {
281    pub fn round(&self) -> Self {
282        Self(self.0.round())
283    }
284
285    pub fn to_device_pixels(&self, scale: f32) -> DevicePixels {
286        DevicePixels((self.0 * scale).ceil() as u32)
287    }
288}
289
290impl Mul<f32> for Pixels {
291    type Output = Pixels;
292
293    fn mul(self, other: f32) -> Pixels {
294        Pixels(self.0 * other)
295    }
296}
297
298impl Mul<Pixels> for Pixels {
299    type Output = Pixels;
300
301    fn mul(self, rhs: Pixels) -> Self::Output {
302        Pixels(self.0 * rhs.0)
303    }
304}
305
306impl Eq for Pixels {}
307
308impl Ord for Pixels {
309    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
310        self.0.partial_cmp(&other.0).unwrap()
311    }
312}
313
314impl std::hash::Hash for Pixels {
315    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
316        self.0.to_bits().hash(state);
317    }
318}
319
320impl From<f64> for Pixels {
321    fn from(val: f64) -> Self {
322        Pixels(val as f32)
323    }
324}
325
326impl From<f32> for Pixels {
327    fn from(val: f32) -> Self {
328        Pixels(val)
329    }
330}
331
332unsafe impl bytemuck::Pod for Pixels {}
333unsafe impl bytemuck::Zeroable for Pixels {}
334
335impl Debug for Pixels {
336    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
337        write!(f, "{} px", self.0)
338    }
339}
340
341impl From<Pixels> for f32 {
342    fn from(pixels: Pixels) -> Self {
343        pixels.0
344    }
345}
346
347impl From<&Pixels> for f32 {
348    fn from(pixels: &Pixels) -> Self {
349        pixels.0
350    }
351}
352
353impl From<Pixels> for f64 {
354    fn from(pixels: Pixels) -> Self {
355        pixels.0 as f64
356    }
357}
358
359#[derive(Clone, Copy, Default, Add, Sub, Mul, Div)]
360pub struct Rems(f32);
361
362impl Mul<Pixels> for Rems {
363    type Output = Pixels;
364
365    fn mul(self, other: Pixels) -> Pixels {
366        Pixels(self.0 * other.0)
367    }
368}
369
370impl Debug for Rems {
371    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
372        write!(f, "{} rem", self.0)
373    }
374}
375
376#[derive(Clone, Copy, Debug)]
377pub enum AbsoluteLength {
378    Pixels(Pixels),
379    Rems(Rems),
380}
381
382impl From<Pixels> for AbsoluteLength {
383    fn from(pixels: Pixels) -> Self {
384        AbsoluteLength::Pixels(pixels)
385    }
386}
387
388impl From<Rems> for AbsoluteLength {
389    fn from(rems: Rems) -> Self {
390        AbsoluteLength::Rems(rems)
391    }
392}
393
394impl AbsoluteLength {
395    pub fn to_pixels(&self, rem_size: Pixels) -> Pixels {
396        match self {
397            AbsoluteLength::Pixels(pixels) => *pixels,
398            AbsoluteLength::Rems(rems) => *rems * rem_size,
399        }
400    }
401}
402
403impl Default for AbsoluteLength {
404    fn default() -> Self {
405        px(0.).into()
406    }
407}
408
409/// A non-auto length that can be defined in pixels, rems, or percent of parent.
410#[derive(Clone, Copy)]
411pub enum DefiniteLength {
412    Absolute(AbsoluteLength),
413    /// A fraction of the parent's size between 0 and 1.
414    Fraction(f32),
415}
416
417impl Debug for DefiniteLength {
418    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
419        match self {
420            DefiniteLength::Absolute(length) => Debug::fmt(length, f),
421            DefiniteLength::Fraction(fract) => write!(f, "{}%", (fract * 100.0) as i32),
422        }
423    }
424}
425
426impl From<Pixels> for DefiniteLength {
427    fn from(pixels: Pixels) -> Self {
428        Self::Absolute(pixels.into())
429    }
430}
431
432impl From<Rems> for DefiniteLength {
433    fn from(rems: Rems) -> Self {
434        Self::Absolute(rems.into())
435    }
436}
437
438impl From<AbsoluteLength> for DefiniteLength {
439    fn from(length: AbsoluteLength) -> Self {
440        Self::Absolute(length)
441    }
442}
443
444impl Default for DefiniteLength {
445    fn default() -> Self {
446        Self::Absolute(AbsoluteLength::default())
447    }
448}
449
450/// A length that can be defined in pixels, rems, percent of parent, or auto.
451#[derive(Clone, Copy)]
452pub enum Length {
453    Definite(DefiniteLength),
454    Auto,
455}
456
457impl Debug for Length {
458    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
459        match self {
460            Length::Definite(definite_length) => write!(f, "{:?}", definite_length),
461            Length::Auto => write!(f, "auto"),
462        }
463    }
464}
465
466pub fn relative(fraction: f32) -> DefiniteLength {
467    DefiniteLength::Fraction(fraction).into()
468}
469
470pub fn rems(rems: f32) -> Rems {
471    Rems(rems)
472}
473
474pub fn px(pixels: f32) -> Pixels {
475    Pixels(pixels)
476}
477
478pub fn auto() -> Length {
479    Length::Auto
480}
481
482impl From<Pixels> for Length {
483    fn from(pixels: Pixels) -> Self {
484        Self::Definite(pixels.into())
485    }
486}
487
488impl From<Rems> for Length {
489    fn from(rems: Rems) -> Self {
490        Self::Definite(rems.into())
491    }
492}
493
494impl From<DefiniteLength> for Length {
495    fn from(length: DefiniteLength) -> Self {
496        Self::Definite(length)
497    }
498}
499
500impl From<AbsoluteLength> for Length {
501    fn from(length: AbsoluteLength) -> Self {
502        Self::Definite(length.into())
503    }
504}
505
506impl Default for Length {
507    fn default() -> Self {
508        Self::Definite(DefiniteLength::default())
509    }
510}
511
512impl From<()> for Length {
513    fn from(_: ()) -> Self {
514        Self::Definite(DefiniteLength::default())
515    }
516}