Skip to main content

ttf_view/tables/cmap/
format2.rs

1use crate::{
2    tables::cmap::GlyphId,
3    types::{int16, uint16},
4};
5
6#[repr(C)]
7#[non_exhaustive]
8pub struct Format2 {
9    pub sub_header_keys: [uint16; 256],
10    sub_headers: [SubHeader; 0],
11    glyph_id_array: [uint16; 0],
12}
13
14#[repr(C)]
15#[non_exhaustive]
16pub struct SubHeader {
17    pub first_code: uint16,
18    pub entry_count: uint16,
19    pub id_delta: int16,
20    pub id_range_offset: uint16,
21}
22
23impl super::CmapSubtableTrait for Format2 {
24    const FORMAT: u16 = 2;
25}
26
27impl Format2 {
28    pub fn sub_headers(&self) -> &[SubHeader] {
29        let max_offset = self.sub_header_keys.iter().max().unwrap().get();
30        let count = (max_offset / 8) + 1;
31        unsafe { std::slice::from_raw_parts(self.sub_headers.as_ptr(), count as _) }
32    }
33    pub const fn sub_header(&self, high_byte: u8) -> &SubHeader {
34        let offset = self.sub_header_keys[high_byte as usize].get();
35        unsafe { &*self.sub_headers.as_ptr().byte_add(offset as usize) }
36    }
37    pub const fn sub_header_zero(&self) -> &SubHeader {
38        unsafe { &*self.sub_headers.as_ptr() }
39    }
40
41    pub const fn map_one(&self, single_byte: u8) -> GlyphId {
42        self.sub_header_zero().map(single_byte)
43    }
44    pub const fn map_two(&self, high_byte: u8, low_byte: u8) -> GlyphId {
45        self.sub_header(high_byte).map(low_byte)
46    }
47}
48
49impl SubHeader {
50    pub const fn map(&self, low_byte: u8) -> GlyphId {
51        let offset = (low_byte as u16).checked_sub(self.first_code.get())?;
52        if offset > self.entry_count.get() {
53            return GlyphId::NOTDEF;
54        }
55
56        let mut result = unsafe {
57            (&*std::ptr::from_ref(&self.id_range_offset)
58                .byte_add(self.id_range_offset.get() as _)
59                .add(offset as _))
60                .get()
61        };
62        if result != 0 {
63            result = result.wrapping_add_signed(self.id_delta.get());
64        }
65
66        GlyphId::new(result)
67    }
68}