1
use std::{
2
    fmt::Debug,
3
    ops::{Add, Div, Mul, Sub},
4
};
5

            
6
use num_traits::{NumCast, One, Zero};
7

            
8
use crate::{
9
    Ceil, DisplayScale, Displayable, Figure, Floor, Pixels, Point, Points, Round, Scale, Scaled,
10
    Size, Vector, Vectorlike,
11
};
12

            
13
/// A 2d rectangle. This type may internally be represented with a [`SizedRect`]
14
/// or an [`ExtentsRect`]. All rect types implement [`Rectlike`].
15
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16
pub enum Rect<T, Unit> {
17
    /// A [`SizedRect`].
18
    Sized(SizedRect<T, Unit>),
19
    /// An [`ExtentsRect`].
20
    Extents(ExtentsRect<T, Unit>),
21
}
22

            
23
impl<T, Unit> Debug for Rect<T, Unit>
24
where
25
    T: Debug,
26
{
27
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28
        match self {
29
            Rect::Sized(sized) => sized.fmt(f),
30
            Rect::Extents(extents) => extents.fmt(f),
31
        }
32
    }
33
}
34

            
35
impl<T, Unit> From<SizedRect<T, Unit>> for Rect<T, Unit> {
36
    fn from(rect: SizedRect<T, Unit>) -> Self {
37
        Self::Sized(rect)
38
    }
39
}
40

            
41
impl<T: Default, Unit> From<Size<T, Unit>> for Rect<T, Unit> {
42
    fn from(size: Size<T, Unit>) -> Self {
43
        Self::Sized(SizedRect::from(size))
44
    }
45
}
46

            
47
impl<T, Unit> From<ExtentsRect<T, Unit>> for Rect<T, Unit> {
48
    fn from(rect: ExtentsRect<T, Unit>) -> Self {
49
        Self::Extents(rect)
50
    }
51
}
52

            
53
impl<T, Unit> Rect<T, Unit> {
54
    /// Returns a new rect using `origin` and `size`.
55
    pub fn sized(origin: Point<T, Unit>, size: Size<T, Unit>) -> Self {
56
        Self::Sized(SizedRect::new(origin, size))
57
    }
58

            
59
    /// Returns a new rect using points `origin` and `extent`.
60
    pub fn extents(origin: Point<T, Unit>, extent: Point<T, Unit>) -> Self {
61
        Self::Extents(ExtentsRect::new(origin, extent))
62
    }
63
}
64

            
65
impl<T, Unit> Rect<T, Unit>
66
where
67
    T: NumCast + Copy,
68
{
69
    /// Attempts to cast `T` to `NewT`. If unsuccessful, None is returned.
70
    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<Rect<NewT, Unit>> {
71
        Some(match self {
72
            Self::Sized(sized) => Rect::Sized(sized.try_cast()?),
73
            Self::Extents(extents) => Rect::Extents(extents.try_cast()?),
74
        })
75
    }
76

            
77
    /// Casts `T` to `NewT`.
78
    ///
79
    /// # Panics
80
    ///
81
    /// Panics if casting fails.
82
    pub fn cast<NewT: NumCast + Copy>(&self) -> Rect<NewT, Unit> {
83
        self.try_cast().expect("unable to cast")
84
    }
85
}
86

            
87
impl<T, Unit> Rect<T, Unit>
88
where
89
    T: Copy,
90
{
91
    /// Returns this value with the new unit. Does not affect the underlying
92
    /// value.
93
    pub fn cast_unit<NewUnit>(&self) -> Rect<T, NewUnit> {
94
        match self {
95
            Self::Sized(sized) => Rect::Sized(sized.cast_unit()),
96
            Self::Extents(extents) => Rect::Extents(extents.cast_unit()),
97
        }
98
    }
99
}
100

            
101
impl<T, Unit> Copy for Rect<T, Unit> where T: Copy {}
102

            
103
impl<T, Unit> Clone for Rect<T, Unit>
104
where
105
    T: Clone,
106
{
107
    fn clone(&self) -> Self {
108
        match self {
109
            Self::Sized(sized) => Self::Sized(sized.clone()),
110
            Self::Extents(extents) => Self::Extents(extents.clone()),
111
        }
112
    }
113
}
114

            
115
impl<T, Unit> Eq for Rect<T, Unit> where
116
    T: Zero
117
        + PartialOrd
118
        + Mul<T, Output = T>
119
        + Sub<T, Output = T>
120
        + One
121
        + Add<T, Output = T>
122
        + Div<T, Output = T>
123
        + Copy
124
{
125
}
126

            
127
impl<T, Unit> PartialEq for Rect<T, Unit>
128
where
129
    T: Zero
130
        + PartialOrd
131
        + Mul<T, Output = T>
132
        + Sub<T, Output = T>
133
        + One
134
        + Add<T, Output = T>
135
        + Div<T, Output = T>
136
        + Copy,
137
{
138
    fn eq(&self, other: &Self) -> bool {
139
        match self {
140
            Self::Sized(sized) => sized.eq(&other.as_sized()),
141
            Self::Extents(extents) => extents.eq(&other.as_extents()),
142
        }
143
    }
144
}
145

            
146
impl<T, Unit> Default for Rect<T, Unit>
147
where
148
    T: Default,
149
{
150
    fn default() -> Self {
151
        Self::Sized(SizedRect::default())
152
    }
153
}
154

            
155
impl<T, Unit> Round for Rect<T, Unit>
156
where
157
    T: Round,
158
{
159
    fn round(self) -> Self {
160
        match self {
161
            Self::Sized(sized) => Self::Sized(sized.round()),
162
            Self::Extents(extents) => Self::Extents(extents.round()),
163
        }
164
    }
165
}
166

            
167
impl<T, Unit> Ceil for Rect<T, Unit>
168
where
169
    T: Ceil,
170
{
171
    fn ceil(self) -> Self {
172
        match self {
173
            Self::Sized(sized) => Self::Sized(sized.ceil()),
174
            Self::Extents(extents) => Self::Extents(extents.ceil()),
175
        }
176
    }
177
}
178

            
179
impl<T, Unit> Floor for Rect<T, Unit>
180
where
181
    T: Floor,
