1use std::marker::PhantomData;
5use std::ops::{Index, IndexMut};
6
7#[cfg(sdfer_use_f64_instead_of_f32)]
9type f32 = f64;
10
11#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
14#[repr(transparent)]
15pub struct Unorm8(u8);
16
17impl Unorm8 {
18 pub const MIN: Self = Self::from_bits(0);
19 pub const MAX: Self = Self::from_bits(u8::MAX);
20
21 #[inline(always)]
22 pub fn encode(x: f32) -> Self {
23 Self((x * 255.0).round() as u8)
26 }
27
28 #[inline(always)]
29 pub fn decode(self) -> f32 {
30 self.0 as f32 / 255.0
31 }
32
33 #[inline(always)]
34 pub const fn from_bits(bits: u8) -> Self {
35 Self(bits)
36 }
37
38 #[inline(always)]
39 pub const fn to_bits(self) -> u8 {
40 self.0
41 }
42}
43
44#[derive(Default, Copy, Clone)]
45pub struct Image2d<T, Storage: AsRef<[T]> = Vec<T>> {
46 width: usize,
47 height: usize,
48 data: Storage,
49 _marker: PhantomData<T>,
50}
51
52impl<T, Storage: AsRef<[T]>> Image2d<T, Storage> {
53 pub fn new(width: usize, height: usize) -> Self
54 where
55 T: Default,
56 Storage: FromIterator<T>,
57 {
58 Self::from_fn(width, height, |_, _| T::default())
59 }
60
61 pub fn from_fn(width: usize, height: usize, mut f: impl FnMut(usize, usize) -> T) -> Self
62 where
63 Storage: FromIterator<T>,
64 {
65 Self::from_storage(
66 width,
67 height,
68 (0..height)
69 .flat_map(|y| (0..width).map(move |x| (x, y)))
70 .map(|(x, y)| f(x, y))
71 .collect(),
72 )
73 }
74
75 pub fn from_storage(width: usize, height: usize, storage: Storage) -> Self {
76 assert_eq!(storage.as_ref().len(), width * height);
77 Self {
78 width,
79 height,
80 data: storage,
81 _marker: PhantomData,
82 }
83 }
84
85 pub fn width(&self) -> usize {
86 self.width
87 }
88
89 pub fn height(&self) -> usize {
90 self.height
91 }
92
93 pub fn reborrow(&self) -> Image2d<T, &[T]> {
94 Image2d {
95 width: self.width,
96 height: self.height,
97 data: self.data.as_ref(),
98 _marker: PhantomData,
99 }
100 }
101
102 pub fn reborrow_mut(&mut self) -> Image2d<T, &mut [T]>
103 where
104 Storage: AsMut<[T]>,
105 {
106 Image2d {
107 width: self.width,
108 height: self.height,
109 data: self.data.as_mut(),
110 _marker: PhantomData,
111 }
112 }
113
114 pub fn cursor_at(&mut self, x: usize, y: usize) -> Image2dCursor<'_, T>
115 where
116 Storage: AsMut<[T]>,
117 {
118 let mut cursor = Image2dCursor {
119 image: self.reborrow_mut(),
120 xy_offset: 0,
121 };
122 cursor.reset((x, y));
123 cursor
124 }
125}
126
127impl<T, Storage: AsRef<[T]>> Index<(usize, usize)> for Image2d<T, Storage> {
128 type Output = T;
129
130 fn index(&self, (x, y): (usize, usize)) -> &T {
131 &self.data.as_ref()[y * self.width..][..self.width][x]
132 }
133}
134
135impl<T, Storage: AsMut<[T]> + AsRef<[T]>> IndexMut<(usize, usize)> for Image2d<T, Storage> {
136 fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut T {
137 &mut self.data.as_mut()[y * self.width..][..self.width][x]
138 }
139}
140
141#[cfg(feature = "image")]
142impl From<image::GrayImage> for Image2d<Unorm8> {
143 fn from(img: image::GrayImage) -> Self {
144 Self {
145 width: img.width().try_into().unwrap(),
146 height: img.height().try_into().unwrap(),
147 data: img.into_vec().into_iter().map(Unorm8::from_bits).collect(),
150 _marker: PhantomData,
151 }
152 }
153}
154
155#[cfg(feature = "image")]
156impl From<Image2d<Unorm8>> for image::GrayImage {
157 fn from(img: Image2d<Unorm8>) -> Self {
158 image::GrayImage::from_vec(
159 img.width().try_into().unwrap(),
160 img.height().try_into().unwrap(),
161 img.data.into_iter().map(Unorm8::to_bits).collect(),
164 )
165 .unwrap()
166 }
167}
168
169impl<T: Copy> Image2d<T> {
170 fn resize_and_fill_with(&mut self, width: usize, height: usize, initial: T) {
171 self.width = width;
172 self.height = height;
173 self.data.clear();
174 self.data.resize(width * height, initial);
175 }
176}
177
178#[derive(Default)]
179pub struct Bitmap {
180 width: usize,
181 height: usize,
182 bit_8x8_blocks: Image2d<u64>,
183}
184
185pub struct BitmapEntry<'a> {
186 bit_8x8_block: &'a mut u64,
187 mask: u64,
188}
189
190impl Bitmap {
191 #[inline(always)]
192 pub fn new(width: usize, height: usize) -> Self {
193 let mut r = Self::default();
194 r.resize_and_fill_with(width, height, false);
195 r
196 }
197
198 #[inline(always)]
199 pub(crate) fn resize_and_fill_with(&mut self, width: usize, height: usize, initial: bool) {
200 self.width = width;
201 self.height = height;
202 self.bit_8x8_blocks.resize_and_fill_with(
203 width.div_ceil(8),
204 height.div_ceil(8),
205 if initial { !0 } else { 0 },
206 );
207 }
208
209 #[inline(always)]
210 pub fn width(&self) -> usize {
211 self.width
212 }
213
214 #[inline(always)]
215 pub fn height(&self) -> usize {
216 self.height
217 }
218
219 const BW: usize = 8;
220 const BH: usize = 8;
221
222 #[inline(always)]
223 const fn bit_8x8_block_xy_and_mask(x: usize, y: usize) -> ((usize, usize), u64) {
224 (
225 (x / Self::BW, y / Self::BH),
226 1 << ((y % Self::BH) * Self::BW + x % Self::BW),
227 )
228 }
229
230 #[inline(always)]
231 pub fn get(&self, x: usize, y: usize) -> bool {
232 let (block_xy, mask) = Self::bit_8x8_block_xy_and_mask(x, y);
233 (self.bit_8x8_blocks[block_xy] & mask) != 0
234 }
235
236 #[inline(always)]
237 pub fn at(&mut self, x: usize, y: usize) -> BitmapEntry<'_> {
238 let (block_xy, mask) = Self::bit_8x8_block_xy_and_mask(x, y);
239 BitmapEntry {
240 bit_8x8_block: &mut self.bit_8x8_blocks[block_xy],
241 mask,
242 }
243 }
244
245 #[inline(always)]
246 pub fn cursor_at(&mut self, x: usize, y: usize) -> BitmapCursor<'_> {
247 let mut cursor = BitmapCursor {
248 bit_8x8_blocks: self.bit_8x8_blocks.cursor_at(0, 0),
249 intra_block_xy: (0, 0),
250 };
251 cursor.reset((x, y));
252 cursor
253 }
254}
255
256impl BitmapEntry<'_> {
257 #[inline(always)]
258 pub fn get(&self) -> bool {
259 (*self.bit_8x8_block & self.mask) != 0
260 }
261
262 #[inline(always)]
263 pub fn set(&mut self, value: bool) {
264 if value {
265 *self.bit_8x8_block |= self.mask;
266 } else {
267 *self.bit_8x8_block &= !self.mask;
268 }
269 }
270}
271
272pub trait NDCursor<'a, P> {
274 type RefMut;
275 fn reset(&'a mut self, position: P);
276 fn get_mut(&'a mut self) -> Self::RefMut;
277 fn advance(&'a mut self, delta: P);
278}
279
280pub trait NDCursorExt<P>: for<'a> NDCursor<'a, P> {
281 fn zip<C2: NDCursorExt<P>>(self, other: C2) -> NDCursorZip<Self, C2>
282 where
283 Self: Sized,
284 {
285 NDCursorZip(self, other)
286 }
287
288 fn map_abs_and_rel<P2, FA: Fn(P2) -> P, FR: Fn(P2) -> P>(
290 self,
291 fa: FA,
292 fr: FR,
293 ) -> NDCursorMapPos<Self, FA, FR>
294 where
295 Self: Sized,
296 {
297 NDCursorMapPos(self, fa, fr)
298 }
299}
300impl<P, C: for<'a> NDCursor<'a, P>> NDCursorExt<P> for C {}
301
302pub struct NDCursorZip<C1, C2>(C1, C2);
303impl<'a, P: Copy, C1: NDCursor<'a, P>, C2: NDCursor<'a, P>> NDCursor<'a, P>
304 for NDCursorZip<C1, C2>
305{
306 type RefMut = (C1::RefMut, C2::RefMut);
307 #[inline(always)]
308 fn reset(&'a mut self, position: P) {
309 self.0.reset(position);
310 self.1.reset(position);
311 }
312 #[inline(always)]
313 fn get_mut(&'a mut self) -> Self::RefMut {
314 (self.0.get_mut(), self.1.get_mut())
315 }
316 #[inline(always)]
317 fn advance(&'a mut self, delta: P) {
318 self.0.advance(delta);
319 self.1.advance(delta);
320 }
321}
322
323pub struct NDCursorMapPos<C, FA, FR>(C, FA, FR);
324impl<'a, C: NDCursor<'a, P>, P, P2, FA: Fn(P2) -> P, FR: Fn(P2) -> P> NDCursor<'a, P2>
325 for NDCursorMapPos<C, FA, FR>
326{
327 type RefMut = C::RefMut;
328 #[inline(always)]
329 fn reset(&'a mut self, position: P2) {
330 self.0.reset((self.1)(position));
331 }
332 #[inline(always)]
333 fn get_mut(&'a mut self) -> Self::RefMut {
334 self.0.get_mut()
335 }
336 #[inline(always)]
337 fn advance(&'a mut self, delta: P2) {
338 self.0.advance((self.2)(delta));
339 }
340}
341
342pub struct Image2dCursor<'a, T> {
343 image: Image2d<T, &'a mut [T]>,
345 xy_offset: usize,
346}
347
348impl<'a, T: 'a> NDCursor<'a, (usize, usize)> for Image2dCursor<'_, T> {
349 type RefMut = &'a mut T;
350 #[inline(always)]
351 fn reset(&'a mut self, (x, y): (usize, usize)) {
352 self.xy_offset = y * self.image.width + x;
353 }
354 #[inline(always)]
355 fn get_mut(&'a mut self) -> Self::RefMut {
356 &mut self.image.data[self.xy_offset]
357 }
358 #[inline(always)]
359 fn advance(&'a mut self, (dx, dy): (usize, usize)) {
360 self.xy_offset += dy * self.image.width + dx;
362 }
363}
364
365pub struct BitmapCursor<'a> {
366 bit_8x8_blocks: Image2dCursor<'a, u64>,
367 intra_block_xy: (u8, u8),
369}
370
371impl<'a> NDCursor<'a, (usize, usize)> for BitmapCursor<'_> {
372 type RefMut = BitmapEntry<'a>;
373 #[inline(always)]
374 fn reset(&'a mut self, (x, y): (usize, usize)) {
375 self.bit_8x8_blocks.reset((x / Bitmap::BW, y / Bitmap::BH));
376 self.intra_block_xy = ((x % Bitmap::BW) as u8, (y % Bitmap::BH) as u8);
377 }
378 #[inline(always)]
379 fn get_mut(&'a mut self) -> Self::RefMut {
380 let bxy = self.intra_block_xy;
381 let (_, mask) = Bitmap::bit_8x8_block_xy_and_mask(bxy.0 as usize, bxy.1 as usize);
382 BitmapEntry {
383 bit_8x8_block: self.bit_8x8_blocks.get_mut(),
384 mask,
385 }
386 }
387 #[inline(always)]
388 fn advance(&'a mut self, (dx, dy): (usize, usize)) {
389 let bxy = self.intra_block_xy;
391 let new_bxy = (bxy.0 as usize + dx, bxy.1 as usize + dy);
392
393 let whole_block_dxy = (new_bxy.0 / Bitmap::BW, new_bxy.1 / Bitmap::BH);
394 if whole_block_dxy != (0, 0) {
395 self.bit_8x8_blocks.advance(whole_block_dxy);
396 }
397
398 self.intra_block_xy = (
399 (new_bxy.0 % Bitmap::BW) as u8,
400 (new_bxy.1 % Bitmap::BH) as u8,
401 );
402 }
403}