ttf_parser/tables/cmap/
format14.rs1use crate::GlyphId;
2use crate::parser::{FromData, LazyArray32, Offset, Offset32, Stream, U24};
3
4#[derive(Clone, Copy)]
5struct VariationSelectorRecord {
6 var_selector: u32,
7 default_uvs_offset: Option<Offset32>,
8 non_default_uvs_offset: Option<Offset32>,
9}
10
11impl FromData for VariationSelectorRecord {
12 const SIZE: usize = 11;
13
14 #[inline]
15 fn parse(data: &[u8]) -> Option<Self> {
16 let mut s = Stream::new(data);
17 Some(VariationSelectorRecord {
18 var_selector: s.read::<U24>()?.0,
19 default_uvs_offset: s.read::<Option<Offset32>>()?,
20 non_default_uvs_offset: s.read::<Option<Offset32>>()?,
21 })
22 }
23}
24
25
26#[derive(Clone, Copy)]
27struct UVSMappingRecord {
28 unicode_value: u32,
29 glyph_id: GlyphId,
30}
31
32impl FromData for UVSMappingRecord {
33 const SIZE: usize = 5;
34
35 #[inline]
36 fn parse(data: &[u8]) -> Option<Self> {
37 let mut s = Stream::new(data);
38 Some(UVSMappingRecord {
39 unicode_value: s.read::<U24>()?.0,
40 glyph_id: s.read::<GlyphId>()?,
41 })
42 }
43}
44
45
46#[derive(Clone, Copy)]
47struct UnicodeRangeRecord {
48 start_unicode_value: u32,
49 additional_count: u8,
50}
51
52impl UnicodeRangeRecord {
53 fn contains(&self, c: u32) -> bool {
54 let end = self.start_unicode_value + u32::from(self.additional_count);
56 (self.start_unicode_value..=end).contains(&c)
57 }
58}
59
60impl FromData for UnicodeRangeRecord {
61 const SIZE: usize = 4;
62
63 #[inline]
64 fn parse(data: &[u8]) -> Option<Self> {
65 let mut s = Stream::new(data);
66 Some(UnicodeRangeRecord {
67 start_unicode_value: s.read::<U24>()?.0,
68 additional_count: s.read::<u8>()?,
69 })
70 }
71}
72
73
74#[derive(Clone, Copy, PartialEq, Debug)]
76pub enum GlyphVariationResult {
77 Found(GlyphId),
79 UseDefault,
84}
85
86
87#[derive(Clone, Copy)]
90pub struct Subtable14<'a> {
91 records: LazyArray32<'a, VariationSelectorRecord>,
92 data: &'a [u8],
94}
95
96impl<'a> Subtable14<'a> {
97 pub fn parse(data: &'a [u8]) -> Option<Self> {
99 let mut s = Stream::new(data);
100 s.skip::<u16>(); s.skip::<u32>(); let count = s.read::<u32>()?;
103 let records = s.read_array32::<VariationSelectorRecord>(count)?;
104 Some(Self { records, data })
105 }
106
107 pub fn glyph_index(&self, code_point: u32, variation: u32) -> Option<GlyphVariationResult> {
109 let (_, record) = self.records.binary_search_by(|v| v.var_selector.cmp(&variation))?;
110
111 if let Some(offset) = record.default_uvs_offset {
112 let data = self.data.get(offset.to_usize()..)?;
113 let mut s = Stream::new(data);
114 let count = s.read::<u32>()?;
115 let ranges = s.read_array32::<UnicodeRangeRecord>(count)?;
116 for range in ranges {
117 if range.contains(code_point) {
118 return Some(GlyphVariationResult::UseDefault);
119 }
120 }
121 }
122
123 if let Some(offset) = record.non_default_uvs_offset {
124 let data = self.data.get(offset.to_usize()..)?;
125 let mut s = Stream::new(data);
126 let count = s.read::<u32>()?;
127 let uvs_mappings = s.read_array32::<UVSMappingRecord>(count)?;
128 let (_, mapping) = uvs_mappings.binary_search_by(|v| v.unicode_value.cmp(&code_point))?;
129 return Some(GlyphVariationResult::Found(mapping.glyph_id));
130 }
131
132 None
133 }
134}
135
136impl core::fmt::Debug for Subtable14<'_> {
137 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
138 write!(f, "Subtable14 {{ ... }}")
139 }
140}