182
{
183
    fn floor(self) -> Self {
184
        match self {
185
            Self::Sized(sized) => Self::Sized(sized.floor()),
186
            Self::Extents(extents) => Self::Extents(extents.floor()),
187
        }
188
    }
189
}
190

            
191
impl<T, Unit> Rect<T, Unit>
192
where
193
    T: Ceil + Floor,
194
{
195
    /// Returns a new rectangle that rounds the origin down using `floor` and
196
    /// rounds the extent/size out using `ceil`.
197
    pub fn round_out(self) -> Self {
198
        match self {
199
            Self::Sized(sized) => Self::Sized(sized.round_out()),
200
            Self::Extents(extents) => Self::Extents(extents.round_out()),
201
        }
202
    }
203

            
204
    /// Returns a new rectangle that rounds the origin up using `ceil` and
205
    /// rounds the extent/size in using `floor`.
206
    pub fn round_in(self) -> Self {
207
        match self {
208
            Self::Sized(sized) => Self::Sized(sized.round_in()),
209
            Self::Extents(extents) => Self::Extents(extents.round_in()),
210
        }
211
    }
212
}
213

            
214
impl<T, UnitA, UnitB> Mul<Scale<T, UnitA, UnitB>> for Rect<T, UnitA>
215
where
216
    T: Mul<T, Output = T> + Copy,
217
{
218
    type Output = Rect<T, UnitB>;
219

            
220
    fn mul(self, rhs: Scale<T, UnitA, UnitB>) -> Self::Output {
221
        match self {
222
            Self::Sized(sized) => Rect::Sized(sized * rhs),
223
            Self::Extents(extents) => Rect::Extents(extents * rhs),
224
        }
225
    }
226
}
227

            
228
impl<T, UnitA, UnitB> Div<crate::Scale<T, UnitA, UnitB>> for Rect<T, UnitB>
229
where
230
    T: Div<T, Output = T> + Copy,
231
{
232
    type Output = Rect<T, UnitA>;
233

            
234
    fn div(self, rhs: crate::Scale<T, UnitA, UnitB>) -> Self::Output {
235
        match self {
236
            Self::Sized(sized) => Rect::Sized(sized / rhs),
237
            Self::Extents(extents) => Rect::Extents(extents / rhs),
238
        }
239
    }
240
}
241

            
242
impl<T, Unit> crate::Approx<T> for Rect<T, Unit>
243
where
244
    T: approx::AbsDiffEq
245
        + Zero
246
        + PartialOrd
247
        + Mul<T, Output = T>
248
        + Sub<T, Output = T>
249
        + One
250
        + Add<T, Output = T>
251
        + Div<T, Output = T>
252
        + Copy,
253
{
254
    fn approx_eq(&self, other: &Self) -> bool {
255
        match self {
256
            Self::Sized(sized) => sized.approx_eq(&other.as_sized()),
257
            Self::Extents(extents) => extents.approx_eq(&other.as_extents()),
258
        }
259
    }
260
}
261

            
262
impl<T, Unit> approx::AbsDiffEq for Rect<T, Unit>
263
where
264
    T: approx::AbsDiffEq<Epsilon = T>
265
        + Zero
266
        + PartialOrd
267
        + Mul<T, Output = T>
268
        + Sub<T, Output = T>
269
        + One
270
        + Add<T, Output = T>
271
        + Div<T, Output = T>
272
        + Copy,
273
{
274
    type Epsilon = T::Epsilon;
275

            
276
    fn default_epsilon() -> Self::Epsilon {
277
        T::default_epsilon()
278
    }
279

            
280
    fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
281
        match self {
282
            Self::Sized(sized) => sized.abs_diff_eq(&other.as_sized(), epsilon),
283
            Self::Extents(extents) => extents.abs_diff_eq(&other.as_extents(), epsilon),
284
        }
285
    }
286

            
287
    fn abs_diff_ne(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
288
        match self {
289
            Self::Sized(sized) => sized.abs_diff_ne(&other.as_sized(), epsilon),
290
            Self::Extents(extents) => extents.abs_diff_ne(&other.as_extents(), epsilon),
291
        }
292
    }
293
}
294

            
295
impl<T, Unit> approx::UlpsEq for Rect<T, Unit>
296
where
297
    T: approx::UlpsEq<Epsilon = T>
298
        + Zero
299
        + PartialOrd
300
        + Mul<T, Output = T>
301
        + Sub<T, Output = T>
302
        + One
303
        + Add<T, Output = T>
304
        + Div<T, Output = T>
305
        + Copy,
306
{
307
    fn default_max_ulps() -> u32 {
308
        T::default_max_ulps()
309
    }
310

            
311
    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
312
        match self {
313
            Self::Sized(sized) => sized.ulps_eq(&other.as_sized(), epsilon, max_ulps),
314
            Self::Extents(extents) => extents.ulps_eq(&other.as_extents(), epsilon, max_ulps),
315
        }
316
    }
317

            
318
    fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
319
        match self {
320
            Self::Sized(sized) => sized.ulps_ne(&other.as_sized(), epsilon, max_ulps),
321
            Self::Extents(extents) => extents.ulps_ne(&other.as_extents(), epsilon, max_ulps),
322
        }
323
    }
324
}
325

            
326
impl<T, Unit> approx::RelativeEq for Rect<T, Unit>
327
where
328
    T: approx::RelativeEq<Epsilon = T>
329
        + Zero
330
        + PartialOrd
331
        + Mul<T, Output = T>
332
        + Sub<T, Output = T>
333
        + One
334
        + Add<T, Output = T>
335
        + Div<T, Output = T>
336
        + Copy,
