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