1use core::fmt::Debug;
2use derive_more::{Add, AddAssign, Div, DivAssign, Mul, Neg, Sub, SubAssign};
3use refineable::Refineable;
4use serde_derive::{Deserialize, Serialize};
5use std::{
6 cmp::{self, PartialOrd},
7 fmt,
8 ops::{Add, Div, Mul, MulAssign, Sub},
9};
10
11#[derive(Refineable, Default, Add, AddAssign, Sub, SubAssign, Copy, Debug, PartialEq, Eq, Hash)]
12#[refineable(debug)]
13#[repr(C)]
14pub struct Point<T: Default + Clone + Debug> {
15 pub x: T,
16 pub y: T,
17}
18
19pub fn point<T: Clone + Debug + Default>(x: T, y: T) -> Point<T> {
20 Point { x, y }
21}
22
23impl<T: Clone + Debug + Default> Point<T> {
24 pub const fn new(x: T, y: T) -> Self {
25 Self { x, y }
26 }
27
28 pub fn zero() -> Self {
29 Self::new(T::default(), T::default())
30 }
31
32 pub fn map<U: Clone + Default + Debug>(&self, f: impl Fn(T) -> U) -> Point<U> {
33 Point {
34 x: f(self.x.clone()),
35 y: f(self.y.clone()),
36 }
37 }
38}
39
40impl Point<Pixels> {
41 pub fn scale(&self, factor: f32) -> Point<ScaledPixels> {
42 Point {
43 x: self.x.scale(factor),
44 y: self.y.scale(factor),
45 }
46 }
47
48 pub fn magnitude(&self) -> f64 {
49 ((self.x.0.powi(2) + self.y.0.powi(2)) as f64).sqrt()
50 }
51}
52
53impl<T, Rhs> Mul<Rhs> for Point<T>
54where
55 T: Mul<Rhs, Output = T> + Clone + Default + Debug,
56 Rhs: Clone + Debug,
57{
58 type Output = Point<T>;
59
60 fn mul(self, rhs: Rhs) -> Self::Output {
61 Point {
62 x: self.x * rhs.clone(),
63 y: self.y * rhs,
64 }
65 }
66}
67
68impl<T, S> MulAssign<S> for Point<T>
69where
70 T: Clone + Mul<S, Output = T> + Default + Debug,
71 S: Clone,
72{
73 fn mul_assign(&mut self, rhs: S) {
74 self.x = self.x.clone() * rhs.clone();
75 self.y = self.y.clone() * rhs;
76 }
77}
78
79impl<T, S> Div<S> for Point<T>
80where
81 T: Div<S, Output = T> + Clone + Default + Debug,
82 S: Clone,
83{
84 type Output = Self;
85
86 fn div(self, rhs: S) -> Self::Output {
87 Self {
88 x: self.x / rhs.clone(),
89 y: self.y / rhs,
90 }
91 }
92}
93
94impl<T> Point<T>
95where
96 T: PartialOrd + Clone + Default + Debug,
97{
98 pub fn max(&self, other: &Self) -> Self {
99 Point {
100 x: if self.x >= other.x {
101 self.x.clone()
102 } else {
103 other.x.clone()
104 },
105 y: if self.y >= other.y {
106 self.y.clone()
107 } else {
108 other.y.clone()
109 },
110 }
111 }
112
113 pub fn min(&self, other: &Self) -> Self {
114 Point {
115 x: if self.x <= other.x {
116 self.x.clone()
117 } else {
118 other.x.clone()
119 },
120 y: if self.y <= other.y {
121 self.y.clone()
122 } else {
123 other.y.clone()
124 },
125 }
126 }
127
128 pub fn clamp(&self, min: &Self, max: &Self) -> Self {
129 self.max(min).min(max)
130 }
131}
132
133impl<T: Clone + Default + Debug> Clone for Point<T> {
134 fn clone(&self) -> Self {
135 Self {
136 x: self.x.clone(),
137 y: self.y.clone(),
138 }
139 }
140}
141
142#[derive(Refineable, Default, Clone, Copy, PartialEq, Div, Hash, Serialize, Deserialize)]
143#[refineable(debug)]
144#[repr(C)]
145pub struct Size<T: Clone + Default + Debug> {
146 pub width: T,
147 pub height: T,
148}
149
150pub fn size<T>(width: T, height: T) -> Size<T>
151where
152 T: Clone + Default + Debug,
153{
154 Size { width, height }
155}
156
157impl<T> Size<T>
158where
159 T: Clone + Default + Debug,
160{
161 pub fn map<U>(&self, f: impl Fn(T) -> U) -> Size<U>
162 where
163 U: Clone + Default + Debug,
164 {
165 Size {
166 width: f(self.width.clone()),
167 height: f(self.height.clone()),
168 }
169 }
170}
171
172impl Size<Pixels> {
173 pub fn scale(&self, factor: f32) -> Size<ScaledPixels> {
174 Size {
175 width: self.width.scale(factor),
176 height: self.height.scale(factor),
177 }
178 }
179}
180
181impl<T> Size<T>
182where
183 T: PartialOrd + Clone + Default + Debug,
184{
185 pub fn max(&self, other: &Self) -> Self {
186 Size {
187 width: if self.width >= other.width {
188 self.width.clone()
189 } else {
190 other.width.clone()
191 },
192 height: if self.height >= other.height {
193 self.height.clone()
194 } else {
195 other.height.clone()
196 },
197 }
198 }
199}
200
201impl<T> Sub for Size<T>
202where
203 T: Sub<Output = T> + Clone + Default + Debug,
204{
205 type Output = Size<T>;
206
207 fn sub(self, rhs: Self) -> Self::Output {
208 Size {
209 width: self.width - rhs.width,
210 height: self.height - rhs.height,
211 }
212 }
213}
214
215impl<T, Rhs> Mul<Rhs> for Size<T>
216where
217 T: Mul<Rhs, Output = Rhs> + Clone + Default + Debug,
218 Rhs: Clone + Default + Debug,
219{
220 type Output = Size<Rhs>;
221
222 fn mul(self, rhs: Rhs) -> Self::Output {
223 Size {
224 width: self.width * rhs.clone(),
225 height: self.height * rhs,
226 }
227 }
228}
229
230impl<T, S> MulAssign<S> for Size<T>
231where
232 T: Mul<S, Output = T> + Clone + Default + Debug,
233 S: Clone,
234{
235 fn mul_assign(&mut self, rhs: S) {
236 self.width = self.width.clone() * rhs.clone();
237 self.height = self.height.clone() * rhs;
238 }
239}
240
241impl<T> Eq for Size<T> where T: Eq + Default + Debug + Clone {}
242
243impl<T> Debug for Size<T>
244where
245 T: Clone + Default + Debug,
246{
247 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
248 write!(f, "Size {{ {:?} × {:?} }}", self.width, self.height)
249 }
250}
251
252impl<T: Clone + Default + Debug> From<Point<T>> for Size<T> {
253 fn from(point: Point<T>) -> Self {
254 Self {
255 width: point.x,
256 height: point.y,
257 }
258 }
259}
260
261impl From<Size<Pixels>> for Size<GlobalPixels> {
262 fn from(size: Size<Pixels>) -> Self {
263 Size {
264 width: GlobalPixels(size.width.0),
265 height: GlobalPixels(size.height.0),
266 }
267 }
268}
269
270impl Size<Length> {
271 pub fn full() -> Self {
272 Self {
273 width: relative(1.).into(),
274 height: relative(1.).into(),
275 }
276 }
277}
278
279impl Size<DefiniteLength> {
280 pub fn zero() -> Self {
281 Self {
282 width: px(0.).into(),
283 height: px(0.).into(),
284 }
285 }
286}
287
288impl Size<Length> {
289 pub fn auto() -> Self {
290 Self {
291 width: Length::Auto,
292 height: Length::Auto,
293 }
294 }
295}
296
297#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
298#[refineable(debug)]
299#[repr(C)]
300pub struct Bounds<T: Clone + Default + Debug> {
301 pub origin: Point<T>,
302 pub size: Size<T>,
303}
304
305impl<T> Bounds<T>
306where
307 T: Clone + Debug + Sub<Output = T> + Default,
308{
309 pub fn from_corners(upper_left: Point<T>, lower_right: Point<T>) -> Self {
310 let origin = Point {
311 x: upper_left.x.clone(),
312 y: upper_left.y.clone(),
313 };
314 let size = Size {
315 width: lower_right.x - upper_left.x,
316 height: lower_right.y - upper_left.y,
317 };
318 Bounds { origin, size }
319 }
320}
321
322impl<T> Bounds<T>
323where
324 T: Clone + Debug + PartialOrd + Add<T, Output = T> + Sub<Output = T> + Default,
325{
326 pub fn intersects(&self, other: &Bounds<T>) -> bool {
327 let my_lower_right = self.lower_right();
328 let their_lower_right = other.lower_right();
329
330 self.origin.x < their_lower_right.x
331 && my_lower_right.x > other.origin.x
332 && self.origin.y < their_lower_right.y
333 && my_lower_right.y > other.origin.y
334 }
335
336 pub fn dilate(&mut self, amount: T) {
337 self.origin.x = self.origin.x.clone() - amount.clone();
338 self.origin.y = self.origin.y.clone() - amount.clone();
339 let double_amount = amount.clone() + amount;
340 self.size.width = self.size.width.clone() + double_amount.clone();
341 self.size.height = self.size.height.clone() + double_amount;
342 }
343}
344
345impl<T: Clone + Default + Debug + PartialOrd + Add<T, Output = T> + Sub<Output = T>> Bounds<T> {
346 pub fn intersect(&self, other: &Self) -> Self {
347 let upper_left = self.origin.max(&other.origin);
348 let lower_right = self.lower_right().min(&other.lower_right());
349 Self::from_corners(upper_left, lower_right)
350 }
351
352 pub fn union(&self, other: &Self) -> Self {
353 let top_left = self.origin.min(&other.origin);
354 let bottom_right = self.lower_right().max(&other.lower_right());
355 Bounds::from_corners(top_left, bottom_right)
356 }
357}
358
359impl<T, Rhs> Mul<Rhs> for Bounds<T>
360where
361 T: Mul<Rhs, Output = Rhs> + Clone + Default + Debug,
362 Point<T>: Mul<Rhs, Output = Point<Rhs>>,
363 Rhs: Clone + Default + Debug,
364{
365 type Output = Bounds<Rhs>;
366
367 fn mul(self, rhs: Rhs) -> Self::Output {
368 Bounds {
369 origin: self.origin * rhs.clone(),
370 size: self.size * rhs,
371 }
372 }
373}
374
375impl<T, S> MulAssign<S> for Bounds<T>
376where
377 T: Mul<S, Output = T> + Clone + Default + Debug,
378 S: Clone,
379{
380 fn mul_assign(&mut self, rhs: S) {
381 self.origin *= rhs.clone();
382 self.size *= rhs;
383 }
384}
385
386impl<T, S> Div<S> for Bounds<T>
387where
388 Size<T>: Div<S, Output = Size<T>>,
389 T: Div<S, Output = T> + Default + Clone + Debug,
390 S: Clone,
391{
392 type Output = Self;
393
394 fn div(self, rhs: S) -> Self {
395 Self {
396 origin: self.origin / rhs.clone(),
397 size: self.size / rhs,
398 }
399 }
400}
401
402impl<T> Bounds<T>
403where
404 T: Add<T, Output = T> + Clone + Default + Debug,
405{
406 pub fn upper_right(&self) -> Point<T> {
407 Point {
408 x: self.origin.x.clone() + self.size.width.clone(),
409 y: self.origin.y.clone(),
410 }
411 }
412
413 pub fn lower_right(&self) -> Point<T> {
414 Point {
415 x: self.origin.x.clone() + self.size.width.clone(),
416 y: self.origin.y.clone() + self.size.height.clone(),
417 }
418 }
419
420 pub fn lower_left(&self) -> Point<T> {
421 Point {
422 x: self.origin.x.clone(),
423 y: self.origin.y.clone() + self.size.height.clone(),
424 }
425 }
426}
427
428impl<T> Bounds<T>
429where
430 T: Add<T, Output = T> + PartialOrd + Clone + Default + Debug,
431{
432 pub fn contains_point(&self, point: &Point<T>) -> bool {
433 point.x >= self.origin.x
434 && point.x <= self.origin.x.clone() + self.size.width.clone()
435 && point.y >= self.origin.y
436 && point.y <= self.origin.y.clone() + self.size.height.clone()
437 }
438
439 pub fn map<U>(&self, f: impl Fn(T) -> U) -> Bounds<U>
440 where
441 U: Clone + Default + Debug,
442 {
443 Bounds {
444 origin: self.origin.map(&f),
445 size: self.size.map(f),
446 }
447 }
448}
449
450impl Bounds<Pixels> {
451 pub fn scale(&self, factor: f32) -> Bounds<ScaledPixels> {
452 Bounds {
453 origin: self.origin.scale(factor),
454 size: self.size.scale(factor),
455 }
456 }
457}
458
459impl<T: Clone + Debug + Copy + Default> Copy for Bounds<T> {}
460
461#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
462#[refineable(debug)]
463#[repr(C)]
464pub struct Edges<T: Clone + Default + Debug> {
465 pub top: T,
466 pub right: T,
467 pub bottom: T,
468 pub left: T,
469}
470
471impl<T> Mul for Edges<T>
472where
473 T: Mul<Output = T> + Clone + Default + Debug,
474{
475 type Output = Self;
476
477 fn mul(self, rhs: Self) -> Self::Output {
478 Self {
479 top: self.top.clone() * rhs.top,
480 right: self.right.clone() * rhs.right,
481 bottom: self.bottom.clone() * rhs.bottom,
482 left: self.left.clone() * rhs.left,
483 }
484 }
485}
486
487impl<T, S> MulAssign<S> for Edges<T>
488where
489 T: Mul<S, Output = T> + Clone + Default + Debug,
490 S: Clone,
491{
492 fn mul_assign(&mut self, rhs: S) {
493 self.top = self.top.clone() * rhs.clone();
494 self.right = self.right.clone() * rhs.clone();
495 self.bottom = self.bottom.clone() * rhs.clone();
496 self.left = self.left.clone() * rhs;
497 }
498}
499
500impl<T: Clone + Default + Debug + Copy> Copy for Edges<T> {}
501
502impl<T: Clone + Default + Debug> Edges<T> {
503 pub fn all(value: T) -> Self {
504 Self {
505 top: value.clone(),
506 right: value.clone(),
507 bottom: value.clone(),
508 left: value,
509 }
510 }
511
512 pub fn map<U>(&self, f: impl Fn(&T) -> U) -> Edges<U>
513 where
514 U: Clone + Default + Debug,
515 {
516 Edges {
517 top: f(&self.top),
518 right: f(&self.right),
519 bottom: f(&self.bottom),
520 left: f(&self.left),
521 }
522 }
523
524 pub fn any<F: Fn(&T) -> bool>(&self, predicate: F) -> bool {
525 predicate(&self.top)
526 || predicate(&self.right)
527 || predicate(&self.bottom)
528 || predicate(&self.left)
529 }
530}
531
532impl Edges<Length> {
533 pub fn auto() -> Self {
534 Self {
535 top: Length::Auto,
536 right: Length::Auto,
537 bottom: Length::Auto,
538 left: Length::Auto,
539 }
540 }
541
542 pub fn zero() -> Self {
543 Self {
544 top: px(0.).into(),
545 right: px(0.).into(),
546 bottom: px(0.).into(),
547 left: px(0.).into(),
548 }
549 }
550}
551
552impl Edges<DefiniteLength> {
553 pub fn zero() -> Self {
554 Self {
555 top: px(0.).into(),
556 right: px(0.).into(),
557 bottom: px(0.).into(),
558 left: px(0.).into(),
559 }
560 }
561}
562
563impl Edges<AbsoluteLength> {
564 pub fn zero() -> Self {
565 Self {
566 top: px(0.).into(),
567 right: px(0.).into(),
568 bottom: px(0.).into(),
569 left: px(0.).into(),
570 }
571 }
572
573 pub fn to_pixels(&self, rem_size: Pixels) -> Edges<Pixels> {
574 Edges {
575 top: self.top.to_pixels(rem_size),
576 right: self.right.to_pixels(rem_size),
577 bottom: self.bottom.to_pixels(rem_size),
578 left: self.left.to_pixels(rem_size),
579 }
580 }
581}
582
583impl Edges<Pixels> {
584 pub fn scale(&self, factor: f32) -> Edges<ScaledPixels> {
585 Edges {
586 top: self.top.scale(factor),
587 right: self.right.scale(factor),
588 bottom: self.bottom.scale(factor),
589 left: self.left.scale(factor),
590 }
591 }
592}
593
594#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
595#[refineable(debug)]
596#[repr(C)]
597pub struct Corners<T: Clone + Default + Debug> {
598 pub top_left: T,
599 pub top_right: T,
600 pub bottom_right: T,
601 pub bottom_left: T,
602}
603
604impl Corners<AbsoluteLength> {
605 pub fn to_pixels(&self, size: Size<Pixels>, rem_size: Pixels) -> Corners<Pixels> {
606 let max = size.width.max(size.height) / 2.;
607 Corners {
608 top_left: self.top_left.to_pixels(rem_size).min(max),
609 top_right: self.top_right.to_pixels(rem_size).min(max),
610 bottom_right: self.bottom_right.to_pixels(rem_size).min(max),
611 bottom_left: self.bottom_left.to_pixels(rem_size).min(max),
612 }
613 }
614}
615
616impl Corners<Pixels> {
617 pub fn scale(&self, factor: f32) -> Corners<ScaledPixels> {
618 Corners {
619 top_left: self.top_left.scale(factor),
620 top_right: self.top_right.scale(factor),
621 bottom_right: self.bottom_right.scale(factor),
622 bottom_left: self.bottom_left.scale(factor),
623 }
624 }
625}
626
627impl<T: Clone + Default + Debug> Corners<T> {
628 pub fn map<U>(&self, f: impl Fn(&T) -> U) -> Corners<U>
629 where
630 U: Clone + Default + Debug,
631 {
632 Corners {
633 top_left: f(&self.top_left),
634 top_right: f(&self.top_right),
635 bottom_right: f(&self.bottom_right),
636 bottom_left: f(&self.bottom_left),
637 }
638 }
639}
640
641impl<T> Mul for Corners<T>
642where
643 T: Mul<Output = T> + Clone + Default + Debug,
644{
645 type Output = Self;
646
647 fn mul(self, rhs: Self) -> Self::Output {
648 Self {
649 top_left: self.top_left.clone() * rhs.top_left,
650 top_right: self.top_right.clone() * rhs.top_right,
651 bottom_right: self.bottom_right.clone() * rhs.bottom_right,
652 bottom_left: self.bottom_left.clone() * rhs.bottom_left,
653 }
654 }
655}
656
657impl<T, S> MulAssign<S> for Corners<T>
658where
659 T: Mul<S, Output = T> + Clone + Default + Debug,
660 S: Clone,
661{
662 fn mul_assign(&mut self, rhs: S) {
663 self.top_left = self.top_left.clone() * rhs.clone();
664 self.top_right = self.top_right.clone() * rhs.clone();
665 self.bottom_right = self.bottom_right.clone() * rhs.clone();
666 self.bottom_left = self.bottom_left.clone() * rhs;
667 }
668}
669
670impl<T> Copy for Corners<T> where T: Copy + Clone + Default + Debug {}
671
672#[derive(
673 Clone,
674 Copy,
675 Default,
676 Add,
677 AddAssign,
678 Sub,
679 SubAssign,
680 Neg,
681 Div,
682 DivAssign,
683 PartialEq,
684 PartialOrd,
685 Serialize,
686 Deserialize,
687)]
688#[repr(transparent)]
689pub struct Pixels(pub(crate) f32);
690
691impl std::ops::Div for Pixels {
692 type Output = Self;
693
694 fn div(self, rhs: Self) -> Self::Output {
695 Self(self.0 / rhs.0)
696 }
697}
698
699impl std::ops::DivAssign for Pixels {
700 fn div_assign(&mut self, rhs: Self) {
701 self.0 /= rhs.0;
702 }
703}
704
705impl std::ops::RemAssign for Pixels {
706 fn rem_assign(&mut self, rhs: Self) {
707 self.0 %= rhs.0;
708 }
709}
710
711impl std::ops::Rem for Pixels {
712 type Output = Self;
713
714 fn rem(self, rhs: Self) -> Self {
715 Self(self.0 % rhs.0)
716 }
717}
718
719impl Mul<f32> for Pixels {
720 type Output = Pixels;
721
722 fn mul(self, other: f32) -> Pixels {
723 Pixels(self.0 * other)
724 }
725}
726
727impl Mul<usize> for Pixels {
728 type Output = Pixels;
729
730 fn mul(self, other: usize) -> Pixels {
731 Pixels(self.0 * other as f32)
732 }
733}
734
735impl Mul<Pixels> for f32 {
736 type Output = Pixels;
737
738 fn mul(self, rhs: Pixels) -> Self::Output {
739 Pixels(self * rhs.0)
740 }
741}
742
743impl MulAssign<f32> for Pixels {
744 fn mul_assign(&mut self, other: f32) {
745 self.0 *= other;
746 }
747}
748
749impl Pixels {
750 pub const ZERO: Pixels = Pixels(0.0);
751 pub const MAX: Pixels = Pixels(f32::MAX);
752
753 pub fn as_usize(&self) -> usize {
754 self.0 as usize
755 }
756
757 pub fn as_isize(&self) -> isize {
758 self.0 as isize
759 }
760
761 pub fn floor(&self) -> Self {
762 Self(self.0.floor())
763 }
764
765 pub fn round(&self) -> Self {
766 Self(self.0.round())
767 }
768
769 pub fn scale(&self, factor: f32) -> ScaledPixels {
770 ScaledPixels(self.0 * factor)
771 }
772
773 pub fn pow(&self, exponent: f32) -> Self {
774 Self(self.0.powf(exponent))
775 }
776
777 pub fn abs(&self) -> Self {
778 Self(self.0.abs())
779 }
780}
781
782impl Mul<Pixels> for Pixels {
783 type Output = Pixels;
784
785 fn mul(self, rhs: Pixels) -> Self::Output {
786 Pixels(self.0 * rhs.0)
787 }
788}
789
790impl Eq for Pixels {}
791
792impl Ord for Pixels {
793 fn cmp(&self, other: &Self) -> cmp::Ordering {
794 self.0.partial_cmp(&other.0).unwrap()
795 }
796}
797
798impl std::hash::Hash for Pixels {
799 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
800 self.0.to_bits().hash(state);
801 }
802}
803
804impl From<f64> for Pixels {
805 fn from(pixels: f64) -> Self {
806 Pixels(pixels as f32)
807 }
808}
809
810impl From<f32> for Pixels {
811 fn from(pixels: f32) -> Self {
812 Pixels(pixels)
813 }
814}
815
816impl Debug for Pixels {
817 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
818 write!(f, "{} px", self.0)
819 }
820}
821
822impl From<Pixels> for f32 {
823 fn from(pixels: Pixels) -> Self {
824 pixels.0
825 }
826}
827
828impl From<&Pixels> for f32 {
829 fn from(pixels: &Pixels) -> Self {
830 pixels.0
831 }
832}
833
834impl From<Pixels> for f64 {
835 fn from(pixels: Pixels) -> Self {
836 pixels.0 as f64
837 }
838}
839
840impl From<Pixels> for u32 {
841 fn from(pixels: Pixels) -> Self {
842 pixels.0 as u32
843 }
844}
845
846impl From<u32> for Pixels {
847 fn from(pixels: u32) -> Self {
848 Pixels(pixels as f32)
849 }
850}
851
852impl From<Pixels> for usize {
853 fn from(pixels: Pixels) -> Self {
854 pixels.0 as usize
855 }
856}
857
858#[derive(
859 Add, AddAssign, Clone, Copy, Default, Div, Eq, Hash, Ord, PartialEq, PartialOrd, Sub, SubAssign,
860)]
861#[repr(transparent)]
862pub struct DevicePixels(pub(crate) i32);
863
864impl DevicePixels {
865 pub fn to_bytes(&self, bytes_per_pixel: u8) -> u32 {
866 self.0 as u32 * bytes_per_pixel as u32
867 }
868}
869
870impl fmt::Debug for DevicePixels {
871 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
872 write!(f, "{} px (device)", self.0)
873 }
874}
875
876impl From<DevicePixels> for i32 {
877 fn from(device_pixels: DevicePixels) -> Self {
878 device_pixels.0
879 }
880}
881
882impl From<i32> for DevicePixels {
883 fn from(device_pixels: i32) -> Self {
884 DevicePixels(device_pixels)
885 }
886}
887
888impl From<u32> for DevicePixels {
889 fn from(device_pixels: u32) -> Self {
890 DevicePixels(device_pixels as i32)
891 }
892}
893
894impl From<DevicePixels> for u32 {
895 fn from(device_pixels: DevicePixels) -> Self {
896 device_pixels.0 as u32
897 }
898}
899
900impl From<DevicePixels> for u64 {
901 fn from(device_pixels: DevicePixels) -> Self {
902 device_pixels.0 as u64
903 }
904}
905
906impl From<u64> for DevicePixels {
907 fn from(device_pixels: u64) -> Self {
908 DevicePixels(device_pixels as i32)
909 }
910}
911
912#[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd)]
913#[repr(transparent)]
914pub struct ScaledPixels(pub(crate) f32);
915
916impl ScaledPixels {
917 pub fn floor(&self) -> Self {
918 Self(self.0.floor())
919 }
920
921 pub fn ceil(&self) -> Self {
922 Self(self.0.ceil())
923 }
924}
925
926impl Eq for ScaledPixels {}
927
928impl Debug for ScaledPixels {
929 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
930 write!(f, "{} px (scaled)", self.0)
931 }
932}
933
934impl From<ScaledPixels> for DevicePixels {
935 fn from(scaled: ScaledPixels) -> Self {
936 DevicePixels(scaled.0.ceil() as i32)
937 }
938}
939
940impl From<DevicePixels> for ScaledPixels {
941 fn from(device: DevicePixels) -> Self {
942 ScaledPixels(device.0 as f32)
943 }
944}
945
946impl From<ScaledPixels> for f64 {
947 fn from(scaled_pixels: ScaledPixels) -> Self {
948 scaled_pixels.0 as f64
949 }
950}
951
952#[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd)]
953#[repr(transparent)]
954pub struct GlobalPixels(pub(crate) f32);
955
956impl Debug for GlobalPixels {
957 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
958 write!(f, "{} px (global coordinate space)", self.0)
959 }
960}
961
962impl From<GlobalPixels> for f64 {
963 fn from(global_pixels: GlobalPixels) -> Self {
964 global_pixels.0 as f64
965 }
966}
967
968impl From<f64> for GlobalPixels {
969 fn from(global_pixels: f64) -> Self {
970 GlobalPixels(global_pixels as f32)
971 }
972}
973
974impl sqlez::bindable::StaticColumnCount for GlobalPixels {}
975
976impl sqlez::bindable::Bind for GlobalPixels {
977 fn bind(
978 &self,
979 statement: &sqlez::statement::Statement,
980 start_index: i32,
981 ) -> anyhow::Result<i32> {
982 self.0.bind(statement, start_index)
983 }
984}
985
986#[derive(Clone, Copy, Default, Add, Sub, Mul, Div, Neg)]
987pub struct Rems(f32);
988
989impl Mul<Pixels> for Rems {
990 type Output = Pixels;
991
992 fn mul(self, other: Pixels) -> Pixels {
993 Pixels(self.0 * other.0)
994 }
995}
996
997impl Debug for Rems {
998 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
999 write!(f, "{} rem", self.0)
1000 }
1001}
1002
1003#[derive(Clone, Copy, Debug, Neg)]
1004pub enum AbsoluteLength {
1005 Pixels(Pixels),
1006 Rems(Rems),
1007}
1008
1009impl AbsoluteLength {
1010 pub fn is_zero(&self) -> bool {
1011 match self {
1012 AbsoluteLength::Pixels(px) => px.0 == 0.,
1013 AbsoluteLength::Rems(rems) => rems.0 == 0.,
1014 }
1015 }
1016}
1017
1018impl From<Pixels> for AbsoluteLength {
1019 fn from(pixels: Pixels) -> Self {
1020 AbsoluteLength::Pixels(pixels)
1021 }
1022}
1023
1024impl From<Rems> for AbsoluteLength {
1025 fn from(rems: Rems) -> Self {
1026 AbsoluteLength::Rems(rems)
1027 }
1028}
1029
1030impl AbsoluteLength {
1031 pub fn to_pixels(&self, rem_size: Pixels) -> Pixels {
1032 match self {
1033 AbsoluteLength::Pixels(pixels) => *pixels,
1034 AbsoluteLength::Rems(rems) => *rems * rem_size,
1035 }
1036 }
1037}
1038
1039impl Default for AbsoluteLength {
1040 fn default() -> Self {
1041 px(0.).into()
1042 }
1043}
1044
1045/// A non-auto length that can be defined in pixels, rems, or percent of parent.
1046#[derive(Clone, Copy, Neg)]
1047pub enum DefiniteLength {
1048 Absolute(AbsoluteLength),
1049 /// A fraction of the parent's size between 0 and 1.
1050 Fraction(f32),
1051}
1052
1053impl DefiniteLength {
1054 pub fn to_pixels(&self, base_size: AbsoluteLength, rem_size: Pixels) -> Pixels {
1055 match self {
1056 DefiniteLength::Absolute(size) => size.to_pixels(rem_size),
1057 DefiniteLength::Fraction(fraction) => match base_size {
1058 AbsoluteLength::Pixels(px) => px * *fraction,
1059 AbsoluteLength::Rems(rems) => rems * rem_size * *fraction,
1060 },
1061 }
1062 }
1063}
1064
1065impl Debug for DefiniteLength {
1066 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1067 match self {
1068 DefiniteLength::Absolute(length) => Debug::fmt(length, f),
1069 DefiniteLength::Fraction(fract) => write!(f, "{}%", (fract * 100.0) as i32),
1070 }
1071 }
1072}
1073
1074impl From<Pixels> for DefiniteLength {
1075 fn from(pixels: Pixels) -> Self {
1076 Self::Absolute(pixels.into())
1077 }
1078}
1079
1080impl From<Rems> for DefiniteLength {
1081 fn from(rems: Rems) -> Self {
1082 Self::Absolute(rems.into())
1083 }
1084}
1085
1086impl From<AbsoluteLength> for DefiniteLength {
1087 fn from(length: AbsoluteLength) -> Self {
1088 Self::Absolute(length)
1089 }
1090}
1091
1092impl Default for DefiniteLength {
1093 fn default() -> Self {
1094 Self::Absolute(AbsoluteLength::default())
1095 }
1096}
1097
1098/// A length that can be defined in pixels, rems, percent of parent, or auto.
1099#[derive(Clone, Copy)]
1100pub enum Length {
1101 Definite(DefiniteLength),
1102 Auto,
1103}
1104
1105impl Debug for Length {
1106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1107 match self {
1108 Length::Definite(definite_length) => write!(f, "{:?}", definite_length),
1109 Length::Auto => write!(f, "auto"),
1110 }
1111 }
1112}
1113
1114pub fn relative(fraction: f32) -> DefiniteLength {
1115 DefiniteLength::Fraction(fraction).into()
1116}
1117
1118/// Returns the Golden Ratio, i.e. `~(1.0 + sqrt(5.0)) / 2.0`.
1119pub fn phi() -> DefiniteLength {
1120 relative(1.61803398875)
1121}
1122
1123pub fn rems(rems: f32) -> Rems {
1124 Rems(rems)
1125}
1126
1127pub const fn px(pixels: f32) -> Pixels {
1128 Pixels(pixels)
1129}
1130
1131pub fn auto() -> Length {
1132 Length::Auto
1133}
1134
1135impl From<Pixels> for Length {
1136 fn from(pixels: Pixels) -> Self {
1137 Self::Definite(pixels.into())
1138 }
1139}
1140
1141impl From<Rems> for Length {
1142 fn from(rems: Rems) -> Self {
1143 Self::Definite(rems.into())
1144 }
1145}
1146
1147impl From<DefiniteLength> for Length {
1148 fn from(length: DefiniteLength) -> Self {
1149 Self::Definite(length)
1150 }
1151}
1152
1153impl From<AbsoluteLength> for Length {
1154 fn from(length: AbsoluteLength) -> Self {
1155 Self::Definite(length.into())
1156 }
1157}
1158
1159impl Default for Length {
1160 fn default() -> Self {
1161 Self::Definite(DefiniteLength::default())
1162 }
1163}
1164
1165impl From<()> for Length {
1166 fn from(_: ()) -> Self {
1167 Self::Definite(DefiniteLength::default())
1168 }
1169}
1170
1171pub trait IsZero {
1172 fn is_zero(&self) -> bool;
1173}
1174
1175impl IsZero for DevicePixels {
1176 fn is_zero(&self) -> bool {
1177 self.0 == 0
1178 }
1179}
1180
1181impl IsZero for ScaledPixels {
1182 fn is_zero(&self) -> bool {
1183 self.0 == 0.
1184 }
1185}
1186
1187impl IsZero for Pixels {
1188 fn is_zero(&self) -> bool {
1189 self.0 == 0.
1190 }
1191}
1192
1193impl IsZero for Rems {
1194 fn is_zero(&self) -> bool {
1195 self.0 == 0.
1196 }
1197}
1198
1199impl IsZero for AbsoluteLength {
1200 fn is_zero(&self) -> bool {
1201 match self {
1202 AbsoluteLength::Pixels(pixels) => pixels.is_zero(),
1203 AbsoluteLength::Rems(rems) => rems.is_zero(),
1204 }
1205 }
1206}
1207
1208impl IsZero for DefiniteLength {
1209 fn is_zero(&self) -> bool {
1210 match self {
1211 DefiniteLength::Absolute(length) => length.is_zero(),
1212 DefiniteLength::Fraction(fraction) => *fraction == 0.,
1213 }
1214 }
1215}
1216
1217impl IsZero for Length {
1218 fn is_zero(&self) -> bool {
1219 match self {
1220 Length::Definite(length) => length.is_zero(),
1221 Length::Auto => false,
1222 }
1223 }
1224}
1225
1226impl<T: IsZero + Debug + Clone + Default> IsZero for Point<T> {
1227 fn is_zero(&self) -> bool {
1228 self.x.is_zero() && self.y.is_zero()
1229 }
1230}
1231
1232impl<T> IsZero for Size<T>
1233where
1234 T: IsZero + Default + Debug + Clone,
1235{
1236 fn is_zero(&self) -> bool {
1237 self.width.is_zero() || self.height.is_zero()
1238 }
1239}
1240
1241impl<T: IsZero + Debug + Clone + Default> IsZero for Bounds<T> {
1242 fn is_zero(&self) -> bool {
1243 self.size.is_zero()
1244 }
1245}
1246
1247impl<T> IsZero for Corners<T>
1248where
1249 T: IsZero + Clone + Default + Debug,
1250{
1251 fn is_zero(&self) -> bool {
1252 self.top_left.is_zero()
1253 && self.top_right.is_zero()
1254 && self.bottom_right.is_zero()
1255 && self.bottom_left.is_zero()
1256 }
1257}
1258
1259#[cfg(test)]
1260mod tests {
1261 use super::*;
1262
1263 #[test]
1264 fn test_bounds_intersects() {
1265 let bounds1 = Bounds {
1266 origin: Point { x: 0.0, y: 0.0 },
1267 size: Size {
1268 width: 5.0,
1269 height: 5.0,
1270 },
1271 };
1272 let bounds2 = Bounds {
1273 origin: Point { x: 4.0, y: 4.0 },
1274 size: Size {
1275 width: 5.0,
1276 height: 5.0,
1277 },
1278 };
1279 let bounds3 = Bounds {
1280 origin: Point { x: 10.0, y: 10.0 },
1281 size: Size {
1282 width: 5.0,
1283 height: 5.0,
1284 },
1285 };
1286
1287 // Test Case 1: Intersecting bounds
1288 assert_eq!(bounds1.intersects(&bounds2), true);
1289
1290 // Test Case 2: Non-Intersecting bounds
1291 assert_eq!(bounds1.intersects(&bounds3), false);
1292
1293 // Test Case 3: Bounds intersecting with themselves
1294 assert_eq!(bounds1.intersects(&bounds1), true);
1295 }
1296}