337
{
338
    fn default_max_relative() -> Self::Epsilon {
339
        T::default_max_relative()
340
    }
341

            
342
    fn relative_eq(
343
        &self,
344
        other: &Self,
345
        epsilon: Self::Epsilon,
346
        max_relative: Self::Epsilon,
347
    ) -> bool {
348
        match self {
349
            Self::Sized(sized) => sized.relative_eq(&other.as_sized(), epsilon, max_relative),
350
            Self::Extents(extents) => {
351
                extents.relative_eq(&other.as_extents(), epsilon, max_relative)
352
            }
353
        }
354
    }
355

            
356
    fn relative_ne(
357
        &self,
358
        other: &Self,
359
        epsilon: Self::Epsilon,
360
        max_relative: Self::Epsilon,
361
    ) -> bool {
362
        match self {
363
            Self::Sized(sized) => sized.relative_ne(&other.as_sized(), epsilon, max_relative),
364
            Self::Extents(extents) => {
365
                extents.relative_ne(&other.as_extents(), epsilon, max_relative)
366
            }
367
        }
368
    }
369
}
370

            
371
impl<T> Displayable<T> for Rect<T, Scaled>
372
where
373
    T: Div<T, Output = T> + Mul<T, Output = T> + Copy,
374
{
375
    type Pixels = Rect<T, Pixels>;
376
    type Points = Rect<T, Points>;
377
    type Scaled = Self;
378

            
379
    fn to_pixels(&self, scale: &DisplayScale<T>) -> Self::Pixels {
380
        match self {
381
            Self::Sized(sized) => Rect::Sized(sized.to_pixels(scale)),
382
            Self::Extents(extents) => Rect::Extents(extents.to_pixels(scale)),
383
        }
384
    }
385

            
386
    fn to_points(&self, scale: &DisplayScale<T>) -> Self::Points {
387
        match self {
388
            Self::Sized(sized) => Rect::Sized(sized.to_points(scale)),
389
            Self::Extents(extents) => Rect::Extents(extents.to_points(scale)),
390
        }
391
    }
392

            
393
    fn to_scaled(&self, _scale: &DisplayScale<T>) -> Self::Scaled {
394
        *self
395
    }
396
}
397

            
398
impl<T> Displayable<T> for Rect<T, Points>
399
where
400
    T: Div<T, Output = T> + Mul<T, Output = T> + Copy,
401
{
402
    type Pixels = Rect<T, Pixels>;
403
    type Points = Self;
404
    type Scaled = Rect<T, Scaled>;
405

            
406
    fn to_pixels(&self, scale: &DisplayScale<T>) -> Self::Pixels {
407
        match self {
408
            Self::Sized(sized) => Rect::Sized(sized.to_pixels(scale)),
409
            Self::Extents(extents) => Rect::Extents(extents.to_pixels(scale)),
410
        }
411
    }
412

            
413
    fn to_points(&self, _scale: &DisplayScale<T>) -> Self::Points {
414
        *self
415
    }
416

            
417
    fn to_scaled(&self, scale: &DisplayScale<T>) -> Self::Scaled {
418
        match self {
419
            Self::Sized(sized) => Rect::Sized(sized.to_scaled(scale)),
420
            Self::Extents(extents) => Rect::Extents(extents.to_scaled(scale)),
421
        }
422
    }
423
}
424

            
425
impl<T> Displayable<T> for Rect<T, Pixels>
426
where
427
    T: Div<T, Output = T> + Mul<T, Output = T> + Copy,
428
{
429
    type Pixels = Self;
430
    type Points = Rect<T, Points>;
431
    type Scaled = Rect<T, Scaled>;
432

            
433
    fn to_pixels(&self, _scale: &DisplayScale<T>) -> Self::Pixels {
434
        *self
435
    }
436

            
437
    fn to_points(&self, scale: &DisplayScale<T>) -> Self::Points {
438
        match self {
439
            Self::Sized(sized) => Rect::Sized(sized.to_points(scale)),
440
            Self::Extents(extents) => Rect::Extents(extents.to_points(scale)),
441
        }
442
    }
443

            
444
    fn to_scaled(&self, scale: &DisplayScale<T>) -> Self::Scaled {
445
        match self {
446
            Self::Sized(sized) => Rect::Sized(sized.to_scaled(scale)),
447
            Self::Extents(extents) => Rect::Extents(extents.to_scaled(scale)),
448
        }
449
    }
450
}
451

            
452
/// A rectangle that uses a [`Point`] and a [`Size`] for representation.
453
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
454
pub struct SizedRect<T, Unit> {
455
    /// The origin of the rectangle.
456
    pub origin: Point<T, Unit>,
457
    /// The size of the rectangle.
458
    pub size: Size<T, Unit>,
459
}
460

            
461
impl<T: Default, Unit> From<Size<T, Unit>> for SizedRect<T, Unit> {
462
    fn from(size: Size<T, Unit>) -> Self {
463
        Self::new(Point::default(), size)
464
    }
465
}
466

            
467
impl<T, Unit> Debug for SizedRect<T, Unit>
468
where
469
    T: Debug,
470
{
471
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
472
        f.debug_struct("SizedRect")
473
            .field("origin", &self.origin)
474
            .field("size", &self.size)
475
            .finish()
476
    }
477
}
478

            
479
impl<T, Unit> SizedRect<T, Unit> {
480
    /// Returns a new rectangle using `origin` and `size`.
481
5
    pub const fn new(origin: Point<T, Unit>, size: Size<T, Unit>) -> Self {
482
5
        Self { origin, size }
483
5
    }
484
}
485

            
486
impl<T, Unit> Copy for SizedRect<T, Unit> where T: Copy {}
487

            
488
impl<T, Unit> Clone for SizedRect<T, Unit>
489
where
490
    T: Clone,
491
{
492
    fn clone(&self) -> Self {
493
        Self {
494
            origin: self.origin.clone(),
495
            size: self.size.clone(),
496
        }
497
    }
498
}
499

            
500
impl<T, Unit> Eq for SizedRect<T, Unit> where T: Eq {}
501

            
502
impl<T, Unit> PartialEq for SizedRect<T, Unit>
503
where
504
    T: PartialEq,
505
{
506
1
    fn eq(&self, other: &Self) -> bool {
507
1
        self.origin.eq(&other.origin) && self.size.eq(&other.size)
508
1
    }
509
}
510

            
511
impl<T, Unit> SizedRect<T, Unit>
512
where
513
    T: NumCast + Copy,
