1use std::{
2 cmp::{max, min},
3 mem,
4};
5
6use crate::{
7 interop,
8 prelude::*,
9 private::{
10 is_finite,
11 safe32::{sk32, sk64},
12 },
13 Contains, IPoint, ISize, IVector, PathDirection, Point, Size, Vector,
14};
15use skia_bindings::{self as sb, SkIRect, SkRect};
16
17#[repr(C)]
18#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
19pub struct IRect {
20 pub left: i32,
22 pub top: i32,
24 pub right: i32,
26 pub bottom: i32,
28}
29
30native_transmutable!(SkIRect, IRect);
31
32impl AsRef<IRect> for IRect {
33 fn as_ref(&self) -> &IRect {
34 self
35 }
36}
37
38impl IRect {
39 pub const fn new(left: i32, top: i32, right: i32, bottom: i32) -> Self {
40 Self {
41 left,
42 top,
43 right,
44 bottom,
45 }
46 }
47
48 #[must_use]
49 pub const fn new_empty() -> Self {
50 Self::new(0, 0, 0, 0)
51 }
52
53 #[must_use]
54 pub fn from_wh(w: i32, h: i32) -> Self {
55 Self::from_size((w, h))
56 }
57
58 #[must_use]
59 pub fn from_size(size: impl Into<ISize>) -> Self {
60 let size = size.into();
61 Self::new(0, 0, size.width, size.height)
62 }
63
64 #[must_use]
65 pub fn from_pt_size(pt: impl Into<IPoint>, size: impl Into<ISize>) -> Self {
66 let pt = pt.into();
67 let size = size.into();
68 Self::from_xywh(pt.x, pt.y, size.width, size.height)
69 }
70
71 #[must_use]
72 pub const fn from_ltrb(l: i32, t: i32, r: i32, b: i32) -> Self {
73 Self::new(l, t, r, b)
74 }
75
76 #[must_use]
77 pub fn from_xywh(x: i32, y: i32, w: i32, h: i32) -> Self {
78 IRect {
79 left: x,
80 top: y,
81 right: sk32::sat_add(x, w),
82 bottom: sk32::sat_add(y, h),
83 }
84 }
85
86 pub const fn left(&self) -> i32 {
87 self.left
88 }
89
90 pub const fn top(&self) -> i32 {
91 self.top
92 }
93
94 pub const fn right(&self) -> i32 {
95 self.right
96 }
97
98 pub const fn bottom(&self) -> i32 {
99 self.bottom
100 }
101
102 pub const fn x(&self) -> i32 {
103 self.left
104 }
105
106 pub const fn y(&self) -> i32 {
107 self.top
108 }
109
110 pub const fn width(&self) -> i32 {
111 sk32::can_overflow_sub(self.right, self.left)
112 }
113
114 pub const fn height(&self) -> i32 {
115 sk32::can_overflow_sub(self.bottom, self.top)
116 }
117
118 pub const fn size(&self) -> ISize {
119 ISize::new(self.width(), self.height())
120 }
121
122 pub const fn width_64(&self) -> i64 {
123 self.right as i64 - self.left as i64
124 }
125
126 pub const fn height_64(&self) -> i64 {
127 self.bottom as i64 - self.top as i64
128 }
129
130 pub fn is_empty_64(&self) -> bool {
131 self.right <= self.left || self.bottom <= self.top
132 }
133
134 pub fn is_empty(&self) -> bool {
135 unsafe { sb::C_SkIRect_isEmpty(self.native()) }
136 }
137
138 pub fn set_empty(&mut self) {
139 *self = Self::new_empty()
140 }
141
142 pub fn set_ltrb(&mut self, left: i32, top: i32, right: i32, bottom: i32) {
143 *self = Self::new(left, top, right, bottom);
144 }
145
146 pub fn set_xywh(&mut self, x: i32, y: i32, w: i32, h: i32) {
147 *self = Self::from_xywh(x, y, w, h);
148 }
149
150 pub fn set_wh(&mut self, width: i32, height: i32) {
151 self.left = 0;
152 self.top = 0;
153 self.right = width;
154 self.bottom = height;
155 }
156
157 pub fn set_size(&mut self, size: impl Into<ISize>) {
158 let size = size.into();
159 self.left = 0;
160 self.top = 0;
161 self.right = size.width;
162 self.bottom = size.height;
163 }
164
165 #[must_use]
166 pub fn with_offset(&self, delta: impl Into<IVector>) -> Self {
167 let mut copied = *self;
168 copied.offset(delta);
169 copied
170 }
171
172 #[must_use]
173 pub fn with_inset(&self, delta: impl Into<IVector>) -> Self {
174 self.with_outset(-delta.into())
175 }
176
177 #[must_use]
178 pub fn with_outset(&self, delta: impl Into<IVector>) -> Self {
179 let delta = delta.into();
180 let (dx, dy) = (delta.x, delta.y);
181 IRect::new(
182 sk32::sat_sub(self.left, dx),
183 sk32::sat_sub(self.top, dy),
184 sk32::sat_add(self.right, dx),
185 sk32::sat_add(self.bottom, dy),
186 )
187 }
188
189 pub fn offset(&mut self, delta: impl Into<IPoint>) {
190 let delta = delta.into();
191 let (dx, dy) = (delta.x, delta.y);
192
193 self.left = sk32::sat_add(self.left, dx);
194 self.top = sk32::sat_add(self.top, dy);
195 self.right = sk32::sat_add(self.right, dx);
196 self.bottom = sk32::sat_add(self.bottom, dy);
197 }
198
199 pub fn offset_to(&mut self, new_p: impl Into<IPoint>) {
200 *self = self.with_offset_to(new_p)
201 }
202
203 #[must_use]
204 pub fn with_offset_to(&self, new_p: impl Into<IPoint>) -> Self {
205 let new_p = new_p.into();
206 let (new_x, new_y) = (new_p.x, new_p.y);
207
208 IRect::new(
209 sk64::pin_to_s32(i64::from(self.right) + i64::from(new_x) - i64::from(self.left)),
210 sk64::pin_to_s32(i64::from(self.bottom) + i64::from(new_y) - i64::from(self.top)),
211 new_x,
212 new_y,
213 )
214 }
215
216 pub fn inset(&mut self, delta: impl Into<IVector>) {
217 *self = self.with_inset(delta)
218 }
219
220 pub fn outset(&mut self, delta: impl Into<IVector>) {
221 *self = self.with_outset(delta)
222 }
223
224 #[must_use]
225 pub fn with_adjustment(&self, d_l: i32, d_t: i32, d_r: i32, d_b: i32) -> Self {
226 IRect::new(
227 sk32::sat_add(self.left, d_l),
228 sk32::sat_add(self.top, d_t),
229 sk32::sat_add(self.right, d_r),
230 sk32::sat_add(self.bottom, d_b),
231 )
232 }
233
234 pub fn adjust(&mut self, d_l: i32, d_t: i32, d_r: i32, d_b: i32) {
235 *self = self.with_adjustment(d_l, d_t, d_r, d_b)
236 }
237
238 pub fn contains_no_empty_check(&self, r: &Self) -> bool {
241 debug_assert!(self.left < self.right && self.top < self.bottom);
242 debug_assert!(r.left < r.right && r.top < r.bottom);
243
244 self.left <= r.left && self.top <= r.top && self.right >= r.right && self.bottom >= r.bottom
245 }
246
247 #[must_use]
248 pub fn intersect(a: &Self, b: &Self) -> Option<Self> {
249 let mut r = Self::default();
250 unsafe { r.native_mut().intersect(a.native(), b.native()) }.then_some(r)
251 }
252
253 pub fn intersects(a: &Self, b: &Self) -> bool {
254 Self::intersect(a, b).is_some()
255 }
256
257 pub fn intersect_no_empty_check_(a: &Self, b: &Self) -> Option<Self> {
258 debug_assert!(!a.is_empty_64() && !b.is_empty_64());
259 let r = IRect::new(
260 max(a.left, b.left),
261 max(a.top, b.top),
262 min(a.right, b.right),
263 min(a.bottom, b.bottom),
264 );
265 (!r.is_empty()).then_some(r)
266 }
267
268 pub fn join(a: &Self, b: &Self) -> Self {
269 let mut copied = *a;
270 unsafe { copied.native_mut().join(b.native()) }
271 copied
272 }
273
274 pub fn sort(&mut self) {
275 *self = self.sorted()
276 }
277
278 #[must_use]
279 pub fn sorted(&self) -> Self {
280 Self::new(
281 min(self.left, self.right),
282 min(self.top, self.bottom),
283 max(self.left, self.right),
284 max(self.top, self.bottom),
285 )
286 }
287
288 pub fn as_i32s(&self) -> &[i32] {
289 unsafe { safer::from_raw_parts(&self.left, 4) }
290 }
291
292 #[deprecated(since = "0.27.0", note = "removed without replacement")]
293 #[must_use]
294 pub fn empty() -> &'static Self {
295 &EMPTY_IRECT
296 }
297}
298
299pub const EMPTY_IRECT: IRect = IRect {
300 left: 0,
301 top: 0,
302 right: 0,
303 bottom: 0,
304};
305
306impl Contains<IPoint> for IRect {
307 fn contains(&self, other: IPoint) -> bool {
308 let (x, y) = (other.x, other.y);
309 x >= self.left && x < self.right && y >= self.top && y < self.bottom
310 }
311}
312
313impl Contains<&IRect> for IRect {
314 fn contains(&self, r: &IRect) -> bool {
315 !r.is_empty()
316 && !self.is_empty()
317 && self.left <= r.left
318 && self.top <= r.top
319 && self.right >= r.right
320 && self.bottom >= r.bottom
321 }
322}
323
324impl Contains<&Rect> for IRect {
325 fn contains(&self, other: &Rect) -> bool {
326 unsafe { sb::C_SkIRect_contains(self.native(), other.native()) }
327 }
328}
329
330impl Contains<IRect> for IRect {
331 fn contains(&self, other: IRect) -> bool {
332 self.contains(&other)
333 }
334}
335
336impl Contains<Rect> for IRect {
337 fn contains(&self, other: Rect) -> bool {
338 self.contains(&other)
339 }
340}
341
342#[repr(C)]
343#[derive(Copy, Clone, PartialEq, Default, Debug)]
344pub struct Rect {
345 pub left: f32,
347 pub top: f32,
349 pub right: f32,
351 pub bottom: f32,
353}
354
355native_transmutable!(SkRect, Rect);
356
357impl AsRef<Rect> for Rect {
358 fn as_ref(&self) -> &Rect {
359 self
360 }
361}
362
363impl Rect {
364 #[must_use]
365 pub fn new(left: f32, top: f32, right: f32, bottom: f32) -> Self {
366 Self {
367 left,
368 top,
369 right,
370 bottom,
371 }
372 }
373
374 pub fn new_empty() -> Self {
375 Self::new(0.0, 0.0, 0.0, 0.0)
376 }
377
378 #[must_use]
379 pub fn from_wh(w: f32, h: f32) -> Self {
380 Self::new(0.0, 0.0, w, h)
381 }
382
383 #[must_use]
384 pub fn from_iwh(w: i32, h: i32) -> Self {
385 Self::from_wh(w as f32, h as f32)
386 }
387
388 #[must_use]
389 pub fn from_size(size: impl Into<Size>) -> Self {
390 (Point::default(), size.into()).into()
391 }
392
393 #[must_use]
394 pub fn from_ltrb(l: f32, t: f32, r: f32, b: f32) -> Self {
395 Self::new(l, t, r, b)
396 }
397
398 #[must_use]
399 pub fn from_xywh(x: f32, y: f32, w: f32, h: f32) -> Self {
400 Self::new(x, y, x + w, y + h)
401 }
402
403 #[must_use]
404 pub fn from_point_and_size(p: impl Into<Point>, sz: impl Into<Size>) -> Self {
405 (p.into(), sz.into()).into()
406 }
407
408 #[must_use]
409 pub fn from_isize(isize: impl Into<ISize>) -> Self {
410 let isize = isize.into();
411 Self::from_iwh(isize.width, isize.height)
412 }
413
414 #[must_use]
415 pub fn from_irect(irect: impl AsRef<IRect>) -> Self {
416 let irect = irect.as_ref();
417 Self::new(
418 irect.left as f32,
419 irect.top as f32,
420 irect.right as f32,
421 irect.bottom as f32,
422 )
423 }
424
425 pub fn is_empty(&self) -> bool {
426 !(self.left < self.right && self.top < self.bottom)
429 }
430
431 pub fn is_sorted(&self) -> bool {
432 self.left <= self.right && self.top <= self.bottom
433 }
434
435 pub fn is_finite(&self) -> bool {
436 is_finite(&[self.left, self.top, self.right, self.bottom])
437 }
438
439 pub const fn x(&self) -> f32 {
440 self.left
441 }
442
443 pub const fn y(&self) -> f32 {
444 self.top
445 }
446
447 pub const fn left(&self) -> f32 {
448 self.left
449 }
450
451 pub const fn top(&self) -> f32 {
452 self.top
453 }
454
455 pub const fn right(&self) -> f32 {
456 self.right
457 }
458
459 pub const fn bottom(&self) -> f32 {
460 self.bottom
461 }
462
463 pub fn size(&self) -> Size {
464 (self.width(), self.height()).into()
465 }
466
467 pub fn width(&self) -> f32 {
468 self.native().fRight - self.native().fLeft
469 }
470
471 pub fn height(&self) -> f32 {
472 self.native().fBottom - self.native().fTop
473 }
474
475 pub fn center_x(&self) -> f32 {
476 self.left * 0.5 + self.right * 0.5
478 }
479
480 pub fn center_y(&self) -> f32 {
481 self.top * 0.5 + self.bottom * 0.5
483 }
484
485 pub fn center(&self) -> Point {
486 Point::from((self.center_x(), self.center_y()))
487 }
488
489 pub fn tl(&self) -> Point {
490 Point::from((self.left, self.top))
491 }
492
493 pub fn tr(&self) -> Point {
494 Point::from((self.right, self.top))
495 }
496
497 pub fn bl(&self) -> Point {
498 Point::from((self.left, self.bottom))
499 }
500
501 pub fn br(&self) -> Point {
502 Point::from((self.right, self.bottom))
503 }
504
505 pub fn to_quad(&self, dir: impl Into<Option<PathDirection>>) -> [Point; 4] {
506 let mut pts = [Point::default(); 4];
507 self.copy_to_quad(&mut pts, dir);
508 pts
509 }
510
511 pub fn copy_to_quad(&self, pts: &mut [Point], dir: impl Into<Option<PathDirection>>) {
512 debug_assert!(pts.len() >= 4);
513 pts[0] = self.tl();
514 pts[2] = self.br();
515 match dir.into().unwrap_or(PathDirection::CW) {
516 PathDirection::CW => {
517 pts[1] = self.tr();
518 pts[3] = self.bl();
519 }
520 PathDirection::CCW => {
521 pts[1] = self.bl();
522 pts[3] = self.tr();
523 }
524 }
525 }
526
527 pub fn set_empty(&mut self) {
528 *self = Self::new_empty()
529 }
530
531 pub fn set_irect(&mut self, irect: impl AsRef<IRect>) {
533 *self = Self::from_irect(irect)
534 }
535
536 pub fn set_ltrb(&mut self, left: f32, top: f32, right: f32, bottom: f32) {
537 *self = Self::new(left, top, right, bottom)
538 }
539
540 pub fn bounds(pts: &[Point]) -> Option<Rect> {
541 let mut bounds = Rect::default();
542 unsafe { sb::C_SkRect_Bounds(pts.native().as_ptr(), pts.len(), bounds.native_mut()) }
543 .then_some(bounds)
544 }
545
546 pub fn bounds_or_empty(pts: &[Point]) -> Rect {
547 Self::bounds(pts).unwrap_or_else(Self::new_empty)
548 }
549
550 pub fn set_bounds(&mut self, points: &[Point]) {
551 self.set_bounds_check(points);
552 }
553
554 pub fn set_bounds_check(&mut self, points: &[Point]) -> bool {
555 unsafe {
556 sb::C_SkRect_setBoundsCheck(self.native_mut(), points.native().as_ptr(), points.len())
557 }
558 }
559
560 pub fn set_bounds_no_check(&mut self, points: &[Point]) {
561 unsafe {
562 sb::C_SkRect_setBoundsNoCheck(self.native_mut(), points.native().as_ptr(), points.len())
563 }
564 }
565
566 pub fn set_bounds2(&mut self, p0: impl Into<Point>, p1: impl Into<Point>) {
567 let (p0, p1) = (p0.into(), p1.into());
568 self.left = p0.x.min(p1.x);
569 self.right = p0.x.max(p1.x);
570 self.top = p0.y.min(p1.y);
571 self.bottom = p0.y.max(p1.y);
572 }
573
574 pub fn from_bounds(points: &[Point]) -> Option<Self> {
575 let mut r = Self::default();
576 r.set_bounds_check(points).then_some(r)
577 }
578
579 pub fn set_xywh(&mut self, x: f32, y: f32, width: f32, height: f32) {
580 *self = Self::from_xywh(x, y, width, height)
581 }
582
583 pub fn set_wh(&mut self, w: f32, h: f32) {
584 *self = Self::from_wh(w, h)
585 }
586
587 pub fn set_iwh(&mut self, width: i32, height: i32) {
588 *self = Self::from_iwh(width, height)
589 }
590
591 #[must_use]
592 pub fn with_offset(&self, d: impl Into<Vector>) -> Self {
593 let d = d.into();
594 Self::new(
595 self.left + d.x,
596 self.top + d.y,
597 self.right + d.x,
598 self.bottom + d.y,
599 )
600 }
601
602 #[must_use]
603 pub fn with_inset(&self, d: impl Into<Vector>) -> Self {
604 let d = d.into();
605 Self::new(
606 self.left + d.x,
607 self.top + d.y,
608 self.right - d.x,
609 self.bottom - d.y,
610 )
611 }
612
613 #[must_use]
614 pub fn with_outset(&self, d: impl Into<Vector>) -> Self {
615 let d = d.into();
616 Self::new(
617 self.left - d.x,
618 self.top - d.y,
619 self.right + d.x,
620 self.bottom + d.y,
621 )
622 }
623
624 pub fn offset(&mut self, d: impl Into<Vector>) {
625 *self = self.with_offset(d)
626 }
627
628 pub fn offset_to(&mut self, new_p: impl Into<Point>) {
629 *self = self.with_offset_to(new_p)
630 }
631
632 #[must_use]
633 pub fn with_offset_to(&self, new_p: impl Into<Point>) -> Self {
634 let new_p = new_p.into();
635 Self::new(new_p.x, new_p.y, new_p.x - self.left, new_p.y - self.top)
636 }
637
638 pub fn inset(&mut self, d: impl Into<Vector>) {
639 *self = self.with_inset(d)
640 }
641
642 pub fn outset(&mut self, d: impl Into<Vector>) {
643 *self = self.with_outset(d)
644 }
645
646 pub fn intersect(&mut self, r: impl AsRef<Rect>) -> bool {
647 unsafe { self.native_mut().intersect(r.as_ref().native()) }
648 }
649
650 #[must_use]
651 pub fn intersect2(&mut self, a: impl AsRef<Rect>, b: impl AsRef<Rect>) -> bool {
652 unsafe {
653 self.native_mut()
654 .intersect1(a.as_ref().native(), b.as_ref().native())
655 }
656 }
657
658 pub fn intersects(&self, r: impl AsRef<Rect>) -> bool {
659 let r = r.as_ref();
660 Self::intersects_(
661 self.left,
662 self.top,
663 self.right,
664 self.bottom,
665 r.left,
666 r.top,
667 r.right,
668 r.bottom,
669 )
670 }
671
672 pub fn intersects2(a: impl AsRef<Rect>, b: impl AsRef<Rect>) -> bool {
673 a.as_ref().intersects(b)
674 }
675
676 #[allow(clippy::too_many_arguments)]
677 fn intersects_(al: f32, at: f32, ar: f32, ab: f32, bl: f32, bt: f32, br: f32, bb: f32) -> bool {
678 let l = al.max(bl);
679 let r = ar.min(br);
680 let t = at.max(bt);
681 let b = ab.min(bb);
682 l < r && t < b
683 }
684
685 pub fn join(&mut self, r: impl AsRef<Rect>) {
686 let r = r.as_ref();
687 unsafe { self.native_mut().join(r.native()) }
688 }
689
690 pub fn join2(a: impl AsRef<Rect>, b: impl AsRef<Rect>) -> Rect {
691 let mut result = *a.as_ref();
692 result.join(b);
693 result
694 }
695
696 pub fn join_non_empty_arg(&mut self, r: impl AsRef<Rect>) {
697 let r = r.as_ref();
698 debug_assert!(!r.is_empty());
699 if self.left >= self.right || self.top >= self.bottom {
700 *self = *r;
701 } else {
702 self.join_possibly_empty_rect(r);
703 }
704 }
705
706 pub fn join_possibly_empty_rect(&mut self, r: impl AsRef<Rect>) {
707 let r = r.as_ref();
708 self.left = self.left.min(r.left);
709 self.top = self.top.min(r.top);
710 self.right = self.right.max(r.right);
711 self.bottom = self.bottom.max(r.bottom);
712 }
713
714 #[must_use]
717 pub fn round(&self) -> IRect {
718 let mut r = IRect::default();
719 unsafe { sb::C_SkRect_round(self.native(), r.native_mut()) };
720 r
721 }
722
723 #[must_use]
726 pub fn round_in(&self) -> IRect {
727 let mut r = IRect::default();
728 unsafe { sb::C_SkRect_roundIn(self.native(), r.native_mut()) };
729 r
730 }
731
732 pub fn sort(&mut self) {
733 if self.left > self.right {
734 mem::swap(&mut self.left, &mut self.right);
735 }
736
737 if self.top > self.bottom {
738 mem::swap(&mut self.top, &mut self.bottom);
739 }
740 }
741
742 #[must_use]
743 pub fn sorted(&self) -> Rect {
744 Rect::new(
745 self.left.min(self.right),
746 self.top.min(self.bottom),
747 self.left.max(self.right),
748 self.top.max(self.bottom),
749 )
750 }
751
752 pub fn as_scalars(&self) -> &[f32; 4] {
753 unsafe { transmute_ref(&self.left) }
754 }
755
756 pub fn dump(&self, as_hex: impl Into<Option<bool>>) {
757 unsafe { self.native().dump(as_hex.into().unwrap_or_default()) }
758 }
759
760 pub fn dump_to_string(&self, as_hex: bool) -> String {
761 let mut str = interop::String::default();
762 unsafe { sb::C_SkRect_dumpToString(self.native(), as_hex, str.native_mut()) }
763 str.to_string()
764 }
765
766 pub fn dump_hex(&self) {
767 self.dump(true)
768 }
769}
770
771impl Contains<Point> for Rect {
772 fn contains(&self, p: Point) -> bool {
773 self.contains(&p)
774 }
775}
776
777impl Contains<&Point> for Rect {
778 fn contains(&self, p: &Point) -> bool {
779 p.x >= self.left && p.x < self.right && p.y >= self.top && p.y < self.bottom
780 }
781}
782
783impl Contains<Rect> for Rect {
784 fn contains(&self, r: Rect) -> bool {
785 self.contains(&r)
786 }
787}
788
789impl Contains<&Rect> for Rect {
790 fn contains(&self, r: &Rect) -> bool {
791 !r.is_empty()
793 && !self.is_empty()
794 && self.left <= r.left
795 && self.top <= r.top
796 && self.right >= r.right
797 && self.bottom >= r.bottom
798 }
799}
800
801impl Contains<IRect> for Rect {
802 fn contains(&self, r: IRect) -> bool {
803 self.contains(&r)
804 }
805}
806
807impl Contains<&IRect> for Rect {
808 fn contains(&self, r: &IRect) -> bool {
809 !r.is_empty()
811 && !self.is_empty()
812 && self.left <= r.left as f32
813 && self.top <= r.top as f32
814 && self.right >= r.right as f32
815 && self.bottom >= r.bottom as f32
816 }
817}
818
819#[test]
820fn contains_overloads_compile() {
821 let r = Rect::default();
822 r.contains(Point::default());
823 r.contains(Rect::default());
824 r.contains(IRect::default());
825}
826
827pub trait RoundOut<R> {
828 fn round_out(&self) -> R;
829}
830
831impl RoundOut<IRect> for Rect {
832 fn round_out(&self) -> IRect {
833 let mut r = IRect::default();
834 unsafe { sb::C_SkRect_roundOut(self.native(), r.native_mut()) };
835 r
836 }
837}
838
839impl RoundOut<Rect> for Rect {
840 fn round_out(&self) -> Rect {
841 Rect::new(
842 self.left.floor(),
843 self.top.floor(),
844 self.right.ceil(),
845 self.bottom.ceil(),
846 )
847 }
848}
849
850impl From<(IPoint, ISize)> for IRect {
855 fn from((point, size): (IPoint, ISize)) -> Self {
856 IRect::new(
857 point.x,
858 point.y,
859 point.x + size.width,
860 point.y + size.height,
861 )
862 }
863}
864
865impl From<(Point, Size)> for Rect {
866 fn from((point, size): (Point, Size)) -> Self {
867 Rect::new(
868 point.x,
869 point.y,
870 point.x + size.width,
871 point.y + size.height,
872 )
873 }
874}
875
876impl From<ISize> for Rect {
877 fn from(isize: ISize) -> Self {
878 Self::from_isize(isize)
879 }
880}
881impl From<IRect> for Rect {
882 fn from(irect: IRect) -> Self {
883 Self::from_irect(irect)
884 }
885}