zintl_render/
texture.rs

1use zintl_render_math::{PhysicalPixels, PhysicalPixelsPoint, PhysicalPixelsRect};
2
3/// All of the rendered glyphs in a single atlas.
4#[derive(Clone, Debug)]
5pub struct Atlas {
6    /// A cached width of the atlas.
7    pub width: PhysicalPixels,
8    /// A cached height of the atlas.
9    pub height: PhysicalPixels,
10    /// Where to draw new glyphs in the atlas.
11    cursor: PhysicalPixelsPoint,
12    /// The pixel data of the atlas, stored as a flat array of RGBA values.
13    pixels: Vec<u8>,
14    row_height: PhysicalPixels,
15}
16
17impl Atlas {
18    /// Creates a new `Atlas` with the specified width and height.
19    pub fn new(initial_width: PhysicalPixels, initial_height: PhysicalPixels) -> Self {
20        let pixels = vec![0; (initial_width * initial_height * 4).value() as usize];
21        Atlas {
22            height: initial_height,
23            cursor: PhysicalPixelsPoint::new(0.into(), 0.into()),
24            pixels,
25            width: initial_width,
26            row_height: PhysicalPixels::zero(),
27        }
28    }
29
30    pub fn resize_pixels(&mut self, new_height: PhysicalPixels) {
31        if new_height > self.height {
32            let new_size = self.width * new_height * 4;
33            self.pixels.resize(new_size.value() as usize, 0);
34            self.height = new_height;
35        }
36    }
37
38    /// Texture bounds (is not normalized), atlas width, and mutable pixel data.
39    pub fn create_image(
40        &mut self,
41        width: PhysicalPixels,
42        height: PhysicalPixels,
43    ) -> (PhysicalPixelsRect, PhysicalPixels, &mut Vec<u8>) {
44        // Allocate a new texture with the specified width and height.
45        {
46            // We need to allocate a new row
47            if self.cursor.x + width > self.width {
48                self.cursor.x = 0.into();
49                self.cursor.y += self.row_height;
50                self.row_height = 0.into();
51            }
52
53            self.row_height = self.row_height.max(height);
54
55            let new_height = self.cursor.y + self.row_height;
56            self.resize_pixels(new_height);
57        }
58
59        let pos = self.cursor;
60        self.cursor.x += width;
61
62        (
63            PhysicalPixelsRect::new(pos, PhysicalPixelsPoint::new(pos.x + width, pos.y + height)),
64            self.width.clone(),
65            &mut self.pixels,
66        )
67    }
68
69    /// Returns a reference to the pixel data of the atlas.
70    pub fn pixels_mut_ref(&mut self) -> &mut [u8] {
71        &mut self.pixels
72    }
73
74    pub fn pixels(&self) -> Vec<u8> {
75        self.pixels.clone()
76    }
77}