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 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}