1 #![feature(test)]
2 extern crate test;
3
4 use approx::*;
5 use stb_truetype::*;
6
7 /// index map format 12
8 static DEJA_VU_MONO: &[u8] = include_bytes!("../fonts/DejaVuSansMono.ttf");
9 static ROBOTO: &[u8] = include_bytes!("../fonts/Roboto-Regular.ttf");
10 /// index map format 4
11 static GUDEA: &[u8] = include_bytes!("../fonts/Gudea-Regular.ttf");
12
13 const ALPHABET_SIZE: usize = 62;
14 const ALPHABET: &[char; ALPHABET_SIZE] = &[
15 'A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g', 'H', 'h', 'I', 'i', 'J',
16 'j', 'K', 'k', 'L', 'l', 'M', 'm', 'N', 'n', 'O', 'o', 'P', 'p', 'Q', 'q', 'R', 'r', 'S', 's',
17 'T', 't', 'U', 'u', 'V', 'v', 'W', 'w', 'X', 'x', 'W', 'w', 'Z', 'z', '0', '1', '2', '3', '4',
18 '5', '6', '7', '8', '9',
19 ];
20
21 #[bench]
find_glyph_index_deja_vu_mono(b: &mut test::Bencher)22 fn find_glyph_index_deja_vu_mono(b: &mut test::Bencher) {
23 let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
24
25 let mut indices = [0_u32; ALPHABET_SIZE];
26 b.iter(|| {
27 for (i, c) in ALPHABET.iter().enumerate() {
28 indices[i] = font.find_glyph_index(*c as u32);
29 }
30 });
31
32 assert_eq!(
33 indices.to_vec(),
34 vec![
35 36, 68, 37, 69, 38, 70, 39, 71, 40, 72, 41, 73, 42, 74, 43, 75, 44, 76, 45, 77, 46, 78,
36 47, 79, 48, 80, 49, 81, 50, 82, 51, 83, 52, 84, 53, 85, 54, 86, 55, 87, 56, 88, 57, 89,
37 58, 90, 59, 91, 58, 90, 61, 93, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28
38 ]
39 );
40 }
41
42 #[bench]
find_glyph_index_gudea(b: &mut test::Bencher)43 fn find_glyph_index_gudea(b: &mut test::Bencher) {
44 let font = FontInfo::new(&*GUDEA, 0).unwrap();
45
46 let mut indices = [0_u32; ALPHABET_SIZE];
47 b.iter(|| {
48 for (i, c) in ALPHABET.iter().enumerate() {
49 indices[i] = font.find_glyph_index(*c as u32);
50 }
51 });
52
53 assert_eq!(
54 indices.to_vec(),
55 vec![
56 37, 69, 38, 70, 39, 71, 40, 72, 41, 73, 42, 74, 43, 75, 44, 76, 45, 77, 46, 78, 47, 79,
57 48, 80, 49, 81, 50, 82, 51, 83, 52, 84, 53, 85, 54, 86, 55, 87, 56, 88, 57, 89, 58, 90,
58 59, 91, 60, 92, 59, 91, 62, 94, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
59 ]
60 );
61 }
62
63 /// (x0, x1, y0, y1)
rect_to_tuple<T>(r: Rect<T>) -> (T, T, T, T)64 fn rect_to_tuple<T>(r: Rect<T>) -> (T, T, T, T) {
65 (r.x0, r.x1, r.y0, r.y1)
66 }
67
68 #[bench]
get_glyph_box_deja_vu_mono(b: &mut test::Bencher)69 fn get_glyph_box_deja_vu_mono(b: &mut test::Bencher) {
70 let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
71
72 let indices: Vec<_> = ALPHABET
73 .iter()
74 .map(|c| font.find_glyph_index(*c as u32))
75 .collect();
76
77 let mut boxes = [None; ALPHABET_SIZE];
78 b.iter(|| {
79 for (i, glyph_index) in indices.iter().enumerate() {
80 boxes[i] = font.get_glyph_box(*glyph_index);
81 }
82 });
83
84 assert_eq!(rect_to_tuple(boxes[11].unwrap()), (195, 1063, 0, 1556));
85 assert_eq!(rect_to_tuple(boxes[34].unwrap()), (143, 1233, 0, 1493));
86 assert_eq!(rect_to_tuple(boxes[57].unwrap()), (143, 1069, -29, 1493));
87 }
88
89 #[bench]
get_glyph_box_gudea(b: &mut test::Bencher)90 fn get_glyph_box_gudea(b: &mut test::Bencher) {
91 let font = FontInfo::new(&*GUDEA, 0).unwrap();
92
93 let indices: Vec<_> = ALPHABET
94 .iter()
95 .map(|c| font.find_glyph_index(*c as u32))
96 .collect();
97
98 let mut boxes = [None; ALPHABET_SIZE];
99 b.iter(|| {
100 for (i, glyph_index) in indices.iter().enumerate() {
101 boxes[i] = font.get_glyph_box(*glyph_index);
102 }
103 });
104
105 assert_eq!(rect_to_tuple(boxes[11].unwrap()), (35, 316, 0, 710));
106 assert_eq!(rect_to_tuple(boxes[34].unwrap()), (91, 571, 1, 701));
107 assert_eq!(rect_to_tuple(boxes[57].unwrap()), (63, 504, -6, 700));
108 }
109
110 #[bench]
get_glyph_bitmap_box_subpixel_deja_vu_mono(b: &mut test::Bencher)111 fn get_glyph_bitmap_box_subpixel_deja_vu_mono(b: &mut test::Bencher) {
112 let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
113
114 let indices: Vec<_> = ALPHABET
115 .iter()
116 .map(|c| font.find_glyph_index(*c as u32))
117 .collect();
118
119 let (s_x, s_y) = (12.0, 14.5);
120 let scale_y = font.scale_for_pixel_height(s_y);
121 let scale_x = scale_y * s_x / s_y;
122
123 let mut boxes = [None; ALPHABET_SIZE];
124 b.iter(|| {
125 for (i, glyph_index) in indices.iter().enumerate() {
126 boxes[i] =
127 font.get_glyph_bitmap_box_subpixel(*glyph_index, scale_x, scale_y, 656.0, 1034.0);
128 }
129 });
130
131 assert_eq!(rect_to_tuple(boxes[11].unwrap()), (656, 662, 1024, 1034));
132 assert_eq!(rect_to_tuple(boxes[34].unwrap()), (656, 663, 1024, 1034));
133 assert_eq!(rect_to_tuple(boxes[57].unwrap()), (656, 662, 1024, 1035));
134 }
135
136 #[bench]
get_glyph_bitmap_box_subpixel_gudea(b: &mut test::Bencher)137 fn get_glyph_bitmap_box_subpixel_gudea(b: &mut test::Bencher) {
138 let font = FontInfo::new(&*GUDEA, 0).unwrap();
139
140 let indices: Vec<_> = ALPHABET
141 .iter()
142 .map(|c| font.find_glyph_index(*c as u32))
143 .collect();
144
145 let (s_x, s_y) = (12.0, 14.5);
146 let scale_y = font.scale_for_pixel_height(s_y);
147 let scale_x = scale_y * s_x / s_y;
148
149 let mut boxes = [None; ALPHABET_SIZE];
150 b.iter(|| {
151 for (i, glyph_index) in indices.iter().enumerate() {
152 boxes[i] =
153 font.get_glyph_bitmap_box_subpixel(*glyph_index, scale_x, scale_y, 656.0, 1034.0);
154 }
155 });
156
157 assert_eq!(rect_to_tuple(boxes[11].unwrap()), (656, 660, 1025, 1034));
158 assert_eq!(rect_to_tuple(boxes[34].unwrap()), (656, 662, 1025, 1034));
159 assert_eq!(rect_to_tuple(boxes[57].unwrap()), (656, 661, 1025, 1035));
160 }
161
162 /// (x, y, cx, cy, type)
vertex_to_tuple(vert: Vertex) -> (i16, i16, i16, i16, u8)163 fn vertex_to_tuple(vert: Vertex) -> (i16, i16, i16, i16, u8) {
164 (vert.x, vert.y, vert.cx, vert.cy, vert.vertex_type() as u8)
165 }
166
167 #[bench]
get_glyph_shape_deja_vu_mono(b: &mut test::Bencher)168 fn get_glyph_shape_deja_vu_mono(b: &mut test::Bencher) {
169 let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
170
171 let indices: Vec<_> = ALPHABET
172 .iter()
173 .map(|c| font.find_glyph_index(*c as u32))
174 .collect();
175
176 let mut shapes = vec![None; ALPHABET_SIZE];
177 b.iter(|| {
178 for (i, glyph_index) in indices.iter().enumerate() {
179 shapes[i] = font.get_glyph_shape(*glyph_index);
180 }
181 });
182
183 let shapes_11: Vec<_> = shapes[11]
184 .as_ref()
185 .unwrap()
186 .iter()
187 .map(|v| vertex_to_tuple(*v))
188 .collect();
189 assert_eq!(
190 shapes_11,
191 vec![
192 (1063, 1556, 0, 0, 1),
193 (1063, 1403, 0, 0, 2),
194 (854, 1403, 0, 0, 2),
195 (716, 1362, 755, 1403, 3),
196 (678, 1219, 678, 1322, 3),
197 (678, 1120, 0, 0, 2),
198 (1063, 1120, 0, 0, 2),
199 (1063, 977, 0, 0, 2),
200 (678, 977, 0, 0, 2),
201 (678, 0, 0, 0, 2),
202 (494, 0, 0, 0, 2),
203 (494, 977, 0, 0, 2),
204 (195, 977, 0, 0, 2),
205 (195, 1120, 0, 0, 2),
206 (494, 1120, 0, 0, 2),
207 (494, 1198, 0, 0, 2),
208 (578, 1469, 494, 1382, 3),
209 (842, 1556, 663, 1556, 3),
210 (1063, 1556, 0, 0, 2)
211 ]
212 );
213
214 let shapes_47: Vec<_> = shapes[47]
215 .as_ref()
216 .unwrap()
217 .iter()
218 .map(|v| vertex_to_tuple(*v))
219 .collect();
220 assert_eq!(
221 shapes_47,
222 vec![
223 (1118, 1120, 0, 0, 1),
224 (717, 584, 0, 0, 2),
225 (1157, 0, 0, 0, 2),
226 (944, 0, 0, 0, 2),
227 (616, 449, 0, 0, 2),
228 (289, 0, 0, 0, 2),
229 (76, 0, 0, 0, 2),
230 (516, 584, 0, 0, 2),
231 (115, 1120, 0, 0, 2),
232 (319, 1120, 0, 0, 2),
233 (616, 715, 0, 0, 2),
234 (911, 1120, 0, 0, 2),
235 (1118, 1120, 0, 0, 2)
236 ]
237 );
238 }
239
240 #[bench]
get_glyph_shape_gudea(b: &mut test::Bencher)241 fn get_glyph_shape_gudea(b: &mut test::Bencher) {
242 let font = FontInfo::new(&*GUDEA, 0).unwrap();
243
244 let indices: Vec<_> = ALPHABET
245 .iter()
246 .map(|c| font.find_glyph_index(*c as u32))
247 .collect();
248
249 let mut shapes = vec![None; ALPHABET_SIZE];
250 b.iter(|| {
251 for (i, glyph_index) in indices.iter().enumerate() {
252 shapes[i] = font.get_glyph_shape(*glyph_index);
253 }
254 });
255
256 let shapes_11: Vec<_> = shapes[11]
257 .as_ref()
258 .unwrap()
259 .iter()
260 .map(|v| vertex_to_tuple(*v))
261 .collect();
262 assert_eq!(
263 shapes_11,
264 vec![
265 (113, 500, 0, 0, 1),
266 (113, 596, 0, 0, 2),
267 (150, 683, 113, 657, 3),
268 (231, 710, 188, 710, 3),
269 (316, 697, 275, 710, 3),
270 (305, 643, 0, 0, 2),
271 (256, 649, 272, 649, 3),
272 (187, 582, 187, 649, 3),
273 (187, 500, 0, 0, 2),
274 (289, 500, 0, 0, 2),
275 (289, 440, 0, 0, 2),
276 (187, 440, 0, 0, 2),
277 (187, 0, 0, 0, 2),
278 (112, 0, 0, 0, 2),
279 (112, 440, 0, 0, 2),
280 (35, 440, 0, 0, 2),
281 (35, 500, 0, 0, 2),
282 (113, 500, 0, 0, 2)
283 ]
284 );
285
286 let shapes_47: Vec<_> = shapes[47]
287 .as_ref()
288 .unwrap()
289 .iter()
290 .map(|v| vertex_to_tuple(*v))
291 .collect();
292 assert_eq!(
293 shapes_47,
294 vec![
295 (113, 501, 0, 0, 1),
296 (218, 324, 0, 0, 2),
297 (323, 501, 0, 0, 2),
298 (406, 501, 0, 0, 2),
299 (259, 255, 0, 0, 2),
300 (412, 0, 0, 0, 2),
301 (329, 0, 0, 0, 2),
302 (218, 198, 0, 0, 2),
303 (107, 0, 0, 0, 2),
304 (24, 0, 0, 0, 2),
305 (177, 255, 0, 0, 2),
306 (30, 501, 0, 0, 2),
307 (113, 501, 0, 0, 2)
308 ]
309 );
310 }
311
312 #[bench]
get_glyph_shape_compound_glyph_roboto_colon(b: &mut test::Bencher)313 fn get_glyph_shape_compound_glyph_roboto_colon(b: &mut test::Bencher) {
314 let font = FontInfo::new(&*ROBOTO, 0).unwrap();
315
316 let colon_index = font.find_glyph_index(':' as u32);
317
318 let mut shape = None;
319 b.iter(|| {
320 shape = font.get_glyph_shape(colon_index);
321 });
322
323 let shape: Vec<_> = shape.unwrap().iter().map(|v| vertex_to_tuple(*v)).collect();
324
325 assert_eq!(
326 shape,
327 vec![
328 (134, 97, -10, 0, 1),
329 (162, 177, 134, 145, 3),
330 (248, 209, 191, 209, 3),
331 (334, 177, 305, 209, 3),
332 (364, 97, 364, 145, 3),
333 (334, 20, 364, 51, 3),
334 (248, -11, 305, -11, 3),
335 (162, 20, 191, -11, 3),
336 (134, 97, 134, 51, 3),
337 (135, 980, -9, 883, 1),
338 (163, 1060, 135, 1028, 3),
339 (249, 1092, 192, 1092, 3),
340 (335, 1060, 306, 1092, 3),
341 (365, 980, 365, 1028, 3),
342 (335, 903, 365, 934, 3),
343 (249, 872, 306, 872, 3),
344 (163, 903, 192, 872, 3),
345 (135, 980, 135, 934, 3)
346 ]
347 );
348 }
349
350 /// (advance_width, left_side_bearing)
h_metrics_to_tuple(h: HMetrics) -> (i32, i32)351 fn h_metrics_to_tuple(h: HMetrics) -> (i32, i32) {
352 (h.advance_width, h.left_side_bearing)
353 }
354
355 #[bench]
get_glyph_h_metrics_deja_vu_mono(b: &mut test::Bencher)356 fn get_glyph_h_metrics_deja_vu_mono(b: &mut test::Bencher) {
357 let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
358
359 let indices: Vec<_> = ALPHABET
360 .iter()
361 .map(|c| font.find_glyph_index(*c as u32))
362 .collect();
363
364 let mut h_metrics = [HMetrics {
365 advance_width: 0,
366 left_side_bearing: 0,
367 }; ALPHABET_SIZE];
368 b.iter(|| {
369 for (i, glyph_index) in indices.iter().enumerate() {
370 h_metrics[i] = font.get_glyph_h_metrics(*glyph_index);
371 }
372 });
373
374 assert_eq!(h_metrics_to_tuple(h_metrics[11]), (1233, 195));
375 assert_eq!(h_metrics_to_tuple(h_metrics[25]), (1233, 109));
376 assert_eq!(h_metrics_to_tuple(h_metrics[49]), (1233, 0));
377 }
378
379 #[bench]
get_glyph_h_metrics_gudea(b: &mut test::Bencher)380 fn get_glyph_h_metrics_gudea(b: &mut test::Bencher) {
381 let font = FontInfo::new(&*GUDEA, 0).unwrap();
382
383 let indices: Vec<_> = ALPHABET
384 .iter()
385 .map(|c| font.find_glyph_index(*c as u32))
386 .collect();
387
388 let mut h_metrics = [HMetrics {
389 advance_width: 0,
390 left_side_bearing: 0,
391 }; ALPHABET_SIZE];
392 b.iter(|| {
393 for (i, glyph_index) in indices.iter().enumerate() {
394 h_metrics[i] = font.get_glyph_h_metrics(*glyph_index);
395 }
396 });
397
398 assert_eq!(h_metrics_to_tuple(h_metrics[11]), (291, 35));
399 assert_eq!(h_metrics_to_tuple(h_metrics[25]), (850, 91));
400 assert_eq!(h_metrics_to_tuple(h_metrics[49]), (679, 11));
401 }
402
403 #[bench]
scale_for_pixel_height_deja_vu_mono(b: &mut test::Bencher)404 fn scale_for_pixel_height_deja_vu_mono(b: &mut test::Bencher) {
405 let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
406
407 let pixel_heights: [f32; 8] = [1.0, 12.0, 14.5, 25.5, 50.0, 112.2, 500.5, 657.5];
408
409 let mut scales = [0.0; 8];
410 b.iter(|| {
411 // repeat so its a similar number of calls to the other benchmarks
412 for _ in 0..test::black_box(8) {
413 for (i, pixel_height) in pixel_heights.iter().enumerate() {
414 scales[i] = font.scale_for_pixel_height(*pixel_height);
415 }
416 }
417 });
418
419 assert_relative_eq!(scales[0], 0.000_419_463_1);
420 assert_relative_eq!(scales[1], 0.005_033_557);
421 assert_relative_eq!(scales[2], 0.006_082_215);
422 assert_relative_eq!(scales[3], 0.010_696_309);
423 assert_relative_eq!(scales[4], 0.020_973_155);
424 assert_relative_eq!(scales[5], 0.047_063_757);
425 assert_relative_eq!(scales[6], 0.209_941_27);
426 assert_relative_eq!(scales[7], 0.275_796_98);
427 }
428
429 #[bench]
scale_for_pixel_height_gudea(b: &mut test::Bencher)430 fn scale_for_pixel_height_gudea(b: &mut test::Bencher) {
431 let font = FontInfo::new(&*GUDEA, 0).unwrap();
432
433 let pixel_heights: [f32; 8] = [1.0, 12.0, 14.5, 25.5, 50.0, 112.2, 500.5, 657.5];
434
435 let mut scales = [0.0; 8];
436 b.iter(|| {
437 // repeat so its a similar number of calls to the other benchmarks
438 for _ in 0..test::black_box(8) {
439 for (i, pixel_height) in pixel_heights.iter().enumerate() {
440 scales[i] = font.scale_for_pixel_height(*pixel_height);
441 }
442 }
443 });
444
445 assert_relative_eq!(scales[0], 0.000_809_061_5);
446 assert_relative_eq!(scales[1], 0.009_708_738);
447 assert_relative_eq!(scales[2], 0.011_731_392);
448 assert_relative_eq!(scales[3], 0.020_631_067);
449 assert_relative_eq!(scales[4], 0.040_453_073);
450 assert_relative_eq!(scales[5], 0.090_776_7);
451 assert_relative_eq!(scales[6], 0.404_935_27);
452 assert_relative_eq!(scales[7], 0.531_957_9);
453 }
454
455 #[bench]
get_v_metrics_deja_vu_mono(b: &mut test::Bencher)456 fn get_v_metrics_deja_vu_mono(b: &mut test::Bencher) {
457 let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
458
459 let mut v_metrics = VMetrics {
460 ascent: 1,
461 descent: 2,
462 line_gap: 3,
463 };
464 b.iter(|| {
465 // repeat so its a similar number of calls to the other benchmarks
466 for _ in 0..test::black_box(ALPHABET_SIZE) {
467 v_metrics = font.get_v_metrics();
468 }
469 });
470
471 let VMetrics {
472 ascent,
473 descent,
474 line_gap,
475 } = v_metrics;
476 assert_eq!(ascent, 1901);
477 assert_eq!(descent, -483);
478 assert_eq!(line_gap, 0);
479 }
480
481 #[bench]
get_v_metrics_gudea(b: &mut test::Bencher)482 fn get_v_metrics_gudea(b: &mut test::Bencher) {
483 let font = FontInfo::new(&*GUDEA, 0).unwrap();
484
485 let mut v_metrics = VMetrics {
486 ascent: 1,
487 descent: 2,
488 line_gap: 3,
489 };
490 b.iter(|| {
491 // repeat so its a similar number of calls to the other benchmarks
492 for _ in 0..test::black_box(ALPHABET_SIZE) {
493 v_metrics = font.get_v_metrics();
494 }
495 });
496
497 let VMetrics {
498 ascent,
499 descent,
500 line_gap,
501 } = v_metrics;
502 assert_eq!(ascent, 972);
503 assert_eq!(descent, -264);
504 assert_eq!(line_gap, 0);
505 }
506