1// https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-0-byte-encoding-table
23use crate::parser::{Stream, NumFrom};
45pub fn parse(data: &[u8], code_point: u32) -> Option<u16> {
6let mut s = Stream::new(data);
7 s.skip::<u16>(); // format
8s.skip::<u16>(); // length
9s.skip::<u16>(); // language
1011s.advance(usize::num_from(code_point));
12let glyph_id: u8 = s.read()?;
1314// Make sure that the glyph is not zero, the array always has length 256,
15 // but some codepoints may be mapped to zero.
16if glyph_id != 0 {
17Some(u16::from(glyph_id))
18 } else {
19None
20}
21}
2223pub fn codepoints(data: &[u8], mut f: impl FnMut(u32)) -> Option<()> {
24let mut s = Stream::new(data);
25 s.skip::<u16>(); // format
26s.skip::<u16>(); // length
27s.skip::<u16>(); // language
2829for code_point in 0..256 {
30// In contrast to every other format, here we take a look at the glyph
31 // id and check whether it is zero because otherwise this method would
32 // always simply call `f` for `0..256` which would be kind of pointless
33 // (this array always has length 256 even when the face has only fewer
34 // glyphs).
35let glyph_id: u8 = s.read()?;
36if glyph_id != 0 {
37 f(code_point);
38 }
39 }
4041Some(())
42}
4344#[cfg(test)]
45mod tests {
46use super::{parse, codepoints};
4748#[test]
49fn maps_not_all_256_codepoints() {
50let mut data = vec![
510x00, 0x00, // format: 0
520x01, 0x06, // subtable size: 262
530x00, 0x00, // language ID: 0
54];
5556// Map (only) codepoint 0x40 to 100.
57data.extend(std::iter::repeat(0).take(256));
58 data[6 + 0x40] = 100;
5960assert_eq!(parse(&data, 0), None);
61assert_eq!(parse(&data, 0x40), Some(100));
62assert_eq!(parse(&data, 100), None);
6364let mut vec = vec![];
65 codepoints(&data, |c| vec.push(c));
66assert_eq!(vec, [0x40]);
67 }
68}