1#![allow(clippy::cast_precision_loss)]
6
7#[cfg(feature = "alloc")]
8extern crate alloc;
9
10#[cfg(feature = "alloc")]
11use alloc::vec::Vec;
12
13use crate::{CoreError, Rect};
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17pub struct TileWindow {
18 pub col: u32,
20 pub row: u32,
22 pub x0: u32,
24 pub y0: u32,
26 pub width: u32,
28 pub height: u32,
30}
31
32pub fn generate_tiles(
41 frame_w: u32,
42 frame_h: u32,
43 tile: u32,
44 overlap: u32,
45) -> Result<Vec<TileWindow>, CoreError> {
46 if frame_w == 0 || frame_h == 0 || tile == 0 || overlap >= tile {
47 return Err(CoreError::InvalidThreshold);
48 }
49 let stride = tile - overlap;
50 let mut out = Vec::new();
51 let mut row = 0_u32;
52 let mut y = 0_u32;
53 loop {
54 let y0 = y.min(frame_h.saturating_sub(tile));
55 let height = tile.min(frame_h.saturating_sub(y0));
56 let mut col = 0_u32;
57 let mut x = 0_u32;
58 loop {
59 let x0 = x.min(frame_w.saturating_sub(tile));
60 let width = tile.min(frame_w.saturating_sub(x0));
61 out.push(TileWindow {
62 col,
63 row,
64 x0,
65 y0,
66 width,
67 height,
68 });
69 if x0 + width >= frame_w {
70 break;
71 }
72 x = x.saturating_add(stride);
73 col = col.saturating_add(1);
74 }
75 if y0 + height >= frame_h {
76 break;
77 }
78 y = y.saturating_add(stride);
79 row = row.saturating_add(1);
80 }
81 Ok(out)
82}
83
84pub fn tile_to_global(tile: TileWindow, local: Rect) -> Result<Rect, CoreError> {
90 let dx = tile.x0 as f32;
91 let dy = tile.y0 as f32;
92 Rect::new(
93 local.left() + dx,
94 local.top() + dy,
95 local.right() + dx,
96 local.bottom() + dy,
97 )
98 .map_err(|_| CoreError::NonFinite)
99}