1use crate::ps::string::Sid;
4use crate::{FontData, FontRead, GlyphId, ReadError};
5
6#[doc(inline)]
7pub use super::v1::{
8 CharsetFormat0 as Format0, CharsetFormat1 as Format1, CharsetFormat2 as Format2,
9 CharsetRange1 as Range1, CharsetRange2 as Range2, CustomCharset,
10};
11
12#[derive(Clone)]
16pub struct Charset<'a> {
17 kind: CharsetKind<'a>,
18 num_glyphs: u32,
19}
20
21impl<'a> Charset<'a> {
22 pub fn new(
23 cff_data: FontData<'a>,
24 charset_offset: usize,
25 num_glyphs: u32,
26 ) -> Result<Self, ReadError> {
27 let kind = match charset_offset {
28 0 => CharsetKind::IsoAdobe,
29 1 => CharsetKind::Expert,
30 2 => CharsetKind::ExpertSubset,
31 _ => {
32 let data = cff_data
33 .split_off(charset_offset)
34 .ok_or(ReadError::OutOfBounds)?;
35 CharsetKind::Custom(CustomCharset::read(data)?)
36 }
37 };
38 Ok(Self { kind, num_glyphs })
39 }
40
41 pub fn kind(&self) -> &CharsetKind<'a> {
42 &self.kind
43 }
44
45 pub fn num_glyphs(&self) -> u32 {
46 self.num_glyphs
47 }
48
49 pub fn string_id(&self, glyph_id: GlyphId) -> Result<Sid, ReadError> {
51 let gid = glyph_id.to_u32();
52 if gid >= self.num_glyphs {
53 return Err(ReadError::OutOfBounds);
54 }
55 match &self.kind {
56 CharsetKind::IsoAdobe => {
57 if gid <= 228 {
61 Ok(Sid::new(gid as u16))
62 } else {
63 Err(ReadError::OutOfBounds)
64 }
65 }
66 CharsetKind::Expert => EXPERT_CHARSET
67 .get(gid as usize)
68 .copied()
69 .ok_or(ReadError::OutOfBounds)
70 .map(Sid::new),
71 CharsetKind::ExpertSubset => EXPERT_SUBSET_CHARSET
72 .get(gid as usize)
73 .copied()
74 .ok_or(ReadError::OutOfBounds)
75 .map(Sid::new),
76 CharsetKind::Custom(custom) => match custom {
77 CustomCharset::Format0(fmt) => fmt.string_id(glyph_id),
78 CustomCharset::Format1(fmt) => fmt.string_id(glyph_id),
79 CustomCharset::Format2(fmt) => fmt.string_id(glyph_id),
80 },
81 }
82 }
83
84 pub fn glyph_id(&self, string_id: Sid) -> Result<GlyphId, ReadError> {
86 let sid = string_id.to_u16();
87 match &self.kind {
88 CharsetKind::IsoAdobe => {
89 if sid <= 228 {
93 Ok(GlyphId::from(sid))
94 } else {
95 Err(ReadError::OutOfBounds)
96 }
97 }
98 CharsetKind::Expert => EXPERT_CHARSET
99 .iter()
100 .position(|n| *n == sid)
101 .map(|pos| GlyphId::new(pos as u32))
102 .ok_or(ReadError::OutOfBounds),
103 CharsetKind::ExpertSubset => EXPERT_SUBSET_CHARSET
104 .iter()
105 .position(|n| *n == sid)
106 .map(|pos| GlyphId::new(pos as u32))
107 .ok_or(ReadError::OutOfBounds),
108 CharsetKind::Custom(custom) => match custom {
109 CustomCharset::Format0(fmt) => fmt.glyph_id(string_id),
110 CustomCharset::Format1(fmt) => fmt.glyph_id(string_id),
111 CustomCharset::Format2(fmt) => fmt.glyph_id(string_id),
112 },
113 }
114 }
115
116 pub fn iter(&self) -> Iter<'a> {
119 match &self.kind {
120 CharsetKind::IsoAdobe
121 | CharsetKind::Expert
122 | CharsetKind::ExpertSubset
123 | CharsetKind::Custom(CustomCharset::Format0(_)) => {
124 Iter(IterKind::Simple(self.clone(), 0))
125 }
126 CharsetKind::Custom(CustomCharset::Format1(custom)) => Iter(IterKind::Custom1(
127 RangeIter::new(custom.ranges(), self.num_glyphs),
128 )),
129 CharsetKind::Custom(CustomCharset::Format2(custom)) => Iter(IterKind::Custom2(
130 RangeIter::new(custom.ranges(), self.num_glyphs),
131 )),
132 }
133 }
134}
135
136#[derive(Clone)]
138pub enum CharsetKind<'a> {
139 IsoAdobe,
140 Expert,
141 ExpertSubset,
142 Custom(CustomCharset<'a>),
143}
144
145impl Format0<'_> {
146 fn string_id(&self, glyph_id: GlyphId) -> Result<Sid, ReadError> {
147 let gid = glyph_id.to_u32() as usize;
148 if gid == 0 {
149 Ok(Sid::new(0))
150 } else {
151 self.glyph()
152 .get(gid - 1)
153 .map(|id| Sid::new(id.get()))
154 .ok_or(ReadError::OutOfBounds)
155 }
156 }
157
158 fn glyph_id(&self, string_id: Sid) -> Result<GlyphId, ReadError> {
159 if string_id.to_u16() == 0 {
160 return Ok(GlyphId::NOTDEF);
161 }
162 self.glyph()
163 .iter()
164 .position(|n| n.get() == string_id.to_u16())
165 .map(|n| GlyphId::from((n as u16).saturating_add(1)))
166 .ok_or(ReadError::OutOfBounds)
167 }
168}
169
170impl Format1<'_> {
171 fn string_id(&self, glyph_id: GlyphId) -> Result<Sid, ReadError> {
172 string_id_from_ranges(self.ranges(), glyph_id)
173 }
174
175 fn glyph_id(&self, string_id: Sid) -> Result<GlyphId, ReadError> {
176 glyph_id_from_ranges(self.ranges(), string_id)
177 }
178}
179
180impl Format2<'_> {
181 fn string_id(&self, glyph_id: GlyphId) -> Result<Sid, ReadError> {
182 string_id_from_ranges(self.ranges(), glyph_id)
183 }
184
185 fn glyph_id(&self, string_id: Sid) -> Result<GlyphId, ReadError> {
186 glyph_id_from_ranges(self.ranges(), string_id)
187 }
188}
189
190fn string_id_from_ranges<T: CharsetRange>(
191 ranges: &[T],
192 glyph_id: GlyphId,
193) -> Result<Sid, ReadError> {
194 let mut gid = glyph_id.to_u32();
195 if gid == 0 {
198 return Ok(Sid::new(0));
199 }
200 gid -= 1;
201 let mut end = 0u32;
202 for range in ranges {
207 let next_end = range
208 .n_left()
209 .checked_add(1)
210 .and_then(|span| end.checked_add(span))
211 .ok_or(ReadError::OutOfBounds)?;
212 if gid < next_end {
213 return (gid - end)
214 .checked_add(range.first())
215 .and_then(|sid| sid.try_into().ok())
216 .ok_or(ReadError::OutOfBounds)
217 .map(Sid::new);
218 }
219 end = next_end;
220 }
221 Err(ReadError::OutOfBounds)
222}
223
224fn glyph_id_from_ranges<T: CharsetRange>(
225 ranges: &[T],
226 string_id: Sid,
227) -> Result<GlyphId, ReadError> {
228 let sid = string_id.to_u16() as u32;
229 if sid == 0 {
231 return Ok(GlyphId::NOTDEF);
232 }
233 let mut gid = 1u32;
234 for range in ranges {
235 let first = range.first();
236 let n_left = range.n_left();
237 let last = first.checked_add(n_left).ok_or(ReadError::OutOfBounds)?;
238 if first <= sid && sid <= last {
239 gid = gid.checked_add(sid - first).ok_or(ReadError::OutOfBounds)?;
240 return Ok(GlyphId::new(gid));
241 }
242 gid = n_left
243 .checked_add(1)
244 .and_then(|span| gid.checked_add(span))
245 .ok_or(ReadError::OutOfBounds)?;
246 }
247 Err(ReadError::OutOfBounds)
248}
249
250trait CharsetRange {
253 fn first(&self) -> u32;
254 fn n_left(&self) -> u32;
255}
256
257impl CharsetRange for Range1 {
258 fn first(&self) -> u32 {
259 self.first.get() as u32
260 }
261
262 fn n_left(&self) -> u32 {
263 self.n_left as u32
264 }
265}
266
267impl CharsetRange for Range2 {
268 fn first(&self) -> u32 {
269 self.first.get() as u32
270 }
271
272 fn n_left(&self) -> u32 {
273 self.n_left.get() as u32
274 }
275}
276
277#[derive(Clone)]
279pub struct Iter<'a>(IterKind<'a>);
280
281impl Iterator for Iter<'_> {
282 type Item = (GlyphId, Sid);
283
284 fn next(&mut self) -> Option<Self::Item> {
285 match &mut self.0 {
286 IterKind::Simple(charset, cur) => {
287 let gid = GlyphId::new(*cur);
288 let sid = charset.string_id(gid).ok()?;
289 *cur = cur.checked_add(1)?;
290 Some((gid, sid))
291 }
292 IterKind::Custom1(custom) => custom.next(),
293 IterKind::Custom2(custom) => custom.next(),
294 }
295 }
296}
297
298#[derive(Clone)]
299enum IterKind<'a> {
300 Simple(Charset<'a>, u32),
303 Custom1(RangeIter<'a, Range1>),
304 Custom2(RangeIter<'a, Range2>),
305}
306
307#[derive(Clone)]
312struct RangeIter<'a, T> {
313 ranges: std::slice::Iter<'a, T>,
314 num_glyphs: u32,
315 gid: u32,
316 first: u32,
317 end: u32,
318 prev_end: u32,
319}
320
321impl<'a, T> RangeIter<'a, T>
322where
323 T: CharsetRange,
324{
325 fn new(ranges: &'a [T], num_glyphs: u32) -> Self {
326 let mut ranges = ranges.iter();
327 let (first, end) = next_range(&mut ranges).unwrap_or_default();
328 Self {
329 ranges,
330 num_glyphs,
331 gid: 0,
332 first,
333 end,
334 prev_end: 0,
335 }
336 }
337
338 fn next(&mut self) -> Option<(GlyphId, Sid)> {
339 if self.gid >= self.num_glyphs {
340 return None;
341 }
342 if self.gid == 0 {
345 self.gid += 1;
346 return Some((GlyphId::new(0), Sid::new(0)));
347 }
348 let gid = self.gid - 1;
349 self.gid = self.gid.checked_add(1)?;
350 while gid >= self.end {
351 let (first, end) = next_range(&mut self.ranges)?;
352 self.prev_end = self.end;
353 self.first = first;
354 self.end = self.prev_end.checked_add(end)?;
355 }
356 let sid = self
357 .first
358 .checked_add(gid.checked_sub(self.prev_end)?)?
359 .try_into()
360 .ok()?;
361 Some((GlyphId::new(gid + 1), Sid::new(sid)))
362 }
363}
364
365fn next_range<T: CharsetRange>(ranges: &mut std::slice::Iter<T>) -> Option<(u32, u32)> {
366 ranges.next().and_then(|range| {
367 range
368 .n_left()
369 .checked_add(1)
370 .map(|span| (range.first(), span))
371 })
372}
373
374#[rustfmt::skip]
376const EXPERT_CHARSET: &[u16] = &[
377 0, 1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13, 14, 15, 99,
378 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 252,
379 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110,
380 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282,
381 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
382 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
383 315, 316, 317, 318, 158, 155, 163, 319, 320, 321, 322, 323, 324, 325, 326, 150,
384 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340,
385 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356,
386 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372,
387 373, 374, 375, 376, 377, 378,
388];
389
390#[rustfmt::skip]
392const EXPERT_SUBSET_CHARSET: &[u16] = &[
393 0, 1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, 241, 242,
394 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 253, 254, 255, 256, 257,
395 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 272,
396 300, 301, 302, 305, 314, 315, 158, 155, 163, 320, 321, 322, 323, 324, 325, 326,
397 150, 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339,
398 340, 341, 342, 343, 344, 345, 346
399];
400
401#[cfg(test)]
402mod tests {
403 use super::*;
404 use font_test_data::bebuffer::BeBuffer;
405
406 #[derive(Clone, Copy)]
407 struct TestRange {
408 first: u32,
409 n_left: u32,
410 }
411
412 impl CharsetRange for TestRange {
413 fn first(&self) -> u32 {
414 self.first
415 }
416
417 fn n_left(&self) -> u32 {
418 self.n_left
419 }
420 }
421
422 #[test]
423 fn iso_adobe_charset() {
424 let charset_offset = 0;
426 let num_glyphs = 64;
427 let expected = |gid: GlyphId| Some(gid.to_u32());
429 test_simple_mapping(charset_offset, num_glyphs, expected);
430 }
431
432 #[test]
433 fn expert_charset() {
434 let charset_offset = 1;
436 let num_glyphs = 64;
437 let expected = |gid: GlyphId| {
439 EXPERT_CHARSET
440 .get(gid.to_u32() as usize)
441 .map(|id| *id as u32)
442 };
443 test_simple_mapping(charset_offset, num_glyphs, expected);
444 }
445
446 #[test]
447 fn expert_subset_charset() {
448 let charset_offset = 2;
450 let num_glyphs = 64;
451 let expected = |gid: GlyphId| {
453 EXPERT_SUBSET_CHARSET
454 .get(gid.to_u32() as usize)
455 .map(|id| *id as u32)
456 };
457 test_simple_mapping(charset_offset, num_glyphs, expected);
458 }
459
460 fn test_simple_mapping(
462 charset_offset: usize,
463 num_glyphs: u32,
464 expected: impl Fn(GlyphId) -> Option<u32>,
465 ) {
466 let charset = Charset::new(FontData::new(&[]), charset_offset, num_glyphs).unwrap();
467 for gid in 0..num_glyphs {
468 let gid = GlyphId::new(gid);
469 let sid = expected(gid).unwrap();
470 assert_eq!(charset.string_id(gid).unwrap().to_u16() as u32, sid);
471 assert_eq!(charset.glyph_id(Sid::new(sid as _)).unwrap(), gid);
472 }
473 for gid in num_glyphs..u16::MAX as u32 {
475 assert_eq!(charset.string_id(GlyphId::new(gid)).ok(), None);
476 }
477 }
478
479 #[test]
480 fn custom_mapping_format0() {
481 let mut buf = BeBuffer::new();
482 let num_glyphs = 6;
483 buf = buf.extend([0u8; 4]);
485 buf = buf.push(0u8);
487 buf = buf.extend([2u16, 4, 6, 8, 10]);
489 let charset = Charset::new(FontData::new(buf.data()), 4, num_glyphs).unwrap();
490 for gid in 0..num_glyphs {
492 assert_eq!(
493 charset.string_id(GlyphId::new(gid)).unwrap().to_u16() as u32,
494 gid * 2
495 )
496 }
497 for (gid, sid) in charset.iter() {
499 assert_eq!(sid.to_u16() as u32, gid.to_u32() * 2);
500 }
501 assert_eq!(charset.iter().count() as u32, num_glyphs);
502 for gid in num_glyphs..u16::MAX as u32 {
504 assert_eq!(charset.string_id(GlyphId::new(gid)).ok(), None);
505 }
506 }
507
508 #[test]
509 fn custom_mapping_format1() {
510 let mut buf = BeBuffer::new();
511 let num_glyphs = 7;
512 buf = buf.extend([0u8; 4]);
514 buf = buf.push(1u8);
516 buf = buf.push(8u16).push(2u8);
518 buf = buf.push(1200u16).push(0u8);
519 buf = buf.push(20u16).push(1u8);
520 let expected_sids = [0, 8, 9, 10, 1200, 20, 21];
521 test_range_mapping(buf.data(), num_glyphs, &expected_sids);
522 }
523
524 #[test]
525 fn custom_mapping_format2() {
526 let mut buf = BeBuffer::new();
527 buf = buf.extend([0u8; 4]);
529 buf = buf.push(2u8);
531 buf = buf.push(8u16).push(2u16);
533 buf = buf.push(1200u16).push(0u16);
534 buf = buf.push(20u16).push(800u16);
535 let mut expected_sids = vec![0, 8, 9, 10, 1200];
536 for i in 0..=800 {
537 expected_sids.push(i + 20);
538 }
539 let num_glyphs = expected_sids.len() as u32;
540 test_range_mapping(buf.data(), num_glyphs, &expected_sids);
541 }
542
543 fn test_range_mapping(data: &[u8], num_glyphs: u32, expected_sids: &[u32]) {
545 let charset = Charset::new(FontData::new(data), 4, num_glyphs).unwrap();
546 for (gid, sid) in expected_sids.iter().enumerate() {
548 assert_eq!(
549 charset.string_id(GlyphId::new(gid as _)).unwrap().to_u16() as u32,
550 *sid
551 )
552 }
553 assert!(charset.iter().eq(expected_sids
555 .iter()
556 .enumerate()
557 .map(|(gid, sid)| (GlyphId::new(gid as u32), Sid::new(*sid as u16)))));
558 assert_eq!(charset.iter().count() as u32, num_glyphs);
559 for gid in num_glyphs..u16::MAX as u32 {
561 assert_eq!(charset.string_id(GlyphId::new(gid)).ok(), None);
562 }
563 for (gid, sid) in expected_sids.iter().enumerate() {
565 assert_eq!(
566 charset.glyph_id(Sid::new(*sid as u16)),
567 Ok(GlyphId::new(gid as u32))
568 );
569 }
570 }
571
572 #[test]
573 fn string_id_from_ranges_overflow_does_not_panic() {
574 let ranges = [TestRange {
576 first: 42,
577 n_left: u32::MAX,
578 }];
579 assert_eq!(
580 string_id_from_ranges(&ranges, GlyphId::new(1)),
581 Err(ReadError::OutOfBounds)
582 );
583 }
584
585 #[test]
586 fn glyph_id_from_ranges_overflow_does_not_panic() {
587 let ranges = [
589 TestRange {
590 first: 2,
591 n_left: 0,
592 },
593 TestRange {
594 first: 2,
595 n_left: u32::MAX - 2,
596 },
597 ];
598 assert_eq!(
599 glyph_id_from_ranges(&ranges, Sid::new(1)),
600 Err(ReadError::OutOfBounds)
601 );
602 }
603
604 #[test]
605 fn next_range_overflow_does_not_panic() {
606 let ranges = [TestRange {
608 first: 7,
609 n_left: u32::MAX,
610 }];
611 let mut iter = ranges.iter();
612 assert_eq!(next_range(&mut iter), None);
613 }
614}