514
{
515
    /// Attempts to cast `T` to `NewT`. If unsuccessful, None is returned.
516
    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<SizedRect<NewT, Unit>> {
517
        Some(SizedRect::new(
518
            self.origin.try_cast()?,
519
            self.size.try_cast()?,
520
        ))
521
    }
522

            
523
    /// Casts `T` to `NewT`.
524
    ///
525
    /// # Panics
526
    ///
527
    /// Panics if casting fails.
528
    pub fn cast<NewT: NumCast + Copy>(&self) -> SizedRect<NewT, Unit> {
529
        self.try_cast().expect("unable to cast")
530
    }
531
}
532

            
533
impl<T, Unit> SizedRect<T, Unit>
534
where
535
    T: Copy,
536
{
537
    /// Returns this value with the new unit. Does not affect the underlying
538
    /// value.
539
    pub fn cast_unit<NewUnit>(&self) -> SizedRect<T, NewUnit> {
540
        SizedRect::new(self.origin.cast_unit(), self.size.cast_unit())
541
    }
542
}
543

            
544
impl<T, Unit> Default for SizedRect<T, Unit>
545
where
546
    T: Default,
547
{
548
    fn default() -> Self {
549
        Self::new(Point::default(), Size::default())
550
    }
551
}
552

            
553
impl<T, Unit> Round for SizedRect<T, Unit>
554
where
555
    T: Round,
556
{
557
    fn round(mut self) -> Self {
558
        self.origin = self.origin.round();
559
        self.size = self.size.round();
560
        self
561
    }
562
}
563

            
564
impl<T, Unit> Ceil for SizedRect<T, Unit>
565
where
566
    T: Ceil,
567
{
568
    fn ceil(mut self) -> Self {
569
        self.origin = self.origin.ceil();
570
        self.size = self.size.ceil();
571
        self
572
    }
573
}
574

            
575
impl<T, Unit> Floor for SizedRect<T, Unit>
576
where
577
    T: Floor,
578
{
579
    fn floor(mut self) -> Self {
580
        self.origin = self.origin.floor();
581
        self.size = self.size.floor();
582
        self
583
    }
584
}
585

            
586
impl<T, Unit> SizedRect<T, Unit>
587
where
588
    T: Ceil + Floor,
589
{
590
    /// Returns a new rectangle that rounds the origin down using `floor` and
591
    /// rounds the size out using `ceil`.
592
    pub fn round_out(mut self) -> Self {
593
        self.origin = self.origin.floor();
594
        self.size = self.size.ceil();
595
        self
596
    }
597

            
598
    /// Returns a new rectangle that rounds the origin up using `ceil` and
599
    /// rounds the size in using `floor`.
600
    pub fn round_in(mut self) -> Self {
601
        self.origin = self.origin.ceil();
602
        self.size = self.size.floor();
603
        self
604
    }
605
}
606

            
607
impl<T, UnitA, UnitB> Mul<Scale<T, UnitA, UnitB>> for SizedRect<T, UnitA>
608
where
609
    T: Mul<T, Output = T> + Copy,
610
{
611
    type Output = SizedRect<T, UnitB>;
612

            
613
    fn mul(self, rhs: Scale<T, UnitA, UnitB>) -> Self::Output {
614
        SizedRect::new(self.origin * rhs, self.size * rhs)
615
    }
616
}
617

            
618
impl<T, UnitA, UnitB> Div<crate::Scale<T, UnitA, UnitB>> for SizedRect<T, UnitB>
619
where
620
    T: Div<T, Output = T> + Copy,
621
{
622
    type Output = SizedRect<T, UnitA>;
623

            
624
    fn div(self, rhs: crate::Scale<T, UnitA, UnitB>) -> Self::Output {
625
        SizedRect::new(self.origin / rhs, self.size / rhs)
626
    }
627
}
628

            
629
impl<T, Unit> crate::Approx<T> for SizedRect<T, Unit>
630
where
631
    T: approx::AbsDiffEq + Copy,
632
{
633
    fn approx_eq(&self, other: &Self) -> bool {
634
        self.origin.approx_eq(&other.origin) && self.size.approx_eq(&other.size)
635
    }
636
}
637

            
638
impl<T, Unit> approx::AbsDiffEq for SizedRect<T, Unit>
639
where
640
    T: approx::AbsDiffEq<Epsilon = T> + Copy,
641
{
642
    type Epsilon = T::Epsilon;
643

            
644
    fn default_epsilon() -> Self::Epsilon {
645
        T::default_epsilon()
646
    }
647

            
648
    fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
649
        self.origin.abs_diff_eq(&other.origin, epsilon)
650
            && self.size.abs_diff_eq(&other.size, epsilon)
651
    }
652

            
653
    fn abs_diff_ne(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
654
        self.origin.abs_diff_ne(&other.origin, epsilon)
655
            || self.size.abs_diff_ne(&other.size, epsilon)
656
    }
657
}
658

            
659
impl<T, Unit> approx::UlpsEq for SizedRect<T, Unit>
660
where
661
    T: approx::UlpsEq<Epsilon = T> + Copy,
662
{
663
    fn default_max_ulps() -> u32 {
664
        T::default_max_ulps()
665
    }
666

            
667
    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
668
        self.origin.ulps_eq(&other.origin, epsilon, max_ulps)
669
            && self.size.ulps_eq(&other.size, epsilon, max_ulps)
670
    }
671

            
672
    fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
673
        self.origin.ulps_ne(&other.origin, epsilon, max_ulps)
674
            || self.size.ulps_ne(&other.size, epsilon, max_ulps)
675
    }
676
}
677

            
678
impl<T, Unit> approx::RelativeEq for SizedRect<T, Unit>
679
where
680
    T: approx::RelativeEq<Epsilon = T> + Copy,
