slint_mapping/sources/
synthetic.rs1use crate::source::{TileKey, TileSource};
14use slint::{Image, Rgba8Pixel, SharedPixelBuffer};
15
16pub struct SyntheticTileSource {
17 tile_size: u32,
18}
19
20impl Default for SyntheticTileSource {
21 fn default() -> Self {
22 Self { tile_size: 256 }
23 }
24}
25
26impl SyntheticTileSource {
27 pub fn new() -> Self {
28 Self::default()
29 }
30
31 pub fn with_tile_size(mut self, size: u32) -> Self {
32 self.tile_size = size;
33 self
34 }
35}
36
37impl TileSource for SyntheticTileSource {
38 fn tile(&self, key: TileKey) -> Option<Image> {
39 let size = self.tile_size;
40 let mut buf = SharedPixelBuffer::<Rgba8Pixel>::new(size, size);
41 let stride = size as usize;
42 let pixels = buf.make_mut_slice();
43
44 let r = (40 + (key.x.wrapping_mul(73) & 0x7f)) as u8;
47 let g = (40 + (key.y.wrapping_mul(151) & 0x7f)) as u8;
48 let b = (40 + ((key.x ^ key.y).wrapping_mul(199) & 0x7f)) as u8;
49 let fill = Rgba8Pixel { r, g, b, a: 255 };
50 let border = Rgba8Pixel {
51 r: 255,
52 g: 255,
53 b: 255,
54 a: 100,
55 };
56 let cross = Rgba8Pixel {
57 r: 255,
58 g: 255,
59 b: 255,
60 a: 60,
61 };
62
63 for y in 0..size as usize {
64 for x in 0..size as usize {
65 let on_border = x == 0 || y == 0 || x == stride - 1 || y == stride - 1;
66 let on_cross = (x == stride / 2) || (y == stride / 2);
67 pixels[y * stride + x] = if on_border {
68 border
69 } else if on_cross && key.z >= 4 {
70 cross
71 } else {
72 fill
73 };
74 }
75 }
76
77 Some(Image::from_rgba8(buf))
78 }
79
80 fn tile_size(&self) -> u32 {
81 self.tile_size
82 }
83
84 fn max_zoom(&self) -> u8 {
85 18
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn always_returns_a_tile() {
95 let src = SyntheticTileSource::new();
96 for key in [
97 TileKey { x: 0, y: 0, z: 0 },
98 TileKey {
99 x: 1234,
100 y: 5678,
101 z: 12,
102 },
103 TileKey {
104 x: u32::MAX,
105 y: u32::MAX,
106 z: 18,
107 },
108 ] {
109 assert!(src.tile(key).is_some(), "{key:?}");
110 }
111 }
112
113 #[test]
114 fn distinct_keys_yield_distinct_tiles() {
115 let src = SyntheticTileSource::new();
120 let a = src.tile(TileKey { x: 0, y: 0, z: 5 }).unwrap();
121 let b = src.tile(TileKey { x: 1, y: 0, z: 5 }).unwrap();
122 let (aw, ah) = (a.size().width, a.size().height);
123 let (bw, bh) = (b.size().width, b.size().height);
124 assert_eq!((aw, ah), (256, 256));
125 assert_eq!((bw, bh), (256, 256));
126 }
127
128 #[test]
129 fn tile_size_override_takes_effect() {
130 let src = SyntheticTileSource::new().with_tile_size(128);
131 assert_eq!(src.tile_size(), 128);
132 let img = src.tile(TileKey { x: 0, y: 0, z: 0 }).unwrap();
133 assert_eq!(img.size().width, 128);
134 assert_eq!(img.size().height, 128);
135 }
136}