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, Div, Mul, MulAssign, Sub, SubAssign};
  6
  7#[derive(Refineable, Default, Add, AddAssign, Sub, SubAssign, Copy, Debug, PartialEq, Eq, Hash)]
  8#[refineable(debug)]
  9#[repr(C)]
 10pub struct Point<T: Clone + Debug> {
 11    pub x: T,
 12    pub y: T,
 13}
 14
 15pub fn point<T: Clone + Debug>(x: T, y: T) -> Point<T> {
 16    Point { x, y }
 17}
 18
 19impl<T: Clone + Debug> Point<T> {
 20    pub fn new(x: T, y: T) -> Self {
 21        Self { x, y }
 22    }
 23
 24    pub fn map<U: Clone + Debug, F: Fn(T) -> U>(&self, f: F) -> Point<U> {
 25        Point {
 26            x: f(self.x.clone()),
 27            y: f(self.y.clone()),
 28        }
 29    }
 30}
 31
 32impl<T, Rhs> Mul<Rhs> for Point<T>
 33where
 34    T: Mul<Rhs, Output = Rhs> + Clone + Debug,
 35    Rhs: Clone + Debug,
 36{
 37    type Output = Point<Rhs>;
 38
 39    fn mul(self, rhs: Rhs) -> Self::Output {
 40        Point {
 41            x: self.x * rhs.clone(),
 42            y: self.y * rhs,
 43        }
 44    }
 45}
 46
 47impl<T: Clone + Debug + Mul<S, Output = T>, S: Clone> MulAssign<S> for Point<T> {
 48    fn mul_assign(&mut self, rhs: S) {
 49        self.x = self.x.clone() * rhs.clone();
 50        self.y = self.y.clone() * rhs;
 51    }
 52}
 53
 54impl<T: Clone + Debug + Sub<Output = T>> SubAssign<Size<T>> for Point<T> {
 55    fn sub_assign(&mut self, rhs: Size<T>) {
 56        self.x = self.x.clone() - rhs.width;
 57        self.y = self.y.clone() - rhs.height;
 58    }
 59}
 60
 61impl<T: Clone + Debug + Add<Output = T> + Copy> AddAssign<T> for Point<T> {
 62    fn add_assign(&mut self, rhs: T) {
 63        self.x = self.x.clone() + rhs;
 64        self.y = self.y.clone() + rhs;
 65    }
 66}
 67
 68impl<T: Clone + Debug + Div<S, Output = T>, S: Clone> Div<S> for Point<T> {
 69    type Output = Self;
 70
 71    fn div(self, rhs: S) -> Self::Output {
 72        Self {
 73            x: self.x / rhs.clone(),
 74            y: self.y / rhs,
 75        }
 76    }
 77}
 78
 79impl<T: Clone + Debug + std::cmp::PartialOrd> Point<T> {
 80    pub fn max(&self, other: &Self) -> Self {
 81        Point {
 82            x: if self.x >= other.x {
 83                self.x.clone()
 84            } else {
 85                other.x.clone()
 86            },
 87            y: if self.y >= other.y {
 88                self.y.clone()
 89            } else {
 90                other.y.clone()
 91            },
 92        }
 93    }
 94}
 95
 96impl<T: Clone + Debug> Clone for Point<T> {
 97    fn clone(&self) -> Self {
 98        Self {
 99            x: self.x.clone(),
100            y: self.y.clone(),
101        }
102    }
103}
104
105unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Point<T> {}
106unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Point<T> {}
107
108#[derive(Refineable, Default, Clone, Copy, Debug, PartialEq, Div)]
109#[refineable(debug)]
110#[repr(C)]
111pub struct Size<T: Clone + Debug> {
112    pub width: T,
113    pub height: T,
114}
115
116unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Size<T> {}
117unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Size<T> {}
118
119pub fn size<T: Clone + Debug>(width: T, height: T) -> Size<T> {
120    Size { width, height }
121}
122
123impl<T: Clone + Debug> Size<T> {
124    pub fn map<U: Clone + Debug, F: Fn(T) -> U>(&self, f: F) -> Size<U> {
125        Size {
126            width: f(self.width.clone()),
127            height: f(self.height.clone()),
128        }
129    }
130}
131
132impl<T, Rhs> Mul<Rhs> for Size<T>
133where
134    T: Mul<Rhs, Output = Rhs> + Debug + Clone,
135    Rhs: Debug + Clone,
136{
137    type Output = Size<Rhs>;
138
139    fn mul(self, rhs: Rhs) -> Self::Output {
140        Size {
141            width: self.width * rhs.clone(),
142            height: self.height * rhs,
143        }
144    }
145}
146
147impl<T: Clone + Debug + Mul<S, Output = T>, S: Clone> MulAssign<S> for Size<T> {
148    fn mul_assign(&mut self, rhs: S) {
149        self.width = self.width.clone() * rhs.clone();
150        self.height = self.height.clone() * rhs;
151    }
152}
153
154impl From<Size<Option<Pixels>>> for Size<Option<f32>> {
155    fn from(val: Size<Option<Pixels>>) -> Self {
156        Size {
157            width: val.width.map(|p| p.0 as f32),
158            height: val.height.map(|p| p.0 as f32),
159        }
160    }
161}
162
163impl Size<Length> {
164    pub fn full() -> Self {
165        Self {
166            width: relative(1.).into(),
167            height: relative(1.).into(),
168        }
169    }
170}
171
172impl Size<DefiniteLength> {
173    pub fn zero() -> Self {
174        Self {
175            width: px(0.).into(),
176            height: px(0.).into(),
177        }
178    }
179}
180
181impl Size<Length> {
182    pub fn auto() -> Self {
183        Self {
184            width: Length::Auto,
185            height: Length::Auto,
186        }
187    }
188}
189
190#[derive(Refineable, Clone, Default, Debug, PartialEq)]
191#[refineable(debug)]
192#[repr(C)]
193pub struct Bounds<T: Clone + Debug> {
194    pub origin: Point<T>,
195    pub size: Size<T>,
196}
197
198unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Bounds<T> {}
199unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Bounds<T> {}
200
201// Bounds<f32> * Pixels = Bounds<Pixels>
202impl<T, Rhs> Mul<Rhs> for Bounds<T>
203where
204    T: Mul<Rhs, Output = Rhs> + Clone + Debug,
205    Rhs: Clone + Debug,
206{
207    type Output = Bounds<Rhs>;
208
209    fn mul(self, rhs: Rhs) -> Self::Output {
210        Bounds {
211            origin: self.origin * rhs.clone(),
212            size: self.size * rhs,
213        }
214    }
215}
216
217impl<T: Clone + Debug + Mul<S, Output = T>, S: Clone> MulAssign<S> for Bounds<T> {
218    fn mul_assign(&mut self, rhs: S) {
219        self.origin *= rhs.clone();
220        self.size *= rhs;
221    }
222}
223
224impl<T: Clone + Debug + Div<S, Output = T>, S: Clone> Div<S> for Bounds<T>
225where
226    Size<T>: Div<S, Output = Size<T>>,
227{
228    type Output = Self;
229
230    fn div(self, rhs: S) -> Self {
231        Self {
232            origin: self.origin / rhs.clone(),
233            size: self.size / rhs,
234        }
235    }
236}
237
238impl<T: Clone + Debug + Add<T, Output = T>> Bounds<T> {
239    pub fn upper_right(&self) -> Point<T> {
240        Point {
241            x: self.origin.x.clone() + self.size.width.clone(),
242            y: self.origin.y.clone(),
243        }
244    }
245
246    pub fn lower_right(&self) -> Point<T> {
247        Point {
248            x: self.origin.x.clone() + self.size.width.clone(),
249            y: self.origin.y.clone() + self.size.height.clone(),
250        }
251    }
252}
253
254impl<T: Clone + Debug + PartialOrd + Add<T, Output = T>> Bounds<T> {
255    pub fn contains_point(&self, point: Point<T>) -> bool {
256        point.x >= self.origin.x
257            && point.x <= self.origin.x.clone() + self.size.width.clone()
258            && point.y >= self.origin.y
259            && point.y <= self.origin.y.clone() + self.size.height.clone()
260    }
261
262    pub fn map<U: Clone + Debug, F: Fn(T) -> U>(&self, f: F) -> Bounds<U> {
263        Bounds {
264            origin: self.origin.map(&f),
265            size: self.size.map(f),
266        }
267    }
268}
269
270impl<T: Clone + Debug + Copy> Copy for Bounds<T> {}
271
272#[derive(Refineable, Clone, Default, Debug)]
273#[refineable(debug)]
274#[repr(C)]
275pub struct Edges<T: Clone + Debug> {
276    pub top: T,
277    pub right: T,
278    pub bottom: T,
279    pub left: T,
280}
281
282impl<T: Clone + Debug + Mul<Output = T>> Mul for Edges<T> {
283    type Output = Self;
284
285    fn mul(self, rhs: Self) -> Self::Output {
286        Self {
287            top: self.top.clone() * rhs.top,
288            right: self.right.clone() * rhs.right,
289            bottom: self.bottom.clone() * rhs.bottom,
290            left: self.left.clone() * rhs.left,
291        }
292    }
293}
294
295impl<T: Clone + Debug + Mul<S, Output = T>, S: Clone> MulAssign<S> for Edges<T> {
296    fn mul_assign(&mut self, rhs: S) {
297        self.top = self.top.clone() * rhs.clone();
298        self.right = self.right.clone() * rhs.clone();
299        self.bottom = self.bottom.clone() * rhs.clone();
300        self.left = self.left.clone() * rhs.clone();
301    }
302}
303
304impl<T: Clone + Debug + Copy> Copy for Edges<T> {}
305
306unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Edges<T> {}
307
308unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Edges<T> {}
309
310impl<T: Clone + Debug> Edges<T> {
311    pub fn map<U: Clone + Debug, F: Fn(&T) -> U>(&self, f: F) -> Edges<U> {
312        Edges {
313            top: f(&self.top),
314            right: f(&self.right),
315            bottom: f(&self.bottom),
316            left: f(&self.left),
317        }
318    }
319
320    pub fn any<F: Fn(&T) -> bool>(&self, predicate: F) -> bool {
321        predicate(&self.top)
322            || predicate(&self.right)
323            || predicate(&self.bottom)
324            || predicate(&self.left)
325    }
326}
327
328impl Edges<Length> {
329    pub fn auto() -> Self {
330        Self {
331            top: Length::Auto,
332            right: Length::Auto,
333            bottom: Length::Auto,
334            left: Length::Auto,
335        }
336    }
337
338    pub fn zero() -> Self {
339        Self {
340            top: px(0.).into(),
341            right: px(0.).into(),
342            bottom: px(0.).into(),
343            left: px(0.).into(),
344        }
345    }
346}
347
348impl Edges<DefiniteLength> {
349    pub fn zero() -> Self {
350        Self {
351            top: px(0.).into(),
352            right: px(0.).into(),
353            bottom: px(0.).into(),
354            left: px(0.).into(),
355        }
356    }
357}
358
359impl Edges<AbsoluteLength> {
360    pub fn zero() -> Self {
361        Self {
362            top: px(0.).into(),
363            right: px(0.).into(),
364            bottom: px(0.).into(),
365            left: px(0.).into(),
366        }
367    }
368
369    pub fn to_pixels(&self, rem_size: Pixels) -> Edges<Pixels> {
370        Edges {
371            top: self.top.to_pixels(rem_size),
372            right: self.right.to_pixels(rem_size),
373            bottom: self.bottom.to_pixels(rem_size),
374            left: self.left.to_pixels(rem_size),
375        }
376    }
377}
378
379#[derive(Refineable, Clone, Default, Debug)]
380#[refineable(debug)]
381#[repr(C)]
382pub struct Corners<T: Clone + Debug> {
383    pub top_left: T,
384    pub top_right: T,
385    pub bottom_right: T,
386    pub bottom_left: T,
387}
388
389impl<T: Clone + Debug> Corners<T> {
390    pub fn map<U: Clone + Debug, F: Fn(&T) -> U>(&self, f: F) -> Corners<U> {
391        Corners {
392            top_left: f(&self.top_left),
393            top_right: f(&self.top_right),
394            bottom_right: f(&self.bottom_right),
395            bottom_left: f(&self.bottom_left),
396        }
397    }
398}
399
400impl<T: Clone + Debug + Mul<Output = T>> Mul for Corners<T> {
401    type Output = Self;
402
403    fn mul(self, rhs: Self) -> Self::Output {
404        Self {
405            top_left: self.top_left.clone() * rhs.top_left,
406            top_right: self.top_right.clone() * rhs.top_right,
407            bottom_right: self.bottom_right.clone() * rhs.bottom_right,
408            bottom_left: self.bottom_left.clone() * rhs.bottom_left,
409        }
410    }
411}
412
413impl<T: Clone + Debug + Mul<S, Output = T>, S: Clone> MulAssign<S> for Corners<T> {
414    fn mul_assign(&mut self, rhs: S) {
415        self.top_left = self.top_left.clone() * rhs.clone();
416        self.top_right = self.top_right.clone() * rhs.clone();
417        self.bottom_right = self.bottom_right.clone() * rhs.clone();
418        self.bottom_left = self.bottom_left.clone() * rhs;
419    }
420}
421
422impl<T: Clone + Debug + Copy> Copy for Corners<T> {}
423
424unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Corners<T> {}
425
426unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Corners<T> {}
427
428#[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd)]
429#[repr(transparent)]
430pub struct Pixels(pub(crate) f32);
431
432impl Mul<f32> for Pixels {
433    type Output = Pixels;
434
435    fn mul(self, other: f32) -> Pixels {
436        Pixels(self.0 * other)
437    }
438}
439
440impl Mul<Pixels> for f32 {
441    type Output = Pixels;
442
443    fn mul(self, rhs: Pixels) -> Self::Output {
444        Pixels(self * rhs.0)
445    }
446}
447
448impl Pixels {
449    pub fn round(&self) -> Self {
450        Self(self.0.round())
451    }
452
453    pub fn to_device_pixels(&self, scale: f32) -> DevicePixels {
454        DevicePixels((self.0 * scale).ceil() as u32)
455    }
456}
457
458impl Mul<Pixels> for Pixels {
459    type Output = Pixels;
460
461    fn mul(self, rhs: Pixels) -> Self::Output {
462        Pixels(self.0 * rhs.0)
463    }
464}
465
466impl Eq for Pixels {}
467
468impl Ord for Pixels {
469    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
470        self.0.partial_cmp(&other.0).unwrap()
471    }
472}
473
474impl std::hash::Hash for Pixels {
475    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
476        self.0.to_bits().hash(state);
477    }
478}
479
480impl From<f64> for Pixels {
481    fn from(val: f64) -> Self {
482        Pixels(val as f32)
483    }
484}
485
486impl From<f32> for Pixels {
487    fn from(val: f32) -> Self {
488        Pixels(val)
489    }
490}
491
492unsafe impl bytemuck::Pod for Pixels {}
493unsafe impl bytemuck::Zeroable for Pixels {}
494
495impl Debug for Pixels {
496    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
497        write!(f, "{} px", self.0)
498    }
499}
500
501impl From<Pixels> for f32 {
502    fn from(pixels: Pixels) -> Self {
503        pixels.0
504    }
505}
506
507impl From<&Pixels> for f32 {
508    fn from(pixels: &Pixels) -> Self {
509        pixels.0
510    }
511}
512
513impl From<Pixels> for f64 {
514    fn from(pixels: Pixels) -> Self {
515        pixels.0 as f64
516    }
517}
518
519#[derive(
520    Clone, Copy, Debug, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd,
521)]
522#[repr(transparent)]
523pub struct DevicePixels(pub(crate) u32);
524
525unsafe impl bytemuck::Pod for DevicePixels {}
526unsafe impl bytemuck::Zeroable for DevicePixels {}
527
528impl From<DevicePixels> for u32 {
529    fn from(device_pixels: DevicePixels) -> Self {
530        device_pixels.0
531    }
532}
533
534impl From<u32> for DevicePixels {
535    fn from(val: u32) -> Self {
536        DevicePixels(val)
537    }
538}
539
540#[derive(Clone, Copy, Default, Add, Sub, Mul, Div)]
541pub struct Rems(f32);
542
543impl Mul<Pixels> for Rems {
544    type Output = Pixels;
545
546    fn mul(self, other: Pixels) -> Pixels {
547        Pixels(self.0 * other.0)
548    }
549}
550
551impl Debug for Rems {
552    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
553        write!(f, "{} rem", self.0)
554    }
555}
556
557#[derive(Clone, Copy, Debug)]
558pub enum AbsoluteLength {
559    Pixels(Pixels),
560    Rems(Rems),
561}
562
563impl AbsoluteLength {
564    pub fn is_zero(&self) -> bool {
565        match self {
566            AbsoluteLength::Pixels(px) => px.0 == 0.,
567            AbsoluteLength::Rems(rems) => rems.0 == 0.,
568        }
569    }
570}
571
572impl From<Pixels> for AbsoluteLength {
573    fn from(pixels: Pixels) -> Self {
574        AbsoluteLength::Pixels(pixels)
575    }
576}
577
578impl From<Rems> for AbsoluteLength {
579    fn from(rems: Rems) -> Self {
580        AbsoluteLength::Rems(rems)
581    }
582}
583
584impl AbsoluteLength {
585    pub fn to_pixels(&self, rem_size: Pixels) -> Pixels {
586        match self {
587            AbsoluteLength::Pixels(pixels) => *pixels,
588            AbsoluteLength::Rems(rems) => *rems * rem_size,
589        }
590    }
591}
592
593impl Default for AbsoluteLength {
594    fn default() -> Self {
595        px(0.).into()
596    }
597}
598
599/// A non-auto length that can be defined in pixels, rems, or percent of parent.
600#[derive(Clone, Copy)]
601pub enum DefiniteLength {
602    Absolute(AbsoluteLength),
603    /// A fraction of the parent's size between 0 and 1.
604    Fraction(f32),
605}
606
607impl DefiniteLength {
608    pub fn to_pixels(&self, base_size: AbsoluteLength, rem_size: Pixels) -> Pixels {
609        match self {
610            DefiniteLength::Absolute(size) => size.to_pixels(rem_size),
611            DefiniteLength::Fraction(fraction) => match base_size {
612                AbsoluteLength::Pixels(px) => px * *fraction,
613                AbsoluteLength::Rems(rems) => rems * rem_size * *fraction,
614            },
615        }
616    }
617}
618
619impl Debug for DefiniteLength {
620    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
621        match self {
622            DefiniteLength::Absolute(length) => Debug::fmt(length, f),
623            DefiniteLength::Fraction(fract) => write!(f, "{}%", (fract * 100.0) as i32),
624        }
625    }
626}
627
628impl From<Pixels> for DefiniteLength {
629    fn from(pixels: Pixels) -> Self {
630        Self::Absolute(pixels.into())
631    }
632}
633
634impl From<Rems> for DefiniteLength {
635    fn from(rems: Rems) -> Self {
636        Self::Absolute(rems.into())
637    }
638}
639
640impl From<AbsoluteLength> for DefiniteLength {
641    fn from(length: AbsoluteLength) -> Self {
642        Self::Absolute(length)
643    }
644}
645
646impl Default for DefiniteLength {
647    fn default() -> Self {
648        Self::Absolute(AbsoluteLength::default())
649    }
650}
651
652/// A length that can be defined in pixels, rems, percent of parent, or auto.
653#[derive(Clone, Copy)]
654pub enum Length {
655    Definite(DefiniteLength),
656    Auto,
657}
658
659impl Debug for Length {
660    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
661        match self {
662            Length::Definite(definite_length) => write!(f, "{:?}", definite_length),
663            Length::Auto => write!(f, "auto"),
664        }
665    }
666}
667
668pub fn relative(fraction: f32) -> DefiniteLength {
669    DefiniteLength::Fraction(fraction).into()
670}
671
672/// Returns the Golden Ratio, i.e. `~(1.0 + sqrt(5.0)) / 2.0`.
673pub fn phi() -> DefiniteLength {
674    relative(1.61803398875)
675}
676
677pub fn rems(rems: f32) -> Rems {
678    Rems(rems)
679}
680
681pub fn px(pixels: f32) -> Pixels {
682    Pixels(pixels)
683}
684
685pub fn auto() -> Length {
686    Length::Auto
687}
688
689impl From<Pixels> for Length {
690    fn from(pixels: Pixels) -> Self {
691        Self::Definite(pixels.into())
692    }
693}
694
695impl From<Rems> for Length {
696    fn from(rems: Rems) -> Self {
697        Self::Definite(rems.into())
698    }
699}
700
701impl From<DefiniteLength> for Length {
702    fn from(length: DefiniteLength) -> Self {
703        Self::Definite(length)
704    }
705}
706
707impl From<AbsoluteLength> for Length {
708    fn from(length: AbsoluteLength) -> Self {
709        Self::Definite(length.into())
710    }
711}
712
713impl Default for Length {
714    fn default() -> Self {
715        Self::Definite(DefiniteLength::default())
716    }
717}
718
719impl From<()> for Length {
720    fn from(_: ()) -> Self {
721        Self::Definite(DefiniteLength::default())
722    }
723}