physis/bcn/
macros.rs

1// SPDX-FileCopyrightText: 2023 Rudolf Kolbe
2// SPDX-License-Identifier: MIT
3
4// macro to generate generic block decoder functions
5macro_rules! block_decoder {
6    ($name: ident, $block_width: expr, $block_height: expr, $raw_block_size: expr, $block_decode_func: expr) => {
7        //#[doc = "Decodes a " $name " encoded texture into an image"]
8        pub fn $name(
9            data: &[u8],
10            width: usize,
11            height: usize,
12            image: &mut [u32],
13        ) -> Result<(), &'static str> {
14            const BLOCK_WIDTH: usize = $block_width;
15            const BLOCK_HEIGHT: usize = $block_height;
16            const BLOCK_SIZE: usize = BLOCK_WIDTH * BLOCK_HEIGHT;
17            let num_blocks_x: usize = (width + BLOCK_WIDTH - 1) / BLOCK_WIDTH;
18            let num_blocks_y: usize = (height + BLOCK_WIDTH - 1) / BLOCK_HEIGHT;
19            let mut buffer: [u32; BLOCK_SIZE] =
20                [crate::bcn::color::color(0, 0, 0, 255); BLOCK_SIZE];
21
22            if data.len() < num_blocks_x * num_blocks_y * $raw_block_size {
23                return Err("Not enough data to decode image!");
24            }
25
26            if image.len() < width * height {
27                return Err("Image buffer is too small!");
28            }
29
30            let mut data_offset = 0;
31            (0..num_blocks_y).for_each(|by| {
32                (0..num_blocks_x).for_each(|bx| {
33                    $block_decode_func(&data[data_offset..], &mut buffer);
34                    crate::bcn::color::copy_block_buffer(
35                        bx,
36                        by,
37                        width,
38                        height,
39                        BLOCK_WIDTH,
40                        BLOCK_HEIGHT,
41                        &buffer,
42                        image,
43                    );
44                    data_offset += $raw_block_size;
45                });
46            });
47            Ok(())
48        }
49    };
50}
51
52pub(crate) use block_decoder;