1use crate::texture::Texture;
2
3#[derive(Copy, Clone, Debug)]
5pub struct Rect {
6 pub x: u32,
8 pub y: u32,
10 pub w: u32,
12 pub h: u32,
14}
15
16impl Rect {
17 pub fn new(x: u32, y: u32, w: u32, h: u32) -> Rect {
19 Rect { x, y, w, h }
20 }
21
22 pub fn new_with_points(x1: u32, y1: u32, x2: u32, y2: u32) -> Rect {
24 Rect {
25 x: x1,
26 y: y1,
27 w: x2 - x1 + 1,
28 h: y2 - y1 + 1,
29 }
30 }
31
32 #[inline(always)]
34 pub fn top(&self) -> u32 {
35 self.y
36 }
37
38 #[inline(always)]
40 pub fn bottom(&self) -> u32 {
41 self.y + self.h - 1
42 }
43
44 #[inline(always)]
46 pub fn left(&self) -> u32 {
47 self.x
48 }
49
50 #[inline(always)]
52 pub fn right(&self) -> u32 {
53 self.x + self.w - 1
54 }
55
56 #[inline(always)]
58 pub fn area(&self) -> u32 {
59 self.w * self.h
60 }
61
62 pub fn intersects(&self, other: &Rect) -> bool {
64 self.left() < other.right()
65 && self.right() > other.left()
66 && self.top() < other.bottom()
67 && self.bottom() > other.top()
68 }
69
70 pub fn contains(&self, other: &Rect) -> bool {
72 self.left() <= other.left()
73 && self.right() >= other.right()
74 && self.top() <= other.top()
75 && self.bottom() >= other.bottom()
76 }
77
78 pub fn contains_point(&self, x: u32, y: u32) -> bool {
80 self.left() <= x && self.right() >= x && self.top() <= y && self.bottom() >= y
81 }
82
83 pub fn is_outline(&self, x: u32, y: u32) -> bool {
85 x == self.left() || x == self.right() || y == self.top() || y == self.bottom()
86 }
87
88 pub fn crop(&self, other: &Rect) -> Vec<Rect> {
90 if !self.intersects(other) {
91 return vec![*self];
92 }
93
94 let inside_x1 = if other.left() < self.left() {
95 self.left()
96 } else {
97 other.left()
98 };
99
100 let inside_y1 = if other.top() < self.top() {
101 self.top()
102 } else {
103 other.top()
104 };
105
106 let inside_x2 = if other.right() > self.right() {
107 self.right()
108 } else {
109 other.right()
110 };
111
112 let inside_y2 = if other.bottom() > self.bottom() {
113 self.bottom()
114 } else {
115 other.bottom()
116 };
117
118 let mut result = Vec::new();
131
132 let r1 = Rect::new_with_points(self.left(), self.top(), inside_x1, self.bottom());
133 if r1.area() > 0 {
134 result.push(r1);
135 }
136
137 let r2 = Rect::new_with_points(inside_x2, self.top(), self.right(), self.bottom());
138 if r2.area() > 0 {
139 result.push(r2);
140 }
141
142 let r3 = Rect::new_with_points(inside_x1, self.top(), inside_x2, inside_y1);
143 if r3.area() > 0 {
144 result.push(r3);
145 }
146
147 let r4 = Rect::new_with_points(inside_x1, inside_y2, inside_x2, self.bottom());
148 if r4.area() > 0 {
149 result.push(r4);
150 }
151
152 result
153 }
154}
155
156impl<T: Texture> From<&T> for Rect {
157 fn from(item: &T) -> Self {
158 Rect {
159 x: 0,
160 y: 0,
161 w: item.width(),
162 h: item.height(),
163 }
164 }
165}