Skip to main content

cff_parser/
charset.rs

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