ttf_parser/tables/cmap/
format14.rs
1use crate::GlyphId;
4use crate::parser::{Stream, FromData, Offset, Offset32, U24};
5
6#[derive(Clone, Copy)]
7struct VariationSelectorRecord {
8 var_selector: u32,
9 default_uvs_offset: Option<Offset32>,
10 non_default_uvs_offset: Option<Offset32>,
11}
12
13impl FromData for VariationSelectorRecord {
14 const SIZE: usize = 11;
15
16 #[inline]
17 fn parse(data: &[u8]) -> Option<Self> {
18 let mut s = Stream::new(data);
19 Some(VariationSelectorRecord {
20 var_selector: s.read::<U24>()?.0,
21 default_uvs_offset: s.read::<Option<Offset32>>()?,
22 non_default_uvs_offset: s.read::<Option<Offset32>>()?,
23 })
24 }
25}
26
27
28#[derive(Clone, Copy)]
29struct UVSMappingRecord {
30 unicode_value: u32,
31 glyph_id: GlyphId,
32}
33
34impl FromData for UVSMappingRecord {
35 const SIZE: usize = 5;
36
37 #[inline]
38 fn parse(data: &[u8]) -> Option<Self> {
39 let mut s = Stream::new(data);
40 Some(UVSMappingRecord {
41 unicode_value: s.read::<U24>()?.0,
42 glyph_id: s.read::<GlyphId>()?,
43 })
44 }
45}
46
47
48#[derive(Clone, Copy)]
49struct UnicodeRangeRecord {
50 start_unicode_value: u32,
51 additional_count: u8,
52}
53
54impl UnicodeRangeRecord {
55 fn contains(&self, c: u32) -> bool {
56 let end = self.start_unicode_value + u32::from(self.additional_count);
58 (self.start_unicode_value..=end).contains(&c)
59 }
60}
61
62impl FromData for UnicodeRangeRecord {
63 const SIZE: usize = 4;
64
65 #[inline]
66 fn parse(data: &[u8]) -> Option<Self> {
67 let mut s = Stream::new(data);
68 Some(UnicodeRangeRecord {
69 start_unicode_value: s.read::<U24>()?.0,
70 additional_count: s.read::<u8>()?,
71 })
72 }
73}
74
75
76#[derive(Clone, Copy, PartialEq, Debug)]
78pub enum GlyphVariationResult {
79 Found(GlyphId),
81 UseDefault,
86}
87
88
89pub fn parse(data: &[u8], c: u32, variation: u32) -> Option<GlyphVariationResult> {
90 let mut s = Stream::new(data);
91 s.skip::<u16>(); s.skip::<u32>(); let count: u32 = s.read()?;
94 let records = s.read_array32::<VariationSelectorRecord>(count)?;
95
96 let (_, record) = records.binary_search_by(|v| v.var_selector.cmp(&variation))?;
97
98 if let Some(offset) = record.default_uvs_offset {
99 let data = data.get(offset.to_usize()..)?;
100 let mut s = Stream::new(data);
101 let count: u32 = s.read()?;
102 let ranges = s.read_array32::<UnicodeRangeRecord>(count)?;
103 for range in ranges {
104 if range.contains(c) {
105 return Some(GlyphVariationResult::UseDefault);
106 }
107 }
108 }
109
110 if let Some(offset) = record.non_default_uvs_offset {
111 let data = data.get(offset.to_usize()..)?;
112 let mut s = Stream::new(data);
113 let count: u32 = s.read()?;
114 let uvs_mappings = s.read_array32::<UVSMappingRecord>(count)?;
115 let (_, mapping) = uvs_mappings.binary_search_by(|v| v.unicode_value.cmp(&c))?;
116 return Some(GlyphVariationResult::Found(mapping.glyph_id));
117 }
118
119 None
120}