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