1pub struct Atlas {
2 lookup_table: Vec<Option<GlyphRegion>>,
3 algorithm: AtlasAlgorithm,
4 width: usize,
5 height: usize,
6 current_x: usize,
7 current_y: usize
8}
9
10impl Atlas {
11 pub fn lookup_table(&self) -> &[Option<GlyphRegion>] {
12 &self.lookup_table
13 }
14
15 pub fn algorithm(&self) -> AtlasAlgorithm {
16 self.algorithm
17 }
18
19 pub fn width(&self) -> usize {
20 self.width
21 }
22
23 pub fn height(&self) -> usize {
24 self.height
25 }
26
27 pub fn current_x(&self) -> usize {
28 self.current_x
29 }
30
31 pub fn current_y(&self) -> usize {
32 self.current_y
33 }
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub struct GlyphRegion {
38 x: usize,
39 y: usize,
40 width: usize,
41 height: usize
42}
43
44impl GlyphRegion {
45 pub fn x(&self) -> usize {
46 self.x
47 }
48
49 pub fn y(&self) -> usize {
50 self.y
51 }
52
53 pub fn width(&self) -> usize {
54 self.width
55 }
56
57 pub fn height(&self) -> usize {
58 self.height
59 }
60}
61
62impl Atlas {
63 pub fn new(algorithm: AtlasAlgorithm) -> Self {
64 Self {
65 lookup_table: vec![None; 1114112],
66 algorithm,
67 width: 0,
68 height: 0,
69 current_x: 0,
70 current_y: 0
71 }
72 }
73
74 pub fn append(&mut self, bitmaps: Vec<(char, Vec<Vec<u8>>)>, buffer: &mut Vec<(GlyphRegion, Vec<u8>)>) {
75 match self.algorithm {
76 AtlasAlgorithm::ShelfPacker => self.shelf_packer(bitmaps, buffer)
77 }
78 }
79
80 fn shelf_packer(&mut self, mut bitmaps: Vec<(char, Vec<Vec<u8>>)>, buffer: &mut Vec<(GlyphRegion, Vec<u8>)>) {
83 bitmaps.sort_by(|a, b| b.1.len().cmp(&a.1.len()));
84 let mut area = 0;
85 bitmaps.iter()
86 .for_each(|(_, bitmap)| {
87 area += bitmap.len() * bitmap[0].len();
88 });
89 area += self.width * self.width;
90 let n = area.isqrt();
91 let width = if (n & (n - 1)) != 0 { 1 << (usize::BITS - n.leading_zeros()) } else { n };
92 if self.height == 0 { self.height = bitmaps[0].1.len(); }
93 if self.width < width { self.width = width; }
94 buffer.extend(bitmaps.into_iter()
95 .map(|(char, bitmap)| {
96 if self.current_x + bitmap[0].len() > self.width || bitmap.len() > self.height - self.current_y {
97 self.current_x = 0;
98 self.current_y = self.height;
99 self.height += bitmap.len();
100 }
101
102 let region = GlyphRegion {
103 x: self.current_x,
104 y: self.current_y,
105 width: bitmap[0].len(),
106 height: bitmap.len()
107 };
108
109 self.lookup_table[char as usize] = Some(region);
110
111 self.current_x += bitmap[0].len();
112
113 (region, bitmap.into_iter().flatten().collect::<Vec<u8>>())
114 }).collect::<Vec<(GlyphRegion, Vec<u8>)>>())
115 }
116}
117
118#[derive(Clone, Copy)]
119pub enum AtlasAlgorithm {
120 ShelfPacker
121 }
124
125#[cfg(test)]
126mod test {
127 use crate::fonts::atlas::generator::{Atlas, AtlasAlgorithm, GlyphRegion};
128
129 #[test]
130 fn test_shelf_packer() {
131 let mut atlas = Atlas::new(AtlasAlgorithm::ShelfPacker);
132 let a_bitmap = vec![
133 vec![0, 1, 0],
134 vec![1, 1, 1],
135 vec![1, 0, 1]
136 ];
137 let d_bitmap = vec![
138 vec![1, 1, 0],
139 vec![1, 0, 1],
140 vec![1, 1, 0]
141 ];
142 let b_bitmap = vec![
143 vec![1, 1, 0],
144 vec![1, 0, 1],
145 vec![1, 1, 0],
146 vec![1, 0, 1],
147 vec![1, 1, 0]
148 ];
149 let mut regions: Vec<(GlyphRegion, Vec<u8>)> = Vec::new();
150 atlas.append(
151 vec![
152 ('A', a_bitmap),
153 ('D', d_bitmap),
154 ('B', b_bitmap)
155 ],
156 &mut regions
157 );
158 let b_glyph_region = atlas.lookup_table['B' as usize];
159 match b_glyph_region {
160 Some(gr) => {
161 assert_eq!(gr.x, 0);
162 assert_eq!(gr.y, 0);
163 assert_eq!(gr.width, 3);
164 assert_eq!(gr.height, 5);
165 }
166 None => panic!("Glyph 'B' doesn't exist when it clearly should")
167 }
168 assert_eq!(regions[0].1.len(), 15);
169 assert_eq!(regions[0].1[0 * 3 + 0], 1);
170 assert_eq!(regions[0].1[0 * 3 + 1], 1);
171 assert_eq!(regions[0].1[0 * 3 + 2], 0);
172 assert_eq!(regions[0].1[1 * 3 + 0], 1);
173 assert_eq!(regions[0].1[1 * 3 + 1], 0);
174 assert_eq!(regions[0].1[1 * 3 + 2], 1);
175 assert_eq!(regions[0].1[2 * 3 + 0], 1);
176 assert_eq!(regions[0].1[2 * 3 + 1], 1);
177 assert_eq!(regions[0].1[2 * 3 + 2], 0);
178 assert_eq!(regions[0].1[3 * 3 + 1], 0);
179 assert_eq!(regions[0].1[3 * 3 + 2], 1);
180 assert_eq!(regions[0].1[4 * 3 + 0], 1);
181 assert_eq!(regions[0].1[4 * 3 + 1], 1);
182 assert_eq!(regions[0].1[4 * 3 + 2], 0);
183 let a_glyph_region = atlas.lookup_table['A' as usize];
184 match a_glyph_region {
185 Some(gr) => {
186 assert_eq!(gr.x, 3);
187 assert_eq!(gr.y, 0);
188 assert_eq!(gr.width, 3);
189 assert_eq!(gr.height, 3);
190 }
191 None => panic!("Glyph 'A' doesn't exist when it clearly should")
192 }
193 assert_eq!(regions[1].1[0 * 3 + 0], 0);
194 assert_eq!(regions[1].1[0 * 3 + 1], 1);
195 assert_eq!(regions[1].1[0 * 3 + 2], 0);
196 assert_eq!(regions[1].1[1 * 3 + 0], 1);
197 assert_eq!(regions[1].1[1 * 3 + 1], 1);
198 assert_eq!(regions[1].1[1 * 3 + 2], 1);
199 assert_eq!(regions[1].1[2 * 3 + 0], 1);
200 assert_eq!(regions[1].1[2 * 3 + 1], 0);
201 assert_eq!(regions[1].1[2 * 3 + 2], 1);
202 let d_glyph_region = atlas.lookup_table['D' as usize];
204 match d_glyph_region {
205 Some(gr) => {
206 assert_eq!(gr.x, 0);
207 assert_eq!(gr.y, 5);
208 assert_eq!(gr.width, 3);
209 assert_eq!(gr.height, 3);
210 },
211 None => panic!("Glyph 'D' doesn't exist when it clearly should")
212 }
213 assert_eq!(regions[2].1[0 * 3 + 0], 1);
214 assert_eq!(regions[2].1[0 * 3 + 1], 1);
215 assert_eq!(regions[2].1[0 * 3 + 2], 0);
216 assert_eq!(regions[2].1[1 * 3 + 0], 1);
217 assert_eq!(regions[2].1[1 * 3 + 1], 0);
218 assert_eq!(regions[2].1[1 * 3 + 2], 1);
219 assert_eq!(regions[2].1[2 * 3 + 0], 1);
220 assert_eq!(regions[2].1[2 * 3 + 1], 1);
221 assert_eq!(regions[2].1[2 * 3 + 2], 0);
222
223 let mut atlas = Atlas::new(AtlasAlgorithm::ShelfPacker);
225 let a_bitmap = vec![
226 vec![0, 1, 0],
227 vec![1, 1, 1],
228 vec![1, 0, 1]
229 ];
230 let d_bitmap = vec![
231 vec![1, 1, 0],
232 vec![1, 0, 1],
233 vec![1, 1, 0]
234 ];
235 let b_bitmap = vec![
236 vec![1, 1, 0],
237 vec![1, 0, 1],
238 vec![1, 1, 0],
239 vec![1, 0, 1],
240 vec![1, 1, 0]
241 ];
242 let mut regions: Vec<(GlyphRegion, Vec<u8>)> = Vec::new();
243 atlas.append(vec![('A', a_bitmap)], &mut regions);
244 atlas.append(vec![('D', d_bitmap)], &mut regions);
245 atlas.append(vec![('B', b_bitmap)], &mut regions);
246 let a_glyph_region = atlas.lookup_table['A' as usize];
247 match a_glyph_region {
248 Some(gr) => {
249 assert_eq!(gr.x, 0);
250 assert_eq!(gr.y, 0);
251 assert_eq!(gr.width, 3);
252 assert_eq!(gr.height, 3);
253 }
254 None => panic!("Glyph 'A' doesn't exist when it clearly should")
255 }
256 assert_eq!(regions[0].1[0 * 3 + 0], 0);
257 assert_eq!(regions[0].1[0 * 3 + 1], 1);
258 assert_eq!(regions[0].1[0 * 3 + 2], 0);
259 assert_eq!(regions[0].1[1 * 3 + 0], 1);
260 assert_eq!(regions[0].1[1 * 3 + 1], 1);
261 assert_eq!(regions[0].1[1 * 3 + 2], 1);
262 assert_eq!(regions[0].1[2 * 3 + 0], 1);
263 assert_eq!(regions[0].1[2 * 3 + 1], 0);
264 assert_eq!(regions[0].1[2 * 3 + 2], 1);
265 let d_glyph_region = atlas.lookup_table['D' as usize];
266 match d_glyph_region {
267 Some(gr) => {
268 assert_eq!(gr.x, 3);
269 assert_eq!(gr.y, 0);
270 assert_eq!(gr.width, 3);
271 assert_eq!(gr.height, 3);
272 },
273 None => panic!("Glyph 'D' doesn't exist when it clearly should")
274 }
275 assert_eq!(regions[1].1[0 * 3 + 0], 1);
276 assert_eq!(regions[1].1[0 * 3 + 1], 1);
277 assert_eq!(regions[1].1[0 * 3 + 2], 0);
278 assert_eq!(regions[1].1[1 * 3 + 0], 1);
279 assert_eq!(regions[1].1[1 * 3 + 1], 0);
280 assert_eq!(regions[1].1[1 * 3 + 2], 1);
281 assert_eq!(regions[1].1[2 * 3 + 0], 1);
282 assert_eq!(regions[1].1[2 * 3 + 1], 1);
283 assert_eq!(regions[1].1[2 * 3 + 2], 0);
284 let b_glyph_region = atlas.lookup_table['B' as usize];
285 match b_glyph_region {
286 Some(gr) => {
287 assert_eq!(gr.x, 0);
288 assert_eq!(gr.y, 3);
289 assert_eq!(gr.width, 3);
290 assert_eq!(gr.height, 5);
291 }
292 None => panic!("Glyph 'B' doesn't exist when it clearly should")
293 }
294 assert_eq!(regions[2].1.len(), 15);
295 assert_eq!(regions[2].1[0 * 3 + 0], 1);
296 assert_eq!(regions[2].1[0 * 3 + 1], 1);
297 assert_eq!(regions[2].1[0 * 3 + 2], 0);
298 assert_eq!(regions[2].1[1 * 3 + 0], 1);
299 assert_eq!(regions[2].1[1 * 3 + 1], 0);
300 assert_eq!(regions[2].1[1 * 3 + 2], 1);
301 assert_eq!(regions[2].1[2 * 3 + 0], 1);
302 assert_eq!(regions[2].1[2 * 3 + 1], 1);
303 assert_eq!(regions[2].1[2 * 3 + 2], 0);
304 assert_eq!(regions[2].1[3 * 3 + 0], 1);
305 assert_eq!(regions[2].1[3 * 3 + 1], 0);
306 assert_eq!(regions[2].1[3 * 3 + 2], 1);
307 assert_eq!(regions[2].1[4 * 3 + 0], 1);
308 assert_eq!(regions[2].1[4 * 3 + 1], 1);
309 assert_eq!(regions[2].1[4 * 3 + 2], 0);
310 }
311}