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