read_fonts/tables/
cbdt.rs

1//! The [CBDT (Color Bitmap Data)](https://docs.microsoft.com/en-us/typography/opentype/spec/cbdt) table
2
3use super::bitmap::{BitmapData, BitmapLocation};
4
5include!("../../generated/generated_cbdt.rs");
6
7impl<'a> Cbdt<'a> {
8    pub fn data(&self, location: &BitmapLocation) -> Result<BitmapData<'a>, ReadError> {
9        super::bitmap::bitmap_data(self.offset_data(), location, true)
10    }
11}
12
13#[cfg(test)]
14mod tests {
15    use super::super::bitmap::{BitmapDataFormat, SmallGlyphMetrics};
16    use crate::{
17        types::{GlyphId, GlyphId16},
18        FontRef, TableProvider,
19    };
20
21    #[test]
22    fn read_cblc_1_cbdt_17() {
23        let font = FontRef::new(font_test_data::EMBEDDED_BITMAPS).unwrap();
24        let cblc = font.cblc().unwrap();
25        let cbdt = font.cbdt().unwrap();
26        let size = &cblc.bitmap_sizes()[0];
27        // Metrics for size at index 0
28        assert!(
29            size.hori.ascender() == 101
30                && size.hori.descender() == -27
31                && size.hori.width_max() == 136
32                && size.vert.ascender() == 101
33                && size.vert.descender() == -27
34                && size.vert.width_max() == 136
35                && size.start_glyph_index() == GlyphId16::new(4)
36                && size.end_glyph_index() == GlyphId16::new(4)
37                && size.ppem_x() == 109
38                && size.ppem_y() == 109
39                && size.bit_depth() == 32
40        );
41        let expected: &[(GlyphId, &[u8], SmallGlyphMetrics)] = &[(
42            GlyphId::new(4),
43            &[0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
44            SmallGlyphMetrics {
45                height: 128,
46                width: 136,
47                bearing_x: 0.into(),
48                bearing_y: 101.into(),
49                advance: 136,
50            },
51        )];
52        for (gid, data, metrics) in expected {
53            let location = size.location(cblc.offset_data(), *gid).unwrap();
54            assert_eq!(location.format, 17);
55            let bitmap_data = cbdt.data(&location).unwrap();
56            let (img_fmt, img_data) = bitmap_data.content.extract_data();
57            assert_eq!(img_fmt, BitmapDataFormat::Png);
58            assert_eq!(img_data, *data);
59            assert_eq!(bitmap_data.extract_small_metrics(), metrics);
60        }
61    }
62
63    #[test]
64    fn sparse_glyph_ids() {
65        let font = FontRef::new(font_test_data::CBDT).unwrap();
66        let cblc = font.cblc().unwrap();
67        let cbdt = font.cbdt().unwrap();
68        let size = &cblc.bitmap_sizes()[0];
69        // this font has a sparse set with gid 1 missing
70        for gid in 0..=3 {
71            let location = size
72                .location(cblc.offset_data(), GlyphId::new(gid))
73                .unwrap();
74            if gid == 1 {
75                assert!(
76                    cbdt.data(&location).is_err(),
77                    "expected bitmap for {gid} to be empty"
78                );
79            } else {
80                assert!(
81                    cbdt.data(&location).is_ok(),
82                    "expected bitmap for {gid} to be present"
83                );
84            }
85        }
86    }
87}