text_typeset/atlas/
allocator.rs1use etagere::{AllocId, Allocation, BucketedAtlasAllocator, size2};
2
3const INITIAL_ATLAS_SIZE: i32 = 512;
4const MAX_ATLAS_SIZE: i32 = 4096;
5
6pub struct GlyphAtlas {
7 pub allocator: BucketedAtlasAllocator,
8 pub pixels: Vec<u8>,
9 pub width: u32,
10 pub height: u32,
11 pub dirty: bool,
12}
13
14impl Default for GlyphAtlas {
15 fn default() -> Self {
16 Self::new()
17 }
18}
19
20impl GlyphAtlas {
21 pub fn new() -> Self {
22 let size = INITIAL_ATLAS_SIZE;
23 let pixel_count = (size * size) as usize * 4;
24 Self {
25 allocator: BucketedAtlasAllocator::new(size2(size, size)),
26 pixels: vec![0u8; pixel_count],
27 width: size as u32,
28 height: size as u32,
29 dirty: false,
30 }
31 }
32
33 pub fn allocate(&mut self, width: u32, height: u32) -> Option<Allocation> {
34 let size = size2(width as i32, height as i32);
35 if let Some(alloc) = self.allocator.allocate(size) {
36 return Some(alloc);
37 }
38 let new_w = (self.width * 2).min(MAX_ATLAS_SIZE as u32) as i32;
40 let new_h = (self.height * 2).min(MAX_ATLAS_SIZE as u32) as i32;
41 if new_w as u32 == self.width && new_h as u32 == self.height {
42 return None; }
44 self.grow(new_w as u32, new_h as u32);
45 self.allocator.allocate(size)
46 }
47
48 pub fn deallocate(&mut self, id: AllocId) {
49 self.allocator.deallocate(id);
50 }
51
52 fn grow(&mut self, new_width: u32, new_height: u32) {
53 let mut new_pixels = vec![0u8; (new_width * new_height) as usize * 4];
54 for y in 0..self.height {
56 let src_start = (y * self.width) as usize * 4;
57 let src_end = src_start + self.width as usize * 4;
58 let dst_start = (y * new_width) as usize * 4;
59 let dst_end = dst_start + self.width as usize * 4;
60 new_pixels[dst_start..dst_end].copy_from_slice(&self.pixels[src_start..src_end]);
61 }
62 self.allocator
63 .grow(size2(new_width as i32, new_height as i32));
64 self.pixels = new_pixels;
65 self.width = new_width;
66 self.height = new_height;
67 self.dirty = true;
68 }
69
70 pub fn blit_rgba(&mut self, x: u32, y: u32, w: u32, h: u32, data: &[u8]) {
72 for row in 0..h {
73 let src_start = (row * w) as usize * 4;
74 let src_end = src_start + w as usize * 4;
75 let dst_start = ((y + row) * self.width + x) as usize * 4;
76 let dst_end = dst_start + w as usize * 4;
77 self.pixels[dst_start..dst_end].copy_from_slice(&data[src_start..src_end]);
78 }
79 self.dirty = true;
80 }
81
82 pub fn blit_mask(&mut self, x: u32, y: u32, w: u32, h: u32, data: &[u8]) {
84 for row in 0..h {
85 for col in 0..w {
86 let alpha = data[(row * w + col) as usize];
87 let dst = ((y + row) * self.width + x + col) as usize * 4;
88 self.pixels[dst] = 255;
89 self.pixels[dst + 1] = 255;
90 self.pixels[dst + 2] = 255;
91 self.pixels[dst + 3] = alpha;
92 }
93 }
94 self.dirty = true;
95 }
96}