681
{
682
    fn default_max_relative() -> Self::Epsilon {
683
        T::default_max_relative()
684
    }
685

            
686
    fn relative_eq(
687
        &self,
688
        other: &Self,
689
        epsilon: Self::Epsilon,
690
        max_relative: Self::Epsilon,
691
    ) -> bool {
692
        self.origin
693
            .relative_eq(&other.origin, epsilon, max_relative)
694
            && self.size.relative_eq(&other.size, epsilon, max_relative)
695
    }
696

            
697
    fn relative_ne(
698
        &self,
699
        other: &Self,
700
        epsilon: Self::Epsilon,
701
        max_relative: Self::Epsilon,
702
    ) -> bool {
703
        self.origin
704
            .relative_ne(&other.origin, epsilon, max_relative)
705
            || self.size.relative_ne(&other.size, epsilon, max_relative)
706
    }
707
}
708

            
709
impl<T> Displayable<T> for SizedRect<T, Scaled>
710
where
711
    T: Div<T, Output = T> + Mul<T, Output = T> + Copy,
712
{
713
    type Pixels = SizedRect<T, Pixels>;
714
    type Points = SizedRect<T, Points>;
715
    type Scaled = Self;
716

            
717
    fn to_pixels(&self, scale: &DisplayScale<T>) -> Self::Pixels {
718
        *self * scale.total
719
    }
720

            
721
    fn to_points(&self, scale: &DisplayScale<T>) -> Self::Points {
722
        *self * scale.additional
723
    }
724

            
725
    fn to_scaled(&self, _scale: &DisplayScale<T>) -> Self::Scaled {
726
        *self
727
    }
728
}
729

            
730
impl<T> Displayable<T> for SizedRect<T, Points>
731
where
732
    T: Div<T, Output = T> + Mul<T, Output = T> + Copy,
733
{
734
    type Pixels = SizedRect<T, Pixels>;
735
    type Points = Self;
736
    type Scaled = SizedRect<T, Scaled>;
737

            
738
    fn to_pixels(&self, scale: &DisplayScale<T>) -> Self::Pixels {
739
        *self * scale.dpi
740
    }
741

            
742
    fn to_points(&self, _scale: &DisplayScale<T>) -> Self::Points {
743
        *self
744
    }
745

            
746
    fn to_scaled(&self, scale: &DisplayScale<T>) -> Self::Scaled {
747
        *self / scale.additional
748
    }
749
}
750

            
751
impl<T> Displayable<T> for SizedRect<T, Pixels>
752
where
753
    T: Div<T, Output = T> + Mul<T, Output = T> + Copy,
754
{
755
    type Pixels = Self;
756
    type Points = SizedRect<T, Points>;
757
    type Scaled = SizedRect<T, Scaled>;
758

            
759
    fn to_pixels(&self, _scale: &DisplayScale<T>) -> Self::Pixels {
760
        *self
761
    }
762

            
763
    fn to_points(&self, scale: &DisplayScale<T>) -> Self::Points {
764
        *self / scale.dpi
765
    }
766

            
767
    fn to_scaled(&self, scale: &DisplayScale<T>) -> Self::Scaled {
768
        *self / scale.total
769
    }
770
}
771

            
772
/// A rectangle that uses two [`Point`]s for representation.
773
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
774
pub struct ExtentsRect<T, Unit> {
775
    /// The origin of the rectangle.
776
    pub origin: Point<T, Unit>,
777
    /// The non-origin point of the rectangle.
778
    pub extent: Point<T, Unit>,
779
}
780

            
781
impl<T, Unit> Debug for ExtentsRect<T, Unit>
782
where
783
    T: Debug,
784
{
785
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
786
        f.debug_struct("SizedRect")
787
            .field("origin", &self.origin)
788
            .field("extent", &self.extent)
789
            .finish()
790
    }
791
}
792

            
793
impl<T, Unit> Copy for ExtentsRect<T, Unit> where T: Copy {}
794

            
795
impl<T, Unit> Clone for ExtentsRect<T, Unit>
796
where
797
    T: Clone,
798
{
799
    fn clone(&self) -> Self {
800
        Self {
801
            origin: self.origin.clone(),
802
            extent: self.extent.clone(),
803
        }
804
    }
805
}
806

            
807
impl<T, Unit> ExtentsRect<T, Unit> {
808
    /// Returns a new rectangle using `origin` and `extent`.
809
20
    pub fn new(origin: Point<T, Unit>, extent: Point<T, Unit>) -> Self {
810
20
        Self { origin, extent }
811
20
    }
812
}
813

            
814
impl<T, Unit> ExtentsRect<T, Unit>
815
where
816
    T: NumCast + Copy,
817
{
818
    /// Attempts to cast `T` to `NewT`. If unsuccessful, None is returned.
819
    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<ExtentsRect<NewT, Unit>> {
820
        Some(ExtentsRect::new(
821
            self.origin.try_cast()?,
822
            self.extent.try_cast()?,
823
        ))
824
    }
825

            
826
    /// Casts `T` to `NewT`.
827
    ///
828
    /// # Panics
829
    ///
830
    /// Panics if casting fails.
831
    pub fn cast<NewT: NumCast + Copy>(&self) -> ExtentsRect<NewT, Unit> {
832
        self.try_cast().expect("unable to cast")
833
    }
834
}
835

            
836
impl<T, Unit> ExtentsRect<T, Unit>
837
where
838
    T: Copy,
839
{
840
    /// Returns this value with the new unit. Does not affect the underlying
841
    /// value.
842
    pub fn cast_unit<NewUnit>(&self) -> ExtentsRect<T, NewUnit> {
843
        ExtentsRect::new(self.origin.cast_unit(), self.extent.cast_unit())
844
    }
845
}
846

            
847
impl<T, Unit> Eq for ExtentsRect<T, Unit> where T: Eq {}
848

            
849
impl<T, Unit> PartialEq for ExtentsRect<T, Unit>
850
where
851
    T: PartialEq,
852
{
853
2
    fn eq(&self, other: &Self) -> bool {
854
2
        self.origin.eq(&other.origin) && self.extent.eq(&other.extent)
855
2
    }
856
}
857

            
858
impl<T, Unit> Default for ExtentsRect<T, Unit>
859
where
860
    T: Default,
