139 pub const fn is_power_of_two(&self) -> bool { |
139 pub const fn is_power_of_two(&self) -> bool { |
140 self.width.is_power_of_two() && self.height.is_power_of_two() |
140 self.width.is_power_of_two() && self.height.is_power_of_two() |
141 } |
141 } |
142 |
142 |
143 #[inline] |
143 #[inline] |
144 pub fn next_power_of_two(&self) -> Self { |
144 pub const fn as_power_of_two(&self) -> Option<PotSize> { |
145 Self { |
145 PotSize::new(self.width, self.height) |
146 width: self.width.next_power_of_two(), |
146 } |
147 height: self.height.next_power_of_two(), |
147 |
148 } |
148 #[inline] |
|
149 pub const fn next_power_of_two(&self) -> PotSize { |
|
150 PotSize::new_impl( |
|
151 self.width.next_power_of_two(), |
|
152 self.height.next_power_of_two(), |
|
153 ) |
149 } |
154 } |
150 |
155 |
151 #[inline] |
156 #[inline] |
152 pub const fn transpose(&self) -> Self { |
157 pub const fn transpose(&self) -> Self { |
153 Self::new(self.height, self.width) |
158 Self::new(self.height, self.width) |
154 } |
159 } |
155 |
160 |
156 #[inline] |
161 #[inline] |
157 pub fn to_mask(&self) -> SizeMask { |
|
158 SizeMask::new(*self) |
|
159 } |
|
160 |
|
161 #[inline] |
|
162 pub fn to_square(&self) -> Self { |
162 pub fn to_square(&self) -> Self { |
163 Self::square(max(self.width, self.height)) |
163 Self::square(max(self.width, self.height)) |
164 } |
164 } |
165 |
165 |
166 pub fn to_grid_index(&self) -> GridIndex { |
|
167 GridIndex::new(*self) |
|
168 } |
|
169 |
|
170 #[inline] |
166 #[inline] |
171 pub const fn contains(&self, other: Self) -> bool { |
167 pub const fn contains(&self, other: Self) -> bool { |
172 self.width >= other.width && self.height >= other.height |
168 self.width >= other.width && self.height >= other.height |
173 } |
169 } |
174 |
170 |
175 #[inline] |
171 #[inline] |
176 pub fn join(&self, other: Self) -> Self { |
172 pub fn join(&self, other: Self) -> Self { |
|
173 Self::new(max(self.width, other.width), max(self.height, other.height)) |
|
174 } |
|
175 } |
|
176 |
|
177 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
|
178 pub struct PotSize { |
|
179 size: Size, |
|
180 } |
|
181 |
|
182 impl PotSize { |
|
183 #[inline] |
|
184 const fn new_impl(width: usize, height: usize) -> Self { |
|
185 debug_assert!(width.is_power_of_two() && height.is_power_of_two()); |
177 Self { |
186 Self { |
178 width: max(self.width, other.width), |
187 size: Size::new(width, height), |
179 height: max(self.height, other.height) |
188 } |
180 } |
189 } |
|
190 |
|
191 #[inline] |
|
192 pub const fn new(width: usize, height: usize) -> Option<Self> { |
|
193 if width.is_power_of_two() && height.is_power_of_two() { |
|
194 Some(Self::new_impl(width, height)) |
|
195 } else { |
|
196 None |
|
197 } |
|
198 } |
|
199 |
|
200 pub const fn size(&self) -> Size { |
|
201 self.size |
|
202 } |
|
203 |
|
204 pub const fn width(&self) -> usize { |
|
205 self.size.width |
|
206 } |
|
207 |
|
208 pub const fn height(&self) -> usize { |
|
209 self.size.height |
|
210 } |
|
211 |
|
212 #[inline] |
|
213 pub const fn square(size: usize) -> Option<Self> { |
|
214 if size.is_power_of_two() { |
|
215 Some(Self::new_impl(size, size)) |
|
216 } else { |
|
217 None |
|
218 } |
|
219 } |
|
220 |
|
221 #[inline] |
|
222 pub const fn area(&self) -> usize { |
|
223 self.size.area() |
|
224 } |
|
225 |
|
226 #[inline] |
|
227 pub const fn linear_index(&self, x: usize, y: usize) -> usize { |
|
228 self.size.linear_index(x, y) |
|
229 } |
|
230 |
|
231 #[inline] |
|
232 pub const fn transpose(&self) -> Self { |
|
233 Self::new_impl(self.height(), self.width()) |
|
234 } |
|
235 |
|
236 #[inline] |
|
237 pub fn to_square(&self) -> Self { |
|
238 let size = max(self.width(), self.height()); |
|
239 Self::new_impl(size, size) |
|
240 } |
|
241 |
|
242 #[inline] |
|
243 pub const fn to_mask(&self) -> SizeMask { |
|
244 SizeMask::new(*self) |
|
245 } |
|
246 |
|
247 pub const fn to_grid_index(&self) -> GridIndex { |
|
248 GridIndex::new(*self) |
|
249 } |
|
250 |
|
251 #[inline] |
|
252 pub const fn contains(&self, other: Self) -> bool { |
|
253 self.size.contains(other.size) |
|
254 } |
|
255 |
|
256 #[inline] |
|
257 pub fn join(&self, other: Self) -> Self { |
|
258 Self::new_impl( |
|
259 max(self.width(), other.width()), |
|
260 max(self.height(), other.height()), |
|
261 ) |
181 } |
262 } |
182 } |
263 } |
183 |
264 |
184 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
265 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
185 pub struct SizeMask { |
266 pub struct SizeMask { |
186 size: Size, |
267 size: Size, |
187 } |
268 } |
188 |
269 |
189 impl SizeMask { |
270 impl SizeMask { |
190 #[inline] |
271 #[inline] |
191 pub fn new(size: Size) -> Self { |
272 pub const fn new(size: PotSize) -> Self { |
192 debug_assert!(size.is_power_of_two()); |
273 Self { |
193 let size = Size { |
274 size: Size::new(!(size.width() - 1), !(size.height() - 1)), |
194 width: !(size.width - 1), |
275 } |
195 height: !(size.height - 1), |
|
196 }; |
|
197 Self { size } |
|
198 } |
276 } |
199 |
277 |
200 #[inline] |
278 #[inline] |
201 pub fn contains_x<T: Into<usize>>(&self, x: T) -> bool { |
279 pub fn contains_x<T: Into<usize>>(&self, x: T) -> bool { |
202 (self.size.width & x.into()) == 0 |
280 (self.size.width & x.into()) == 0 |
209 |
287 |
210 #[inline] |
288 #[inline] |
211 pub fn contains(&self, point: Point) -> bool { |
289 pub fn contains(&self, point: Point) -> bool { |
212 self.contains_x(point.x as usize) && self.contains_y(point.y as usize) |
290 self.contains_x(point.x as usize) && self.contains_y(point.y as usize) |
213 } |
291 } |
|
292 |
|
293 #[inline] |
|
294 pub const fn to_size(&self) -> PotSize { |
|
295 PotSize::new_impl(!self.size.width + 1, !self.size.height + 1) |
|
296 } |
214 } |
297 } |
215 |
298 |
216 pub struct GridIndex { |
299 pub struct GridIndex { |
217 shift: Point, |
300 shift: Point, |
218 } |
301 } |
219 |
302 |
220 impl GridIndex { |
303 impl GridIndex { |
221 pub fn new(size: Size) -> Self { |
304 pub const fn new(size: PotSize) -> Self { |
222 debug_assert!(size.is_power_of_two()); |
|
223 let shift = Point::new( |
305 let shift = Point::new( |
224 size.width.trailing_zeros() as i32, |
306 size.width().trailing_zeros() as i32, |
225 size.height.trailing_zeros() as i32, |
307 size.height().trailing_zeros() as i32, |
226 ); |
308 ); |
227 Self { shift } |
309 Self { shift } |
228 } |
310 } |
229 |
311 |
230 pub const fn map(&self, position: Point) -> Point { |
312 pub const fn map(&self, position: Point) -> Point { |
322 top_left: Point::ZERO, |
404 top_left: Point::ZERO, |
323 bottom_right: Point::diag(-1), |
405 bottom_right: Point::diag(-1), |
324 }; |
406 }; |
325 |
407 |
326 #[inline] |
408 #[inline] |
327 pub fn new(top_left: Point, bottom_right: Point) -> Self { |
409 pub const fn new(top_left: Point, bottom_right: Point) -> Self { |
328 debug_assert!(top_left.x <= bottom_right.x + 1); |
410 debug_assert!(top_left.x <= bottom_right.x + 1); |
329 debug_assert!(top_left.y <= bottom_right.y + 1); |
411 debug_assert!(top_left.y <= bottom_right.y + 1); |
330 Self { |
412 Self { |
331 top_left, |
413 top_left, |
332 bottom_right, |
414 bottom_right, |
333 } |
415 } |
334 } |
416 } |
335 |
417 |
336 pub fn from_box(left: i32, right: i32, top: i32, bottom: i32) -> Self { |
418 pub const fn from_box(left: i32, right: i32, top: i32, bottom: i32) -> Self { |
337 Self::new(Point::new(left, top), Point::new(right, bottom)) |
419 Self::new(Point::new(left, top), Point::new(right, bottom)) |
338 } |
420 } |
339 |
421 |
340 pub fn from_size(top_left: Point, size: Size) -> Self { |
422 pub fn from_size(top_left: Point, size: Size) -> Self { |
341 Self::new( |
423 Self::new( |
448 && self.top() <= other.bottom() |
530 && self.top() <= other.bottom() |
449 && self.bottom() >= other.top() |
531 && self.bottom() >= other.top() |
450 } |
532 } |
451 |
533 |
452 #[inline] |
534 #[inline] |
453 pub fn split_at(&self, point: Point) -> [Rect; 4] { |
535 pub const fn split_at(&self, point: Point) -> [Rect; 4] { |
454 debug_assert!(self.contains_inside(point)); |
536 debug_assert!(self.contains_inside(point)); |
455 [ |
537 [ |
456 Self::from_box(self.left(), point.x, self.top(), point.y), |
538 Self::from_box(self.left(), point.x, self.top(), point.y), |
457 Self::from_box(point.x, self.right(), self.top(), point.y), |
539 Self::from_box(point.x, self.right(), self.top(), point.y), |
458 Self::from_box(point.x, self.right(), point.y, self.bottom()), |
540 Self::from_box(point.x, self.right(), point.y, self.bottom()), |
459 Self::from_box(self.left(), point.x, point.y, self.bottom()), |
541 Self::from_box(self.left(), point.x, point.y, self.bottom()), |
460 ] |
542 ] |
461 } |
543 } |
462 |
544 |
463 #[inline] |
545 #[inline] |
464 pub fn with_margins(&self, left: i32, right: i32, top: i32, bottom: i32) -> Self { |
546 pub const fn with_margins(&self, left: i32, right: i32, top: i32, bottom: i32) -> Self { |
465 Self::from_box( |
547 Self::from_box( |
466 self.left() - left, |
548 self.left() - left, |
467 self.right() + right, |
549 self.right() + right, |
468 self.top() - top, |
550 self.top() - top, |
469 self.bottom() + bottom, |
551 self.bottom() + bottom, |