1 | use crate::{ |
2 | interop, |
3 | prelude::*, |
4 | private::{ |
5 | is_finite, |
6 | safe32::{sk32, sk64}, |
7 | }, |
8 | Contains, IPoint, ISize, IVector, Point, Size, Vector, |
9 | }; |
10 | use skia_bindings::{self as sb, SkIRect, SkRect}; |
11 | use std::{ |
12 | cmp::{max, min}, |
13 | mem, |
14 | }; |
15 | |
16 | #[repr (C)] |
17 | #[derive (Copy, Clone, PartialEq, Eq, Default, Debug)] |
18 | pub struct IRect { |
19 | /// The x coordinate of the rectangle's left edge. |
20 | pub left: i32, |
21 | /// The y coordinate of the rectangle's top edge. |
22 | pub top: i32, |
23 | /// The x coordinate of the rectangle's right edge. |
24 | pub right: i32, |
25 | /// The y coordinate of the rectangle's bottom edge. |
26 | pub bottom: i32, |
27 | } |
28 | |
29 | native_transmutable!(SkIRect, IRect, irect_layout); |
30 | |
31 | impl AsRef<IRect> for IRect { |
32 | fn as_ref(&self) -> &IRect { |
33 | self |
34 | } |
35 | } |
36 | |
37 | impl 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 | // contains() is implemented through a trait below. |
238 | |
239 | 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()) }.if_true_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().if_false_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 | #[deprecated (since = "0.27.0" , note = "removed without replacement" )] |
288 | #[must_use ] |
289 | pub fn empty() -> &'static Self { |
290 | &EMPTY_IRECT |
291 | } |
292 | } |
293 | |
294 | pub const EMPTY_IRECT: IRect = IRect { |
295 | left: 0, |
296 | top: 0, |
297 | right: 0, |
298 | bottom: 0, |
299 | }; |
300 | |
301 | impl Contains<IPoint> for IRect { |
302 | fn contains(&self, other: IPoint) -> bool { |
303 | let (x: i32, y: i32) = (other.x, other.y); |
304 | x >= self.left && x < self.right && y >= self.top && y < self.bottom |
305 | } |
306 | } |
307 | |
308 | impl Contains<&IRect> for IRect { |
309 | fn contains(&self, r: &IRect) -> bool { |
310 | !r.is_empty() |
311 | && !self.is_empty() |
312 | && self.left <= r.left |
313 | && self.top <= r.top |
314 | && self.right >= r.right |
315 | && self.bottom >= r.bottom |
316 | } |
317 | } |
318 | |
319 | impl Contains<&Rect> for IRect { |
320 | fn contains(&self, other: &Rect) -> bool { |
321 | unsafe { sb::C_SkIRect_contains(self.native(), rect:other.native()) } |
322 | } |
323 | } |
324 | |
325 | impl Contains<IRect> for IRect { |
326 | fn contains(&self, other: IRect) -> bool { |
327 | self.contains(&other) |
328 | } |
329 | } |
330 | |
331 | impl Contains<Rect> for IRect { |
332 | fn contains(&self, other: Rect) -> bool { |
333 | self.contains(&other) |
334 | } |
335 | } |
336 | |
337 | #[repr (C)] |
338 | #[derive (Copy, Clone, PartialEq, Default, Debug)] |
339 | pub struct Rect { |
340 | /// The x coordinate of the rectangle's left edge. |
341 | pub left: f32, |
342 | /// The y coordinate of the rectangle's top edge. |
343 | pub top: f32, |
344 | /// The x coordinate of the rectangle's right edge. |
345 | pub right: f32, |
346 | /// The y coordinate of the rectangle's bottom edge. |
347 | pub bottom: f32, |
348 | } |
349 | |
350 | native_transmutable!(SkRect, Rect, rect_layout); |
351 | |
352 | impl AsRef<Rect> for Rect { |
353 | fn as_ref(&self) -> &Rect { |
354 | self |
355 | } |
356 | } |
357 | |
358 | impl Rect { |
359 | #[must_use ] |
360 | pub fn new(left: f32, top: f32, right: f32, bottom: f32) -> Self { |
361 | Self { |
362 | left, |
363 | top, |
364 | right, |
365 | bottom, |
366 | } |
367 | } |
368 | |
369 | pub fn new_empty() -> Self { |
370 | Self::new(0.0, 0.0, 0.0, 0.0) |
371 | } |
372 | |
373 | #[must_use ] |
374 | pub fn from_wh(w: f32, h: f32) -> Self { |
375 | Self::new(0.0, 0.0, w, h) |
376 | } |
377 | |
378 | #[must_use ] |
379 | pub fn from_iwh(w: i32, h: i32) -> Self { |
380 | Self::from_wh(w as f32, h as f32) |
381 | } |
382 | |
383 | #[must_use ] |
384 | pub fn from_size(size: impl Into<Size>) -> Self { |
385 | (Point::default(), size.into()).into() |
386 | } |
387 | |
388 | #[must_use ] |
389 | pub fn from_ltrb(l: f32, t: f32, b: f32, r: f32) -> Self { |
390 | Self::new(l, t, b, r) |
391 | } |
392 | |
393 | #[must_use ] |
394 | pub fn from_xywh(x: f32, y: f32, w: f32, h: f32) -> Self { |
395 | Self::new(x, y, x + w, y + h) |
396 | } |
397 | |
398 | #[must_use ] |
399 | pub fn from_point_and_size(p: impl Into<Point>, sz: impl Into<Size>) -> Self { |
400 | (p.into(), sz.into()).into() |
401 | } |
402 | |
403 | #[must_use ] |
404 | pub fn from_isize(isize: impl Into<ISize>) -> Self { |
405 | let isize = isize.into(); |
406 | Self::from_iwh(isize.width, isize.height) |
407 | } |
408 | |
409 | #[must_use ] |
410 | pub fn from_irect(irect: impl AsRef<IRect>) -> Self { |
411 | let irect = irect.as_ref(); |
412 | Self::new( |
413 | irect.left as f32, |
414 | irect.top as f32, |
415 | irect.right as f32, |
416 | irect.bottom as f32, |
417 | ) |
418 | } |
419 | |
420 | pub fn is_empty(&self) -> bool { |
421 | // We write it as the NOT of a non-empty rect, so we will return true if any values |
422 | // are NaN. |
423 | !(self.left < self.right && self.top < self.bottom) |
424 | } |
425 | |
426 | pub fn is_sorted(&self) -> bool { |
427 | self.left <= self.right && self.top <= self.bottom |
428 | } |
429 | |
430 | pub fn is_finite(&self) -> bool { |
431 | is_finite(&[self.left, self.top, self.right, self.bottom]) |
432 | } |
433 | |
434 | pub const fn x(&self) -> f32 { |
435 | self.left |
436 | } |
437 | |
438 | pub const fn y(&self) -> f32 { |
439 | self.top |
440 | } |
441 | |
442 | pub const fn left(&self) -> f32 { |
443 | self.left |
444 | } |
445 | |
446 | pub const fn top(&self) -> f32 { |
447 | self.top |
448 | } |
449 | |
450 | pub const fn right(&self) -> f32 { |
451 | self.right |
452 | } |
453 | |
454 | pub const fn bottom(&self) -> f32 { |
455 | self.bottom |
456 | } |
457 | |
458 | pub fn size(&self) -> Size { |
459 | (self.width(), self.height()).into() |
460 | } |
461 | |
462 | pub fn width(&self) -> f32 { |
463 | self.native().fRight - self.native().fLeft |
464 | } |
465 | |
466 | pub fn height(&self) -> f32 { |
467 | self.native().fBottom - self.native().fTop |
468 | } |
469 | |
470 | pub fn center_x(&self) -> f32 { |
471 | // don't use (fLeft + fBottom) * 0.5 as that might overflow before the 0.5 |
472 | self.left * 0.5 + self.right * 0.5 |
473 | } |
474 | |
475 | pub fn center_y(&self) -> f32 { |
476 | // don't use (fTop + fBottom) * 0.5 as that might overflow before the 0.5 |
477 | self.top * 0.5 + self.bottom * 0.5 |
478 | } |
479 | |
480 | pub fn center(&self) -> Point { |
481 | Point::from((self.center_x(), self.center_y())) |
482 | } |
483 | |
484 | pub fn to_quad(self) -> [Point; 4] { |
485 | let mut quad = [Point::default(); 4]; |
486 | unsafe { self.native().toQuad(quad.native_mut().as_mut_ptr()) } |
487 | quad |
488 | } |
489 | |
490 | pub fn set_empty(&mut self) { |
491 | *self = Self::new_empty() |
492 | } |
493 | |
494 | // TODO: deprecate and rename to set() as soon the other set() variant is removed. |
495 | pub fn set_irect(&mut self, irect: impl AsRef<IRect>) { |
496 | *self = Self::from_irect(irect) |
497 | } |
498 | |
499 | pub fn set_ltrb(&mut self, left: f32, top: f32, right: f32, bottom: f32) { |
500 | *self = Self::new(left, top, right, bottom) |
501 | } |
502 | |
503 | pub fn set_bounds(&mut self, points: &[Point]) { |
504 | unsafe { |
505 | self.native_mut() |
506 | .setBoundsCheck(points.native().as_ptr(), points.len().try_into().unwrap()); |
507 | } |
508 | } |
509 | |
510 | pub fn set_bounds_check(&mut self, points: &[Point]) -> bool { |
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_no_check(&mut self, points: &[Point]) { |
518 | unsafe { |
519 | self.native_mut() |
520 | .setBoundsNoCheck(points.native().as_ptr(), points.len().try_into().unwrap()) |
521 | } |
522 | } |
523 | |
524 | pub fn set_bounds2(&mut self, p0: impl Into<Point>, p1: impl Into<Point>) { |
525 | let (p0, p1) = (p0.into(), p1.into()); |
526 | self.left = p0.x.min(p1.x); |
527 | self.right = p0.x.max(p1.x); |
528 | self.top = p0.y.min(p1.y); |
529 | self.bottom = p0.y.max(p1.y); |
530 | } |
531 | |
532 | pub fn from_bounds(points: &[Point]) -> Option<Self> { |
533 | let mut r = Self::default(); |
534 | unsafe { |
535 | r.native_mut() |
536 | .setBoundsCheck(points.native().as_ptr(), points.len().try_into().unwrap()) |
537 | } |
538 | .if_true_some(r) |
539 | } |
540 | |
541 | pub fn set_xywh(&mut self, x: f32, y: f32, width: f32, height: f32) { |
542 | *self = Self::from_xywh(x, y, width, height) |
543 | } |
544 | |
545 | pub fn set_wh(&mut self, w: f32, h: f32) { |
546 | *self = Self::from_wh(w, h) |
547 | } |
548 | |
549 | pub fn set_iwh(&mut self, width: i32, height: i32) { |
550 | *self = Self::from_iwh(width, height) |
551 | } |
552 | |
553 | #[must_use ] |
554 | pub fn with_offset(&self, d: impl Into<Vector>) -> Self { |
555 | let d = d.into(); |
556 | Self::new( |
557 | self.left + d.x, |
558 | self.top + d.y, |
559 | self.right + d.x, |
560 | self.bottom + d.y, |
561 | ) |
562 | } |
563 | |
564 | #[must_use ] |
565 | pub fn with_inset(&self, d: impl Into<Vector>) -> Self { |
566 | let d = d.into(); |
567 | Self::new( |
568 | self.left + d.x, |
569 | self.top + d.y, |
570 | self.right - d.x, |
571 | self.bottom - d.y, |
572 | ) |
573 | } |
574 | |
575 | #[must_use ] |
576 | pub fn with_outset(&self, d: impl Into<Vector>) -> Self { |
577 | let d = d.into(); |
578 | Self::new( |
579 | self.left - d.x, |
580 | self.top - d.y, |
581 | self.right + d.x, |
582 | self.bottom + d.y, |
583 | ) |
584 | } |
585 | |
586 | pub fn offset(&mut self, d: impl Into<Vector>) { |
587 | *self = self.with_offset(d) |
588 | } |
589 | |
590 | pub fn offset_to(&mut self, new_p: impl Into<Point>) { |
591 | *self = self.with_offset_to(new_p) |
592 | } |
593 | |
594 | #[must_use ] |
595 | pub fn with_offset_to(&self, new_p: impl Into<Point>) -> Self { |
596 | let new_p = new_p.into(); |
597 | Self::new(new_p.x, new_p.y, new_p.x - self.left, new_p.y - self.top) |
598 | } |
599 | |
600 | pub fn inset(&mut self, d: impl Into<Vector>) { |
601 | *self = self.with_inset(d) |
602 | } |
603 | |
604 | pub fn outset(&mut self, d: impl Into<Vector>) { |
605 | *self = self.with_outset(d) |
606 | } |
607 | |
608 | pub fn intersect(&mut self, r: impl AsRef<Rect>) -> bool { |
609 | unsafe { self.native_mut().intersect(r.as_ref().native()) } |
610 | } |
611 | |
612 | #[must_use ] |
613 | pub fn intersect2(&mut self, a: impl AsRef<Rect>, b: impl AsRef<Rect>) -> bool { |
614 | unsafe { |
615 | self.native_mut() |
616 | .intersect1(a.as_ref().native(), b.as_ref().native()) |
617 | } |
618 | } |
619 | |
620 | pub fn intersects(&self, r: impl AsRef<Rect>) -> bool { |
621 | let r = r.as_ref(); |
622 | Self::intersects_( |
623 | self.left, |
624 | self.top, |
625 | self.right, |
626 | self.bottom, |
627 | r.left, |
628 | r.top, |
629 | r.right, |
630 | r.bottom, |
631 | ) |
632 | } |
633 | |
634 | pub fn intersects2(a: impl AsRef<Rect>, b: impl AsRef<Rect>) -> bool { |
635 | a.as_ref().intersects(b) |
636 | } |
637 | |
638 | #[allow (clippy::too_many_arguments)] |
639 | fn intersects_(al: f32, at: f32, ar: f32, ab: f32, bl: f32, bt: f32, br: f32, bb: f32) -> bool { |
640 | let l = al.max(bl); |
641 | let r = ar.min(br); |
642 | let t = at.max(bt); |
643 | let b = ab.min(bb); |
644 | l < r && t < b |
645 | } |
646 | |
647 | pub fn join(&mut self, r: impl AsRef<Rect>) { |
648 | let r = r.as_ref(); |
649 | unsafe { self.native_mut().join(r.native()) } |
650 | } |
651 | |
652 | pub fn join2(a: impl AsRef<Rect>, b: impl AsRef<Rect>) -> Rect { |
653 | let mut result = *a.as_ref(); |
654 | result.join(b); |
655 | result |
656 | } |
657 | |
658 | pub fn join_non_empty_arg(&mut self, r: impl AsRef<Rect>) { |
659 | let r = r.as_ref(); |
660 | debug_assert!(!r.is_empty()); |
661 | if self.left >= self.right || self.top >= self.bottom { |
662 | *self = *r; |
663 | } else { |
664 | self.join_possibly_empty_rect(r); |
665 | } |
666 | } |
667 | |
668 | pub fn join_possibly_empty_rect(&mut self, r: impl AsRef<Rect>) { |
669 | let r = r.as_ref(); |
670 | self.left = self.left.min(r.left); |
671 | self.top = self.top.min(r.top); |
672 | self.right = self.right.max(r.right); |
673 | self.bottom = self.bottom.max(r.bottom); |
674 | } |
675 | |
676 | // The set of contains() functions are defined as a trait below. |
677 | |
678 | #[must_use ] |
679 | pub fn round(&self) -> IRect { |
680 | let mut r = IRect::default(); |
681 | unsafe { sb::C_SkRect_round(self.native(), r.native_mut()) }; |
682 | r |
683 | } |
684 | |
685 | // The functions round_out() are defined as a trait below. |
686 | |
687 | #[must_use ] |
688 | pub fn round_in(&self) -> IRect { |
689 | let mut r = IRect::default(); |
690 | unsafe { sb::C_SkRect_roundIn(self.native(), r.native_mut()) }; |
691 | r |
692 | } |
693 | |
694 | pub fn sort(&mut self) { |
695 | if self.left > self.right { |
696 | mem::swap(&mut self.left, &mut self.right); |
697 | } |
698 | |
699 | if self.top > self.bottom { |
700 | mem::swap(&mut self.top, &mut self.bottom); |
701 | } |
702 | } |
703 | |
704 | #[must_use ] |
705 | pub fn sorted(&self) -> Rect { |
706 | Rect::new( |
707 | self.left.min(self.right), |
708 | self.top.min(self.bottom), |
709 | self.left.max(self.right), |
710 | self.top.max(self.bottom), |
711 | ) |
712 | } |
713 | |
714 | pub fn as_scalars(&self) -> &[f32; 4] { |
715 | unsafe { transmute_ref(&self.left) } |
716 | } |
717 | |
718 | pub fn dump(&self, as_hex: impl Into<Option<bool>>) { |
719 | unsafe { self.native().dump(as_hex.into().unwrap_or_default()) } |
720 | } |
721 | |
722 | pub fn dump_to_string(&self, as_hex: bool) -> String { |
723 | let mut str = interop::String::default(); |
724 | unsafe { sb::C_SkRect_dumpToString(self.native(), as_hex, str.native_mut()) } |
725 | str.to_string() |
726 | } |
727 | |
728 | pub fn dump_hex(&self) { |
729 | self.dump(true) |
730 | } |
731 | } |
732 | |
733 | impl Contains<Point> for Rect { |
734 | fn contains(&self, p: Point) -> bool { |
735 | self.contains(&p) |
736 | } |
737 | } |
738 | |
739 | impl Contains<&Point> for Rect { |
740 | fn contains(&self, p: &Point) -> bool { |
741 | p.x >= self.left && p.x < self.right && p.y >= self.top && p.y < self.bottom |
742 | } |
743 | } |
744 | |
745 | impl Contains<Rect> for Rect { |
746 | fn contains(&self, r: Rect) -> bool { |
747 | self.contains(&r) |
748 | } |
749 | } |
750 | |
751 | impl Contains<&Rect> for Rect { |
752 | fn contains(&self, r: &Rect) -> bool { |
753 | // TODO: can we eliminate the this->is_empty check? |
754 | !r.is_empty() |
755 | && !self.is_empty() |
756 | && self.left <= r.left |
757 | && self.top <= r.top |
758 | && self.right >= r.right |
759 | && self.bottom >= r.bottom |
760 | } |
761 | } |
762 | |
763 | impl Contains<IRect> for Rect { |
764 | fn contains(&self, r: IRect) -> bool { |
765 | self.contains(&r) |
766 | } |
767 | } |
768 | |
769 | impl Contains<&IRect> for Rect { |
770 | fn contains(&self, r: &IRect) -> bool { |
771 | // TODO: can we eliminate the this->isEmpty check? |
772 | !r.is_empty() |
773 | && !self.is_empty() |
774 | && self.left <= r.left as f32 |
775 | && self.top <= r.top as f32 |
776 | && self.right >= r.right as f32 |
777 | && self.bottom >= r.bottom as f32 |
778 | } |
779 | } |
780 | |
781 | #[test ] |
782 | fn contains_overloads_compile() { |
783 | let r = Rect::default(); |
784 | r.contains(Point::default()); |
785 | r.contains(Rect::default()); |
786 | r.contains(IRect::default()); |
787 | } |
788 | |
789 | pub trait RoundOut<R> { |
790 | fn round_out(&self) -> R; |
791 | } |
792 | |
793 | impl RoundOut<IRect> for Rect { |
794 | fn round_out(&self) -> IRect { |
795 | let mut r: IRect = IRect::default(); |
796 | unsafe { sb::C_SkRect_roundOut(self.native(), dst:r.native_mut()) }; |
797 | r |
798 | } |
799 | } |
800 | |
801 | impl RoundOut<Rect> for Rect { |
802 | fn round_out(&self) -> Rect { |
803 | Rect::new( |
804 | self.left.floor(), |
805 | self.top.floor(), |
806 | self.right.ceil(), |
807 | self.bottom.ceil(), |
808 | ) |
809 | } |
810 | } |
811 | |
812 | // |
813 | // From |
814 | // |
815 | |
816 | impl From<(IPoint, ISize)> for IRect { |
817 | fn from((point: IPoint, size: ISize): (IPoint, ISize)) -> Self { |
818 | IRect::new( |
819 | left:point.x, |
820 | top:point.y, |
821 | right:point.x + size.width, |
822 | bottom:point.y + size.height, |
823 | ) |
824 | } |
825 | } |
826 | |
827 | impl From<(Point, Size)> for Rect { |
828 | fn from((point: Point, size: Size): (Point, Size)) -> Self { |
829 | Rect::new( |
830 | left:point.x, |
831 | top:point.y, |
832 | right:point.x + size.width, |
833 | bottom:point.y + size.height, |
834 | ) |
835 | } |
836 | } |
837 | |
838 | impl From<ISize> for Rect { |
839 | fn from(isize: ISize) -> Self { |
840 | Self::from_isize(isize) |
841 | } |
842 | } |
843 | impl From<IRect> for Rect { |
844 | fn from(irect: IRect) -> Self { |
845 | Self::from_irect(irect) |
846 | } |
847 | } |
848 | |