861
{
862
    fn default() -> Self {
863
        Self::new(Point::default(), Point::default())
864
    }
865
}
866

            
867
impl<T, Unit> Round for ExtentsRect<T, Unit>
868
where
869
    T: Round,
870
{
871
    fn round(mut self) -> Self {
872
        self.origin = self.origin.round();
873
        self.extent = self.extent.round();
874
        self
875
    }
876
}
877

            
878
impl<T, Unit> Ceil for ExtentsRect<T, Unit>
879
where
880
    T: Ceil,
881
{
882
    fn ceil(mut self) -> Self {
883
        self.origin = self.origin.ceil();
884
        self.extent = self.extent.ceil();
885
        self
886
    }
887
}
888

            
889
impl<T, Unit> Floor for ExtentsRect<T, Unit>
890
where
891
    T: Floor,
892
{
893
    fn floor(mut self) -> Self {
894
        self.origin = self.origin.floor();
895
        self.extent = self.extent.floor();
896
        self
897
    }
898
}
899

            
900
impl<T, Unit> ExtentsRect<T, Unit>
901
where
902
    T: Ceil + Floor,
903
{
904
    /// Returns a new rectangle that rounds the origin down using `floor` and
905
    /// rounds the extent out using `ceil`.
906
    pub fn round_out(mut self) -> Self {
907
        self.origin = self.origin.floor();
908
        self.extent = self.extent.ceil();
909
        self
910
    }
911

            
912
    /// Returns a new rectangle that rounds the origin up using `ceil` and
913
    /// rounds the extent in using `floor`.
914
    pub fn round_in(mut self) -> Self {
915
        self.origin = self.origin.ceil();
916
        self.extent = self.extent.floor();
917
        self
918
    }
919
}
920

            
921
impl<T, UnitA, UnitB> Mul<Scale<T, UnitA, UnitB>> for ExtentsRect<T, UnitA>
922
where
923
    T: Mul<T, Output = T> + Copy,
924
{
925
    type Output = ExtentsRect<T, UnitB>;
926

            
927
    fn mul(self, rhs: Scale<T, UnitA, UnitB>) -> Self::Output {
928
        ExtentsRect::new(self.origin * rhs, self.extent * rhs)
929
    }
930
}
931

            
932
impl<T, UnitA, UnitB> Div<crate::Scale<T, UnitA, UnitB>> for ExtentsRect<T, UnitB>
933
where
934
    T: Div<T, Output = T> + Copy,
935
{
936
    type Output = ExtentsRect<T, UnitA>;
937

            
938
    fn div(self, rhs: crate::Scale<T, UnitA, UnitB>) -> Self::Output {
939
        ExtentsRect::new(self.origin / rhs, self.extent / rhs)
940
    }
941
}
942

            
943
impl<T, Unit> crate::Approx<T> for ExtentsRect<T, Unit>
944
where
945
    T: approx::AbsDiffEq + Copy,
946
{
947
    fn approx_eq(&self, other: &Self) -> bool {
948
        self.origin.approx_eq(&other.origin) && self.extent.approx_eq(&other.extent)
949
    }
950
}
951

            
952
impl<T, Unit> approx::AbsDiffEq for ExtentsRect<T, Unit>
953
where
954
    T: approx::AbsDiffEq<Epsilon = T> + Copy,
955
{
956
    type Epsilon = T::Epsilon;
957

            
958
    fn default_epsilon() -> Self::Epsilon {
959
        T::default_epsilon()
960
    }
961

            
962
    fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
963
        self.origin.abs_diff_eq(&other.origin, epsilon)
964
            && self.extent.abs_diff_eq(&other.extent, epsilon)
965
    }
966

            
967
    fn abs_diff_ne(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
968
        self.origin.abs_diff_ne(&other.origin, epsilon)
969
            || self.extent.abs_diff_ne(&other.extent, epsilon)
970
    }
971
}
972

            
973
impl<T, Unit> approx::UlpsEq for ExtentsRect<T, Unit>
974
where
975
    T: approx::UlpsEq<Epsilon = T> + Copy,
976
{
977
    fn default_max_ulps() -> u32 {
978
        T::default_max_ulps()
979
    }
980

            
981
    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
982
        self.origin.ulps_eq(&other.origin, epsilon, max_ulps)
983
            && self.extent.ulps_eq(&other.extent, epsilon, max_ulps)
984
    }
985

            
986
    fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
987
        self.origin.ulps_ne(&other.origin, epsilon, max_ulps)
988
            || self.extent.ulps_ne(&other.extent, epsilon, max_ulps)
989
    }
990
}
991

            
992
impl<T, Unit> approx::RelativeEq for ExtentsRect<T, Unit>
993
where
994
    T: approx::RelativeEq<Epsilon = T> + Copy,
