ttf_parser/
ggg.rs
1use crate::GlyphId;
4use crate::parser::*;
5
6
7#[derive(Clone, Copy)]
8struct RangeRecord {
9 start_glyph_id: GlyphId,
10 end_glyph_id: GlyphId,
11 value: u16,
12}
13
14impl RangeRecord {
15 fn range(&self) -> core::ops::RangeInclusive<GlyphId> {
16 self.start_glyph_id..=self.end_glyph_id
17 }
18}
19
20impl FromData for RangeRecord {
21 const SIZE: usize = 6;
22
23 #[inline]
24 fn parse(data: &[u8]) -> Option<Self> {
25 let mut s = Stream::new(data);
26 Some(RangeRecord {
27 start_glyph_id: s.read::<GlyphId>()?,
28 end_glyph_id: s.read::<GlyphId>()?,
29 value: s.read::<u16>()?,
30 })
31 }
32}
33
34
35#[derive(Clone, Copy, Debug)]
37pub(crate) struct CoverageTable<'a> {
38 data: &'a [u8],
39}
40
41impl<'a> CoverageTable<'a> {
42 pub fn new(data: &'a [u8]) -> Self {
43 CoverageTable { data }
44 }
45
46 pub fn contains(&self, glyph_id: GlyphId) -> bool {
47 let mut s = Stream::new(self.data);
48 let format: u16 = try_opt_or!(s.read(), false);
49
50 match format {
51 1 => {
52 let count = try_opt_or!(s.read::<u16>(), false);
53 s.read_array16::<GlyphId>(count).unwrap().binary_search(&glyph_id).is_some()
54 }
55 2 => {
56 let count = try_opt_or!(s.read::<u16>(), false);
57 let records = try_opt_or!(s.read_array16::<RangeRecord>(count), false);
58 records.into_iter().any(|r| r.range().contains(&glyph_id))
59 }
60 _ => false,
61 }
62 }
63}
64
65
66#[repr(C)]
68#[derive(Clone, Copy, PartialEq, Debug)]
69pub struct Class(pub u16);
70
71impl FromData for Class {
72 const SIZE: usize = 2;
73
74 #[inline]
75 fn parse(data: &[u8]) -> Option<Self> {
76 u16::parse(data).map(Class)
77 }
78}
79
80
81#[derive(Clone, Copy)]
83pub(crate) struct ClassDefinitionTable<'a> {
84 data: &'a [u8],
85}
86
87impl<'a> ClassDefinitionTable<'a> {
88 pub fn new(data: &'a [u8]) -> Self {
89 ClassDefinitionTable { data }
90 }
91
92 pub fn get(&self, glyph_id: GlyphId) -> Class {
94 self.get_impl(glyph_id).unwrap_or(Class(0))
95 }
96
97 fn get_impl(&self, glyph_id: GlyphId) -> Option<Class> {
98 let mut s = Stream::new(self.data);
99 let format: u16 = s.read()?;
100 match format {
101 1 => {
102 let start_glyph_id: GlyphId = s.read()?;
103
104 if glyph_id < start_glyph_id {
106 return None;
107 }
108
109 let count: u16 = s.read()?;
110 let classes = s.read_array16::<Class>(count)?;
111 classes.get(glyph_id.0 - start_glyph_id.0)
112 }
113 2 => {
114 let count: u16 = s.read()?;
115 let records = s.read_array16::<RangeRecord>(count)?;
116 records.into_iter().find(|r| r.range().contains(&glyph_id))
117 .map(|record| Class(record.value))
118 }
119 _ => None,
120 }
121 }
122}