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