995
{
996
    fn default_max_relative() -> Self::Epsilon {
997
        T::default_max_relative()
998
    }
999

            
    fn relative_eq(
        &self,
        other: &Self,
        epsilon: Self::Epsilon,
        max_relative: Self::Epsilon,
    ) -> bool {
        self.origin
            .relative_eq(&other.origin, epsilon, max_relative)
            && self
                .extent
                .relative_eq(&other.extent, epsilon, max_relative)
    }

            
    fn relative_ne(
        &self,
        other: &Self,
        epsilon: Self::Epsilon,
        max_relative: Self::Epsilon,
    ) -> bool {
        self.origin
            .relative_ne(&other.origin, epsilon, max_relative)
            || self
                .extent
                .relative_ne(&other.extent, epsilon, max_relative)
    }
}

            
impl<T> Displayable<T> for ExtentsRect<T, Scaled>
where
    T: Div<T, Output = T> + Mul<T, Output = T> + Copy,
{
    type Pixels = ExtentsRect<T, Pixels>;
    type Points = ExtentsRect<T, Points>;
    type Scaled = Self;

            
    fn to_pixels(&self, scale: &DisplayScale<T>) -> Self::Pixels {
        *self * scale.total
    }

            
    fn to_points(&self, scale: &DisplayScale<T>) -> Self::Points {
        *self * scale.additional
    }

            
    fn to_scaled(&self, _scale: &DisplayScale<T>) -> Self::Scaled {
        *self
    }
}

            
impl<T> Displayable<T> for ExtentsRect<T, Points>
where
    T: Div<T, Output = T> + Mul<T, Output = T> + Copy,
{
    type Pixels = ExtentsRect<T, Pixels>;
    type Points = Self;
    type Scaled = ExtentsRect<T, Scaled>;

            
    fn to_pixels(&self, scale: &DisplayScale<T>) -> Self::Pixels {
        *self * scale.dpi
    }

            
    fn to_points(&self, _scale: &DisplayScale<T>) -> Self::Points {
        *self
    }

            
    fn to_scaled(&self, scale: &DisplayScale<T>) -> Self::Scaled {
        *self / scale.additional
    }
}

            
impl<T> Displayable<T> for ExtentsRect<T, Pixels>
where
    T: Div<T, Output = T> + Mul<T, Output = T> + Copy,
{
    type Pixels = Self;
    type Points = ExtentsRect<T, Points>;
    type Scaled = ExtentsRect<T, Scaled>;

            
    fn to_pixels(&self, _scale: &DisplayScale<T>) -> Self::Pixels {
        *self
    }

            
    fn to_points(&self, scale: &DisplayScale<T>) -> Self::Points {
        *self / scale.dpi
    }

            
    fn to_scaled(&self, scale: &DisplayScale<T>) -> Self::Scaled {
        *self / scale.total
    }
}

            
/// Functionalitiy that all rectangle types implement
pub trait Rectlike<T, Unit>: Sized
where
    T: Zero
        + PartialOrd
        + Mul<T, Output = T>
        + Sub<T, Output = T>
        + One
        + Add<T, Output = T>
        + Div<T, Output = T>
        + Copy,
{
    /// Returns this rectangle as a `Rect`. The rectangle's underlying data will
    /// be unchanged by this operation.
    fn as_rect(&self) -> Rect<T, Unit>;
    /// Returns this rectangle converted to an [`ExtentsRect`].
    fn as_extents(&self) -> ExtentsRect<T, Unit>;
    /// Returns this rectangle converted to a [`SizedRect`].
    fn as_sized(&self) -> SizedRect<T, Unit>;

            
    /// Checks to see if this rect is empty. If it is, None is returned. If it
    /// isn't, the rect is returned unmodified.
1
    fn to_non_empty(self) -> Option<Self> {
1
        if self.is_empty() {
            None
        } else {
1
            Some(self)
        }
1
    }

            
    /// Returns true if the rect doesn't have a positive width and height.
1
    fn is_empty(&self) -> bool {
1
        let zero = T::zero();
1
        !(self.width().get() > zero && self.height().get() > zero)
1
    }

            
    /// Returns the area contained by this rectangle.
    fn area(&self) -> Figure<T, Unit> {
        self.width() * self.height()
    }

            
    /// Returns the width of the rectangle.
    fn width(&self) -> Figure<T, Unit>;
    /// Returns the height of the rectangle.
    fn height(&self) -> Figure<T, Unit>;

            
    /// Returns the size of the rectangle.
    fn size(&self) -> Size<T, Unit> {
        Size::from_figures(self.width(), self.height())
    }

            
    /// Returns the origin of the rectangle.
    fn origin(&self) -> Point<T, Unit>;

            
    /// Returns the center of the rectangle.
    fn center(&self) -> Point<T, Unit> {
        self.origin() + self.size() / (T::one() + T::one())
    }

            
    /// Returns true if `point` is within this rectangle.
14
    fn contains(&self, point: Point<T, Unit>) -> bool {
14
        let extents = self.as_extents();
14
        extents.origin.x <= point.x
12
            && extents.origin.y <= point.y
10
            && extents.extent.x >= point.x
8
            && extents.extent.y >= point.y
14
    }

            
    /// Moves this rectangle by the vector provided.
    fn translate<V: Into<Vector<T, Unit>>>(&self, by: V) -> Self;

            
    /// Increases the size of this rectangle by the vector provided. The rectangle will grow around its center.
    fn inflate<V: Into<Vector<T, Unit>>>(&self, by: V) -> Self;

            
    /// Returns the intersecting area between the two rectangles. If the
    /// rectangles do not intersect, None is returned.
1
    fn intersection<R: Rectlike<T, Unit>>(&self, other: &R) -> Option<ExtentsRect<T, Unit>> {
1
        let r1 = self.as_extents();
1
        let r2 = other.as_extents();
1
        ExtentsRect::new(r1.origin.max(&r2.origin), r1.extent.min(&r2.extent)).to_non_empty()
1
    }

            
    /// Returns the union of the two rectangles. If both rectangles aren't
    /// empty, the smallest rectangle that both rectangles can fit into will be
    /// returned. If either rectangle is empty, the other rectangle is returned
    /// unmodified.
    fn union<R: Rectlike<T, Unit>>(&self, other: &R) -> Option<ExtentsRect<T, Unit>> {
        match (
            self.as_extents().to_non_empty(),
            other.as_extents().to_non_empty(),
        ) {
            (Some(r1), Some(r2)) => {
                ExtentsRect::new(r1.origin.min(&r2.origin), r1.extent.max(&r2.extent))
                    .to_non_empty()
            }
            (Some(r), None) | (None, Some(r)) => Some(r),
            (None, None) => None,
        }
    }
}

            
impl<T, Unit> Rectlike<T, Unit> for Rect<T, Unit>
where
    T: Zero
        + PartialOrd
        + Mul<T, Output = T>
        + Sub<T, Output = T>
        + One
        + Add<T, Output = T>
        + Div<T, Output = T>
        + Copy,
{
    fn as_rect(&self) -> Rect<T, Unit> {
        *self
    }

            
    fn as_extents(&self) -> ExtentsRect<T, Unit> {
        match self {
            Rect::Sized(sized) => sized.as_extents(),
            Rect::Extents(extents) => extents.as_extents(),
        }
    }

            
    fn as_sized(&self) -> SizedRect<T, Unit> {
        match self {
            Rect::Sized(sized) => sized.as_sized(),
            Rect::Extents(extents) => extents.as_sized(),
        }
    }

            
    fn width(&self) -> Figure<T, Unit> {
        match self {
            Rect::Sized(sized) => sized.width(),
            Rect::Extents(extents) => extents.width(),
        }
    }

            
    fn height(&self) -> Figure<T, Unit> {
        match self {
            Rect::Sized(sized) => sized.height(),
            Rect::Extents(extents) => extents.height(),
        }
    }

            
    fn origin(&self) -> Point<T, Unit> {
        match self {
            Rect::Sized(sized) => sized.origin(),
            Rect::Extents(extents) => extents.origin(),
        }
    }

            
    fn translate<V: Into<Vector<T, Unit>>>(&self, by: V) -> Self {
        match self {
            Rect::Sized(sized) => Rect::Sized(sized.translate(by)),
            Rect::Extents(extents) => Rect::Extents(extents.translate(by)),
        }
    }

            
    fn inflate<V: Into<Vector<T, Unit>>>(&self, by: V) -> Self {
        match self {
            Rect::Sized(sized) => Rect::Sized(sized.inflate(by)),
            Rect::Extents(extents) => Rect::Extents(extents.inflate(by)),
        }
    }
}

            
impl<T, Unit> Rectlike<T, Unit> for ExtentsRect<T, Unit>
where
    T: Zero
        + PartialOrd
        + Mul<T, Output = T>
        + Sub<T, Output = T>
        + One
        + Add<T, Output = T>
        + Div<T, Output = T>
        + Copy,
{
    fn as_rect(&self) -> Rect<T, Unit> {
        Rect::Extents(*self)
    }

            
    fn as_extents(&self) -> Self {
        *self
    }

            
    fn as_sized(&self) -> SizedRect<T, Unit> {
        SizedRect::new(
            self.origin,
            (self.extent.to_vector() - self.origin.to_vector()).to_size(),
        )
    }

            
1
    fn width(&self) -> Figure<T, Unit> {
1
        self.extent.x() - self.origin.x()
1
    }

            
1
    fn height(&self) -> Figure<T, Unit> {
1
        self.extent.y() - self.origin.y()
1
    }

            
    fn origin(&self) -> Point<T, Unit> {
        self.origin
    }

            
    fn translate<V: Into<Vector<T, Unit>>>(&self, by: V) -> Self {
        let by = by.into();
        Self {
            origin: self.origin + by,
            extent: self.extent + by,
        }
    }

            
1
    fn inflate<V: Into<Vector<T, Unit>>>(&self, by: V) -> Self {
1
        let half = by.into() / (T::one() + T::one());
1
        Self {
1
            origin: self.origin - half,
1
            extent: self.extent + half,
1
        }
1
    }
}

            
impl<T, Unit> Rectlike<T, Unit> for SizedRect<T, Unit>
where
    T: Zero
        + PartialOrd
        + Mul<T, Output = T>
        + Sub<T, Output = T>
        + One
        + Add<T, Output = T>
        + Div<T, Output = T>
        + Copy,
{
    fn as_rect(&self) -> Rect<T, Unit> {
        Rect::Sized(*self)
    }

            
18
    fn as_extents(&self) -> ExtentsRect<T, Unit> {
18
        ExtentsRect::new(self.origin, self.origin + self.size)
18
    }

            
    fn as_sized(&self) -> Self {
        *self
    }

            
    fn width(&self) -> Figure<T, Unit> {
        self.size.width()
    }

            
    fn height(&self) -> Figure<T, Unit> {
        self.size.height()
    }

            
    fn origin(&self) -> Point<T, Unit> {
        self.origin
    }

            
    fn translate<V: Into<Vector<T, Unit>>>(&self, by: V) -> Self {
        let by = by.into();
        Self {
            origin: self.origin + by,
            size: self.size,
        }
    }

            
1
    fn inflate<V: Into<Vector<T, Unit>>>(&self, by: V) -> Self {
1
        let by = by.into();
1
        let half = by / (T::one() + T::one());
1
        Self {
1
            origin: self.origin - half,
1
            size: self.size + by,
1
        }
1
    }
}

            
1
#[test]
1
fn intersection_tests() {
1
    let a = SizedRect::<u32, ()>::new(Point::new(10, 20), Size::new(90, 80));
1
    let b = SizedRect::new(Point::new(50, 50), Size::new(50, 50));
1
    assert_eq!(
1
        a.intersection(&b),
1
        Some(ExtentsRect::new(Point::new(50, 50), Point::new(100, 100)))
1
    );
1
}

            
1
#[test]
1
fn contains_test() {
1
    let a = SizedRect::<u32, ()>::new(Point::new(10, 20), Size::new(30, 40));
1
    assert!(a.contains(Point::new(10, 20)));
1
    assert!(a.contains(Point::new(11, 20)));
1
    assert!(a.contains(Point::new(10, 21)));
1
    assert!(a.contains(Point::new(40, 60)));
1
    assert!(a.contains(Point::new(39, 60)));
1
    assert!(a.contains(Point::new(40, 59)));
1
    assert!(!a.contains(Point::new(9, 20)));
1
    assert!(!a.contains(Point::new(10, 19)));
1
    assert!(!a.contains(Point::new(41, 20)));
1
    assert!(!a.contains(Point::new(40, 19)));
1
    assert!(!a.contains(Point::new(9, 60)));
1
    assert!(!a.contains(Point::new(10, 61)));
1
    assert!(!a.contains(Point::new(41, 60)));
1
    assert!(!a.contains(Point::new(40, 61)));
1
}

            
1
#[test]
1
fn inflation_tests() {
1
    let a = SizedRect::<u32, ()>::new(Point::new(2, 3), Size::new(4, 5));
1
    let inflated = a.inflate(Vector::new(2, 2));
1
    assert_eq!(inflated, SizedRect::new(Point::new(1, 2), Size::new(6, 7)));
1
    assert_eq!(
1
        a.as_extents().inflate(Vector::new(2, 2)),
1
        inflated.as_extents()
1
    );
1
}