ttf_parser/tables/cff/
charset.rs

1use crate::GlyphId;
2use crate::parser::{Stream, FromData, LazyArray16};
3use super::StringId;
4
5/// The Standard Encoding as defined in the Adobe Technical Note #5176 Appendix B.
6pub const STANDARD_ENCODING: [u8;256] = [
7      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
8      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
9      1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,  16,
10     17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,
11     33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
12     49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
13     65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,
14     81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,   0,
15      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
16      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
17      0,  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
18      0, 111, 112, 113, 114,   0, 115, 116, 117, 118, 119, 120, 121, 122,   0, 123,
19      0, 124, 125, 126, 127, 128, 129, 130, 131,   0, 132, 133,   0, 134, 135, 136,
20    137,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
21      0, 138,   0, 139,   0,   0,   0,   0, 140, 141, 142, 143,   0,   0,   0,   0,
22      0, 144,   0,   0,   0, 145,   0,   0, 146, 147, 148, 149,   0,   0,   0,   0,
23];
24
25/// The Expert Encoding conversion as defined in the Adobe Technical Note #5176 Appendix C.
26const EXPERT_ENCODING: &[u16] = &[
27      0,    1,  229,  230,  231,  232,  233,  234,  235,  236,  237,  238,   13,   14,   15,   99,
28    239,  240,  241,  242,  243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  252,
29    253,  254,  255,  256,  257,  258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,
30    267,  268,  269,  270,  271,  272,  273,  274,  275,  276,  277,  278,  279,  280,  281,  282,
31    283,  284,  285,  286,  287,  288,  289,  290,  291,  292,  293,  294,  295,  296,  297,  298,
32    299,  300,  301,  302,  303,  304,  305,  306,  307,  308,  309,  310,  311,  312,  313,  314,
33    315,  316,  317,  318,  158,  155,  163,  319,  320,  321,  322,  323,  324,  325,  326,  150,
34    164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,  340,
35    341,  342,  343,  344,  345,  346,  347,  348,  349,  350,  351,  352,  353,  354,  355,  356,
36    357,  358,  359,  360,  361,  362,  363,  364,  365,  366,  367,  368,  369,  370,  371,  372,
37    373,  374,  375,  376,  377,  378,
38];
39
40/// The Expert Subset Encoding conversion as defined in the Adobe Technical Note #5176 Appendix C.
41const EXPERT_SUBSET_ENCODING: &[u16] = &[
42      0,    1,  231,  232,  235,  236,  237,  238,   13,   14,   15,   99,  239,  240,  241,  242,
43    243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  253,  254,  255,  256,  257,
44    258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,  267,  268,  269,  270,  272,
45    300,  301,  302,  305,  314,  315,  158,  155,  163,  320,  321,  322,  323,  324,  325,  326,
46    150,  164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,
47    340,  341,  342,  343,  344,  345,  346
48];
49
50
51#[derive(Clone, Copy, Debug)]
52pub(crate) struct Format1Range {
53    first: StringId,
54    left: u8,
55}
56
57impl FromData for Format1Range {
58    const SIZE: usize = 3;
59
60    #[inline]
61    fn parse(data: &[u8]) -> Option<Self> {
62        let mut s = Stream::new(data);
63        Some(Format1Range {
64            first: s.read::<StringId>()?,
65            left: s.read::<u8>()?,
66        })
67    }
68}
69
70
71#[derive(Clone, Copy, Debug)]
72pub(crate) struct Format2Range {
73    first: StringId,
74    left: u16,
75}
76
77impl FromData for Format2Range {
78    const SIZE: usize = 4;
79
80    #[inline]
81    fn parse(data: &[u8]) -> Option<Self> {
82        let mut s = Stream::new(data);
83        Some(Format2Range {
84            first: s.read::<StringId>()?,
85            left: s.read::<u16>()?,
86        })
87    }
88}
89
90
91#[derive(Clone, Copy, Debug)]
92pub(crate) enum Charset<'a> {
93    ISOAdobe,
94    Expert,
95    ExpertSubset,
96    Format0(LazyArray16<'a, StringId>),
97    Format1(LazyArray16<'a, Format1Range>),
98    Format2(LazyArray16<'a, Format2Range>),
99}
100
101impl Charset<'_> {
102    pub fn sid_to_gid(&self, sid: StringId) -> Option<GlyphId> {
103        if sid.0 == 0 {
104            return Some(GlyphId(0));
105        }
106
107        match self {
108            Charset::ISOAdobe | Charset::Expert | Charset::ExpertSubset => None,
109            Charset::Format0(ref array) => {
110                // First glyph is omitted, so we have to add 1.
111                array.into_iter().position(|n| n == sid).map(|n| GlyphId(n as u16 + 1))
112            }
113            Charset::Format1(array) => {
114                let mut glyph_id = GlyphId(1);
115                for range in *array {
116                    let last = u32::from(range.first.0) + u32::from(range.left);
117                    if range.first <= sid && u32::from(sid.0) <= last {
118                        glyph_id.0 += sid.0 - range.first.0;
119                        return Some(glyph_id)
120                    }
121
122                    glyph_id.0 += u16::from(range.left) + 1;
123                }
124
125                None
126            }
127            Charset::Format2(array) => {
128                // The same as format 1, but Range::left is u16.
129                let mut glyph_id = GlyphId(1);
130                for range in *array {
131                    let last = u32::from(range.first.0) + u32::from(range.left);
132                    if sid >= range.first && u32::from(sid.0) <= last {
133                        glyph_id.0 += sid.0 - range.first.0;
134                        return Some(glyph_id)
135                    }
136
137                    glyph_id.0 += range.left + 1;
138                }
139
140                None
141            }
142        }
143    }
144
145    pub fn gid_to_sid(&self, gid: GlyphId) -> Option<StringId> {
146        match self {
147            Charset::ISOAdobe => {
148                if gid.0 <= 228 { Some(StringId(gid.0)) } else { None }
149            }
150            Charset::Expert => {
151                EXPERT_ENCODING.get(usize::from(gid.0)).cloned().map(StringId)
152            }
153            Charset::ExpertSubset => {
154                EXPERT_SUBSET_ENCODING.get(usize::from(gid.0)).cloned().map(StringId)
155            }
156            Charset::Format0(ref array) => {
157                if gid.0 == 0 {
158                    Some(StringId(0))
159                } else {
160                    array.get(gid.0 - 1)
161                }
162            }
163            Charset::Format1(array) => {
164                if gid.0 == 0 {
165                    Some(StringId(0))
166                } else {
167                    let mut sid = gid.0 - 1;
168                    for range in *array {
169                        if sid <= u16::from(range.left) {
170                            sid = sid.checked_add(range.first.0)?;
171                            return Some(StringId(sid));
172                        }
173
174                        sid = sid.checked_sub(u16::from(range.left) + 1)?;
175                    }
176
177                    None
178                }
179            }
180            Charset::Format2(array) => {
181                if gid.0 == 0 {
182                    Some(StringId(0))
183                } else {
184                    let mut sid = gid.0 - 1;
185                    for range in *array {
186                        if sid <= range.left {
187                            sid = sid.checked_add(range.first.0)?;
188                            return Some(StringId(sid));
189                        }
190
191                        sid = sid.checked_sub(range.left.checked_add(1)?)?;
192                    }
193
194                    None
195                }
196            }
197        }
198    }
199}
200
201pub(crate) fn parse_charset<'a>(number_of_glyphs: u16, s: &mut Stream<'a>) -> Option<Charset<'a>> {
202    if number_of_glyphs < 2 {
203        return None;
204    }
205
206    // -1 everywhere, since `.notdef` is omitted.
207    let format: u8 = s.read()?;
208    match format {
209        0 => Some(Charset::Format0(s.read_array16::<StringId>(number_of_glyphs - 1)?)),
210        1 => {
211            // The number of ranges is not defined, so we have to
212            // read until no glyphs are left.
213            let mut count = 0;
214            {
215                let mut s = s.clone();
216                let mut total_left = number_of_glyphs - 1;
217                while total_left > 0 {
218                    s.skip::<StringId>(); // first
219                    let left: u8 = s.read()?;
220                    total_left = total_left.checked_sub(u16::from(left) + 1)?;
221                    count += 1;
222                }
223            }
224
225            s.read_array16::<Format1Range>(count).map(Charset::Format1)
226        }
227        2 => {
228            // The same as format 1, but Range::left is u16.
229            let mut count = 0;
230            {
231                let mut s = s.clone();
232                let mut total_left = number_of_glyphs - 1;
233                while total_left > 0 {
234                    s.skip::<StringId>(); // first
235                    let left: u16 = s.read()?;
236                    let left = left.checked_add(1)?;
237                    total_left = total_left.checked_sub(left)?;
238                    count += 1;
239                }
240            }
241
242            s.read_array16::<Format2Range>(count).map(Charset::Format2)
243        }
244        _ => None,
245    }
246}