1use core::convert::TryFrom;
10use core::num::NonZeroU16;
11use core::ops::Range;
12
13use super::argstack::ArgumentsStack;
14use super::charset::{parse_charset, Charset};
15use super::charstring::CharStringParser;
16use super::dict::DictionaryParser;
17use super::encoding::{parse_encoding, Encoding, STANDARD_ENCODING};
18use super::index::{parse_index, skip_index, Index};
19#[cfg(feature = "glyph-names")]
20use super::std_names::STANDARD_NAMES;
21use super::{calc_subroutine_bias, conv_subroutine_index, Builder, CFFError, IsEven, StringId};
22use crate::parser::{LazyArray16, NumFrom, Stream, TryNumFrom};
23use crate::{DummyOutline, GlyphId, OutlineBuilder, Rect, RectF};
24
25const MAX_OPERANDS_LEN: usize = 48;
27
28const STACK_LIMIT: u8 = 10;
30const MAX_ARGUMENTS_STACK_LEN: usize = 48;
31
32const TWO_BYTE_OPERATOR_MARK: u8 = 12;
33
34mod operator {
36 pub const HORIZONTAL_STEM: u8 = 1;
37 pub const VERTICAL_STEM: u8 = 3;
38 pub const VERTICAL_MOVE_TO: u8 = 4;
39 pub const LINE_TO: u8 = 5;
40 pub const HORIZONTAL_LINE_TO: u8 = 6;
41 pub const VERTICAL_LINE_TO: u8 = 7;
42 pub const CURVE_TO: u8 = 8;
43 pub const CALL_LOCAL_SUBROUTINE: u8 = 10;
44 pub const RETURN: u8 = 11;
45 pub const ENDCHAR: u8 = 14;
46 pub const HORIZONTAL_STEM_HINT_MASK: u8 = 18;
47 pub const HINT_MASK: u8 = 19;
48 pub const COUNTER_MASK: u8 = 20;
49 pub const MOVE_TO: u8 = 21;
50 pub const HORIZONTAL_MOVE_TO: u8 = 22;
51 pub const VERTICAL_STEM_HINT_MASK: u8 = 23;
52 pub const CURVE_LINE: u8 = 24;
53 pub const LINE_CURVE: u8 = 25;
54 pub const VV_CURVE_TO: u8 = 26;
55 pub const HH_CURVE_TO: u8 = 27;
56 pub const SHORT_INT: u8 = 28;
57 pub const CALL_GLOBAL_SUBROUTINE: u8 = 29;
58 pub const VH_CURVE_TO: u8 = 30;
59 pub const HV_CURVE_TO: u8 = 31;
60 pub const HFLEX: u8 = 34;
61 pub const FLEX: u8 = 35;
62 pub const HFLEX1: u8 = 36;
63 pub const FLEX1: u8 = 37;
64 pub const FIXED_16_16: u8 = 255;
65}
66
67mod top_dict_operator {
70 pub const CHARSET_OFFSET: u16 = 15;
71 pub const ENCODING_OFFSET: u16 = 16;
72 pub const CHAR_STRINGS_OFFSET: u16 = 17;
73 pub const PRIVATE_DICT_SIZE_AND_OFFSET: u16 = 18;
74 pub const FONT_MATRIX: u16 = 1207;
75 pub const ROS: u16 = 1230;
76 pub const FD_ARRAY: u16 = 1236;
77 pub const FD_SELECT: u16 = 1237;
78}
79
80mod private_dict_operator {
83 pub const LOCAL_SUBROUTINES_OFFSET: u16 = 19;
84 pub const DEFAULT_WIDTH: u16 = 20;
85 pub const NOMINAL_WIDTH: u16 = 21;
86}
87
88mod charset_id {
90 pub const ISO_ADOBE: usize = 0;
91 pub const EXPERT: usize = 1;
92 pub const EXPERT_SUBSET: usize = 2;
93}
94
95mod encoding_id {
97 pub const STANDARD: usize = 0;
98 pub const EXPERT: usize = 1;
99}
100
101#[derive(Clone, Copy, Debug)]
102pub(crate) enum FontKind<'a> {
103 SID(SIDMetadata<'a>),
104 CID(CIDMetadata<'a>),
105}
106
107#[derive(Clone, Copy, Default, Debug)]
108pub(crate) struct SIDMetadata<'a> {
109 local_subrs: Index<'a>,
110 default_width: f32,
112 nominal_width: f32,
114 encoding: Encoding<'a>,
115}
116
117#[derive(Clone, Copy, Default, Debug)]
118pub(crate) struct CIDMetadata<'a> {
119 fd_array: Index<'a>,
120 fd_select: FDSelect<'a>,
121}
122
123#[allow(missing_docs)]
125#[derive(Clone, Copy, Debug)]
126pub struct Matrix {
127 pub sx: f32,
128 pub ky: f32,
129 pub kx: f32,
130 pub sy: f32,
131 pub tx: f32,
132 pub ty: f32,
133}
134
135impl Default for Matrix {
136 fn default() -> Self {
137 Self {
138 sx: 0.001,
139 ky: 0.0,
140 kx: 0.0,
141 sy: 0.001,
142 tx: 0.0,
143 ty: 0.0,
144 }
145 }
146}
147
148#[derive(Default)]
149struct TopDict {
150 charset_offset: Option<usize>,
151 encoding_offset: Option<usize>,
152 char_strings_offset: usize,
153 private_dict_range: Option<Range<usize>>,
154 matrix: Matrix,
155 has_ros: bool,
156 fd_array_offset: Option<usize>,
157 fd_select_offset: Option<usize>,
158}
159
160fn parse_top_dict(s: &mut Stream) -> Option<TopDict> {
161 let mut top_dict = TopDict::default();
162
163 let index = parse_index::<u16>(s)?;
164
165 let data = index.get(0)?;
167
168 let mut operands_buffer = [0.0; MAX_OPERANDS_LEN];
169 let mut dict_parser = DictionaryParser::new(data, &mut operands_buffer);
170 while let Some(operator) = dict_parser.parse_next() {
171 match operator.get() {
172 top_dict_operator::CHARSET_OFFSET => {
173 top_dict.charset_offset = dict_parser.parse_offset();
174 }
175 top_dict_operator::ENCODING_OFFSET => {
176 top_dict.encoding_offset = dict_parser.parse_offset();
177 }
178 top_dict_operator::CHAR_STRINGS_OFFSET => {
179 top_dict.char_strings_offset = dict_parser.parse_offset()?;
180 }
181 top_dict_operator::PRIVATE_DICT_SIZE_AND_OFFSET => {
182 top_dict.private_dict_range = dict_parser.parse_range();
183 }
184 top_dict_operator::FONT_MATRIX => {
185 dict_parser.parse_operands()?;
186 let operands = dict_parser.operands();
187 if operands.len() == 6 {
188 top_dict.matrix = Matrix {
189 sx: operands[0] as f32,
190 ky: operands[1] as f32,
191 kx: operands[2] as f32,
192 sy: operands[3] as f32,
193 tx: operands[4] as f32,
194 ty: operands[5] as f32,
195 };
196 }
197 }
198 top_dict_operator::ROS => {
199 top_dict.has_ros = true;
200 }
201 top_dict_operator::FD_ARRAY => {
202 top_dict.fd_array_offset = dict_parser.parse_offset();
203 }
204 top_dict_operator::FD_SELECT => {
205 top_dict.fd_select_offset = dict_parser.parse_offset();
206 }
207 _ => {}
208 }
209 }
210
211 Some(top_dict)
212}
213
214#[cfg(test)]
216mod tests {
217 use super::*;
218
219 #[test]
220 fn private_dict_size_overflow() {
221 let data = &[
222 0x00, 0x01, 0x01, 0x01, 0x0C, 0x1D, 0x7F, 0xFF, 0xFF, 0xFF, 0x1D, 0x7F, 0xFF, 0xFF, 0xFF, 0x12, ];
230
231 let top_dict = parse_top_dict(&mut Stream::new(data)).unwrap();
232 assert_eq!(top_dict.private_dict_range, Some(2147483647..4294967294));
233 }
234
235 #[test]
236 fn private_dict_negative_char_strings_offset() {
237 let data = &[
238 0x00, 0x01, 0x01, 0x01, 0x03, 0x8A, 0x11, ];
246
247 assert!(parse_top_dict(&mut Stream::new(data)).is_none());
248 }
249
250 #[test]
251 fn private_dict_no_char_strings_offset_operand() {
252 let data = &[
253 0x00, 0x01, 0x01, 0x01, 0x02, 0x11, ];
261
262 assert!(parse_top_dict(&mut Stream::new(data)).is_none());
263 }
264
265 #[test]
266 fn negative_private_dict_offset_and_size() {
267 let data = &[
268 0x00, 0x01, 0x01, 0x01, 0x04, 0x8A, 0x8A, 0x12, ];
277
278 let top_dict = parse_top_dict(&mut Stream::new(data)).unwrap();
279 assert!(top_dict.private_dict_range.is_none());
280 }
281}
282
283#[derive(Default, Debug)]
284struct PrivateDict {
285 local_subroutines_offset: Option<usize>,
286 default_width: Option<f32>,
287 nominal_width: Option<f32>,
288}
289
290fn parse_private_dict(data: &[u8]) -> PrivateDict {
291 let mut dict = PrivateDict::default();
292 let mut operands_buffer = [0.0; MAX_OPERANDS_LEN];
293 let mut dict_parser = DictionaryParser::new(data, &mut operands_buffer);
294 while let Some(operator) = dict_parser.parse_next() {
295 if operator.get() == private_dict_operator::LOCAL_SUBROUTINES_OFFSET {
296 dict.local_subroutines_offset = dict_parser.parse_offset();
297 } else if operator.get() == private_dict_operator::DEFAULT_WIDTH {
298 dict.default_width = dict_parser.parse_number().map(|n| n as f32);
299 } else if operator.get() == private_dict_operator::NOMINAL_WIDTH {
300 dict.nominal_width = dict_parser.parse_number().map(|n| n as f32);
301 }
302 }
303
304 dict
305}
306
307fn parse_font_dict(data: &[u8]) -> Option<Range<usize>> {
308 let mut operands_buffer = [0.0; MAX_OPERANDS_LEN];
309 let mut dict_parser = DictionaryParser::new(data, &mut operands_buffer);
310 while let Some(operator) = dict_parser.parse_next() {
311 if operator.get() == top_dict_operator::PRIVATE_DICT_SIZE_AND_OFFSET {
312 return dict_parser.parse_range();
313 }
314 }
315
316 None
317}
318
319fn parse_cid_local_subrs<'a>(
326 data: &'a [u8],
327 glyph_id: GlyphId,
328 cid: &CIDMetadata,
329) -> Option<Index<'a>> {
330 let font_dict_index = cid.fd_select.font_dict_index(glyph_id)?;
331 let font_dict_data = cid.fd_array.get(u32::from(font_dict_index))?;
332 let private_dict_range = parse_font_dict(font_dict_data)?;
333 let private_dict_data = data.get(private_dict_range.clone())?;
334 let private_dict = parse_private_dict(private_dict_data);
335 let subroutines_offset = private_dict.local_subroutines_offset?;
336
337 let start = private_dict_range.start.checked_add(subroutines_offset)?;
340 let subrs_data = data.get(start..)?;
341 let mut s = Stream::new(subrs_data);
342 parse_index::<u16>(&mut s)
343}
344
345struct CharStringParserContext<'a> {
346 metadata: &'a Table<'a>,
347 width: Option<f32>,
348 stems_len: u32,
349 has_endchar: bool,
350 has_seac: bool,
351 glyph_id: GlyphId, local_subrs: Option<Index<'a>>,
353}
354
355fn parse_char_string(
356 data: &[u8],
357 metadata: &Table,
358 glyph_id: GlyphId,
359 width_only: bool,
360 builder: &mut dyn OutlineBuilder,
361) -> Result<(Rect, Option<f32>), CFFError> {
362 let local_subrs = match metadata.kind {
363 FontKind::SID(ref sid) => Some(sid.local_subrs),
364 FontKind::CID(_) => None, };
366
367 let mut ctx = CharStringParserContext {
368 metadata,
369 width: None,
370 stems_len: 0,
371 has_endchar: false,
372 has_seac: false,
373 glyph_id,
374 local_subrs,
375 };
376
377 let mut inner_builder = Builder {
378 builder,
379 bbox: RectF::new(),
380 };
381
382 let stack = ArgumentsStack {
383 data: &mut [0.0; MAX_ARGUMENTS_STACK_LEN], len: 0,
385 max_len: MAX_ARGUMENTS_STACK_LEN,
386 };
387 let mut parser = CharStringParser {
388 stack,
389 builder: &mut inner_builder,
390 x: 0.0,
391 y: 0.0,
392 has_move_to: false,
393 is_first_move_to: true,
394 width_only,
395 };
396 _parse_char_string(&mut ctx, data, 0, &mut parser)?;
397
398 if width_only {
399 return Ok((Rect::zero(), ctx.width));
400 }
401
402 if !ctx.has_endchar {
403 return Err(CFFError::MissingEndChar);
404 }
405
406 let bbox = parser.builder.bbox;
407
408 if bbox.is_default() {
410 return Err(CFFError::ZeroBBox);
411 }
412
413 let rect = bbox.to_rect().ok_or(CFFError::BboxOverflow)?;
414 Ok((rect, ctx.width))
415}
416
417fn _parse_char_string(
418 ctx: &mut CharStringParserContext,
419 char_string: &[u8],
420 depth: u8,
421 p: &mut CharStringParser,
422) -> Result<(), CFFError> {
423 let mut s = Stream::new(char_string);
424 while !s.at_end() {
425 let op = s.read::<u8>().ok_or(CFFError::ReadOutOfBounds)?;
426 match op {
427 0 | 2 | 9 | 13 | 15 | 16 | 17 => {
428 return Err(CFFError::InvalidOperator);
430 }
431 operator::HORIZONTAL_STEM
432 | operator::VERTICAL_STEM
433 | operator::HORIZONTAL_STEM_HINT_MASK
434 | operator::VERTICAL_STEM_HINT_MASK => {
435 let len = if p.stack.len().is_odd() && ctx.width.is_none() {
442 ctx.width = Some(p.stack.at(0));
443 p.stack.len() - 1
444 } else {
445 p.stack.len()
446 };
447
448 ctx.stems_len += len as u32 >> 1;
449
450 p.stack.clear();
452 }
453 operator::VERTICAL_MOVE_TO => {
454 let mut i = 0;
455 if p.stack.len() == 2 {
456 i += 1;
457 if ctx.width.is_none() {
458 ctx.width = Some(p.stack.at(0));
459 }
460 }
461
462 p.parse_vertical_move_to(i)?;
463 }
464 operator::LINE_TO => {
465 p.parse_line_to()?;
466 }
467 operator::HORIZONTAL_LINE_TO => {
468 p.parse_horizontal_line_to()?;
469 }
470 operator::VERTICAL_LINE_TO => {
471 p.parse_vertical_line_to()?;
472 }
473 operator::CURVE_TO => {
474 p.parse_curve_to()?;
475 }
476 operator::CALL_LOCAL_SUBROUTINE => {
477 if p.stack.is_empty() {
478 return Err(CFFError::InvalidArgumentsStackLength);
479 }
480
481 if depth == STACK_LIMIT {
482 return Err(CFFError::NestingLimitReached);
483 }
484
485 if ctx.local_subrs.is_none() {
489 if let FontKind::CID(ref cid) = ctx.metadata.kind {
490 ctx.local_subrs =
491 parse_cid_local_subrs(ctx.metadata.table_data, ctx.glyph_id, cid);
492 }
493 }
494
495 if let Some(local_subrs) = ctx.local_subrs {
496 let subroutine_bias = calc_subroutine_bias(local_subrs.len());
497 let index = conv_subroutine_index(p.stack.pop(), subroutine_bias)?;
498 let char_string = local_subrs
499 .get(index)
500 .ok_or(CFFError::InvalidSubroutineIndex)?;
501 _parse_char_string(ctx, char_string, depth + 1, p)?;
502 } else {
503 return Err(CFFError::NoLocalSubroutines);
504 }
505
506 if ctx.has_endchar && !ctx.has_seac {
507 if !s.at_end() {
508 return Err(CFFError::DataAfterEndChar);
509 }
510
511 break;
512 }
513 }
514 operator::RETURN => {
515 break;
516 }
517 TWO_BYTE_OPERATOR_MARK => {
518 let op2 = s.read::<u8>().ok_or(CFFError::ReadOutOfBounds)?;
520 match op2 {
521 operator::HFLEX => p.parse_hflex()?,
522 operator::FLEX => p.parse_flex()?,
523 operator::HFLEX1 => p.parse_hflex1()?,
524 operator::FLEX1 => p.parse_flex1()?,
525 _ => return Err(CFFError::UnsupportedOperator),
526 }
527 }
528 operator::ENDCHAR => {
529 if p.stack.len() == 4 || (ctx.width.is_none() && p.stack.len() == 5) {
530 let accent_char = seac_code_to_glyph_id(&ctx.metadata.charset, p.stack.pop())
532 .ok_or(CFFError::InvalidSeacCode)?;
533 let base_char = seac_code_to_glyph_id(&ctx.metadata.charset, p.stack.pop())
534 .ok_or(CFFError::InvalidSeacCode)?;
535 let dy = p.stack.pop();
536 let dx = p.stack.pop();
537
538 if ctx.width.is_none() && !p.stack.is_empty() {
539 ctx.width = Some(p.stack.pop())
540 }
541
542 ctx.has_seac = true;
543
544 if depth == STACK_LIMIT {
545 return Err(CFFError::NestingLimitReached);
546 }
547
548 let base_char_string = ctx
549 .metadata
550 .char_strings
551 .get(u32::from(base_char.0))
552 .ok_or(CFFError::InvalidSeacCode)?;
553 _parse_char_string(ctx, base_char_string, depth + 1, p)?;
554 p.x = dx;
555 p.y = dy;
556
557 let accent_char_string = ctx
558 .metadata
559 .char_strings
560 .get(u32::from(accent_char.0))
561 .ok_or(CFFError::InvalidSeacCode)?;
562 _parse_char_string(ctx, accent_char_string, depth + 1, p)?;
563 } else if p.stack.len() == 1 && ctx.width.is_none() {
564 ctx.width = Some(p.stack.pop());
565 }
566
567 if !p.is_first_move_to {
568 p.is_first_move_to = true;
569 p.builder.close();
570 }
571
572 if !s.at_end() {
573 return Err(CFFError::DataAfterEndChar);
574 }
575
576 ctx.has_endchar = true;
577
578 break;
579 }
580 operator::HINT_MASK | operator::COUNTER_MASK => {
581 let mut len = p.stack.len();
582
583 p.stack.clear();
585
586 if len.is_odd() {
588 len -= 1;
589 if ctx.width.is_none() {
590 ctx.width = Some(p.stack.at(0));
591 }
592 }
593
594 ctx.stems_len += len as u32 >> 1;
595
596 s.advance(usize::num_from((ctx.stems_len + 7) >> 3));
597 }
598 operator::MOVE_TO => {
599 let mut i = 0;
600 if p.stack.len() == 3 {
601 i += 1;
602 if ctx.width.is_none() {
603 ctx.width = Some(p.stack.at(0));
604 }
605 }
606
607 p.parse_move_to(i)?;
608 }
609 operator::HORIZONTAL_MOVE_TO => {
610 let mut i = 0;
611 if p.stack.len() == 2 {
612 i += 1;
613 if ctx.width.is_none() {
614 ctx.width = Some(p.stack.at(0));
615 }
616 }
617
618 p.parse_horizontal_move_to(i)?;
619 }
620 operator::CURVE_LINE => {
621 p.parse_curve_line()?;
622 }
623 operator::LINE_CURVE => {
624 p.parse_line_curve()?;
625 }
626 operator::VV_CURVE_TO => {
627 p.parse_vv_curve_to()?;
628 }
629 operator::HH_CURVE_TO => {
630 p.parse_hh_curve_to()?;
631 }
632 operator::SHORT_INT => {
633 let n = s.read::<i16>().ok_or(CFFError::ReadOutOfBounds)?;
634 p.stack.push(f32::from(n))?;
635 }
636 operator::CALL_GLOBAL_SUBROUTINE => {
637 if p.stack.is_empty() {
638 return Err(CFFError::InvalidArgumentsStackLength);
639 }
640
641 if depth == STACK_LIMIT {
642 return Err(CFFError::NestingLimitReached);
643 }
644
645 let subroutine_bias = calc_subroutine_bias(ctx.metadata.global_subrs.len());
646 let index = conv_subroutine_index(p.stack.pop(), subroutine_bias)?;
647 let char_string = ctx
648 .metadata
649 .global_subrs
650 .get(index)
651 .ok_or(CFFError::InvalidSubroutineIndex)?;
652 _parse_char_string(ctx, char_string, depth + 1, p)?;
653
654 if ctx.has_endchar && !ctx.has_seac {
655 if !s.at_end() {
656 return Err(CFFError::DataAfterEndChar);
657 }
658
659 break;
660 }
661 }
662 operator::VH_CURVE_TO => {
663 p.parse_vh_curve_to()?;
664 }
665 operator::HV_CURVE_TO => {
666 p.parse_hv_curve_to()?;
667 }
668 32..=246 => {
669 p.parse_int1(op)?;
670 }
671 247..=250 => {
672 p.parse_int2(op, &mut s)?;
673 }
674 251..=254 => {
675 p.parse_int3(op, &mut s)?;
676 }
677 operator::FIXED_16_16 => {
678 p.parse_fixed(&mut s)?;
679 }
680 }
681
682 if p.width_only && ctx.width.is_some() {
683 break;
684 }
685 }
686
687 Ok(())
690}
691
692fn seac_code_to_glyph_id(charset: &Charset, n: f32) -> Option<GlyphId> {
693 let code = u8::try_num_from(n)?;
694
695 let sid = STANDARD_ENCODING[usize::from(code)];
696 let sid = StringId(u16::from(sid));
697
698 match charset {
699 Charset::ISOAdobe => {
700 if code <= 228 {
702 Some(GlyphId(sid.0))
703 } else {
704 None
705 }
706 }
707 Charset::Expert | Charset::ExpertSubset => None,
708 _ => charset.sid_to_gid(sid),
709 }
710}
711
712#[derive(Clone, Copy, Debug)]
713enum FDSelect<'a> {
714 Format0(LazyArray16<'a, u8>),
715 Format3(&'a [u8]), }
717
718impl Default for FDSelect<'_> {
719 fn default() -> Self {
720 FDSelect::Format0(LazyArray16::default())
721 }
722}
723
724impl FDSelect<'_> {
725 fn font_dict_index(&self, glyph_id: GlyphId) -> Option<u8> {
726 match self {
727 FDSelect::Format0(ref array) => array.get(glyph_id.0),
728 FDSelect::Format3(data) => {
729 let mut s = Stream::new(data);
730 let number_of_ranges = s.read::<u16>()?;
731 if number_of_ranges == 0 {
732 return None;
733 }
734
735 let number_of_ranges = number_of_ranges.checked_add(1)?;
739
740 let mut prev_first_glyph = s.read::<GlyphId>()?;
742 let mut prev_index = s.read::<u8>()?;
743 for _ in 1..number_of_ranges {
744 let curr_first_glyph = s.read::<GlyphId>()?;
745 if (prev_first_glyph..curr_first_glyph).contains(&glyph_id) {
746 return Some(prev_index);
747 } else {
748 prev_index = s.read::<u8>()?;
749 }
750
751 prev_first_glyph = curr_first_glyph;
752 }
753
754 None
755 }
756 }
757 }
758}
759
760fn parse_fd_select<'a>(number_of_glyphs: u16, s: &mut Stream<'a>) -> Option<FDSelect<'a>> {
761 let format = s.read::<u8>()?;
762 match format {
763 0 => Some(FDSelect::Format0(s.read_array16::<u8>(number_of_glyphs)?)),
764 3 => Some(FDSelect::Format3(s.tail()?)),
765 _ => None,
766 }
767}
768
769fn parse_sid_metadata<'a>(
770 data: &'a [u8],
771 top_dict: TopDict,
772 encoding: Encoding<'a>,
773) -> Option<FontKind<'a>> {
774 let mut metadata = SIDMetadata::default();
775 metadata.encoding = encoding;
776
777 let private_dict = if let Some(range) = top_dict.private_dict_range.clone() {
778 parse_private_dict(data.get(range)?)
779 } else {
780 return Some(FontKind::SID(metadata));
781 };
782
783 metadata.default_width = private_dict.default_width.unwrap_or(0.0);
784 metadata.nominal_width = private_dict.nominal_width.unwrap_or(0.0);
785
786 if let (Some(private_dict_range), Some(subroutines_offset)) = (
787 top_dict.private_dict_range,
788 private_dict.local_subroutines_offset,
789 ) {
790 if let Some(start) = private_dict_range.start.checked_add(subroutines_offset) {
793 let data = data.get(start..data.len())?;
794 let mut s = Stream::new(data);
795 metadata.local_subrs = parse_index::<u16>(&mut s)?;
796 }
797 }
798
799 Some(FontKind::SID(metadata))
800}
801
802fn parse_cid_metadata(data: &[u8], top_dict: TopDict, number_of_glyphs: u16) -> Option<FontKind> {
803 let (charset_offset, fd_array_offset, fd_select_offset) = match (
804 top_dict.charset_offset,
805 top_dict.fd_array_offset,
806 top_dict.fd_select_offset,
807 ) {
808 (Some(a), Some(b), Some(c)) => (a, b, c),
809 _ => return None, };
811
812 if charset_offset <= charset_id::EXPERT_SUBSET {
813 return None;
816 }
817
818 let mut metadata = CIDMetadata::default();
819
820 metadata.fd_array = {
821 let mut s = Stream::new_at(data, fd_array_offset)?;
822 parse_index::<u16>(&mut s)?
823 };
824
825 metadata.fd_select = {
826 let mut s = Stream::new_at(data, fd_select_offset)?;
827 parse_fd_select(number_of_glyphs, &mut s)?
828 };
829
830 Some(FontKind::CID(metadata))
831}
832
833#[derive(Clone, Copy)]
836pub struct Table<'a> {
837 table_data: &'a [u8],
840
841 #[allow(dead_code)]
842 strings: Index<'a>,
843 global_subrs: Index<'a>,
844 charset: Charset<'a>,
845 number_of_glyphs: NonZeroU16,
846 matrix: Matrix,
847 char_strings: Index<'a>,
848 kind: FontKind<'a>,
849}
850
851impl<'a> Table<'a> {
852 pub fn parse(data: &'a [u8]) -> Option<Self> {
854 let mut s = Stream::new(data);
855
856 let major = s.read::<u8>()?;
858 s.skip::<u8>(); let header_size = s.read::<u8>()?;
860 s.skip::<u8>(); if major != 1 {
863 return None;
864 }
865
866 if header_size > 4 {
868 s.advance(usize::from(header_size) - 4);
869 }
870
871 skip_index::<u16>(&mut s)?;
873
874 let top_dict = parse_top_dict(&mut s)?;
875
876 if top_dict.char_strings_offset == 0 {
878 return None;
879 }
880
881 let strings = parse_index::<u16>(&mut s)?;
883
884 let global_subrs = parse_index::<u16>(&mut s)?;
886
887 let char_strings = {
888 let mut s = Stream::new_at(data, top_dict.char_strings_offset)?;
889 parse_index::<u16>(&mut s)?
890 };
891
892 let number_of_glyphs = u16::try_from(char_strings.len())
894 .ok()
895 .and_then(NonZeroU16::new)?;
896
897 let charset = match top_dict.charset_offset {
898 Some(charset_id::ISO_ADOBE) => Charset::ISOAdobe,
899 Some(charset_id::EXPERT) => Charset::Expert,
900 Some(charset_id::EXPERT_SUBSET) => Charset::ExpertSubset,
901 Some(offset) => {
902 let mut s = Stream::new_at(data, offset)?;
903 parse_charset(number_of_glyphs, &mut s)?
904 }
905 None => Charset::ISOAdobe, };
907
908 let matrix = top_dict.matrix;
909
910 let kind = if top_dict.has_ros {
911 parse_cid_metadata(data, top_dict, number_of_glyphs.get())?
912 } else {
913 let encoding = match top_dict.encoding_offset {
915 Some(encoding_id::STANDARD) => Encoding::new_standard(),
916 Some(encoding_id::EXPERT) => Encoding::new_expert(),
917 Some(offset) => parse_encoding(&mut Stream::new_at(data, offset)?)?,
918 None => Encoding::new_standard(), };
920
921 parse_sid_metadata(data, top_dict, encoding)?
922 };
923
924 Some(Self {
925 table_data: data,
926 strings,
927 global_subrs,
928 charset,
929 number_of_glyphs,
930 matrix,
931 char_strings,
932 kind,
933 })
934 }
935
936 #[inline]
940 pub fn number_of_glyphs(&self) -> u16 {
941 self.number_of_glyphs.get()
942 }
943
944 #[inline]
946 pub fn matrix(&self) -> Matrix {
947 self.matrix
948 }
949
950 pub fn outline(
952 &self,
953 glyph_id: GlyphId,
954 builder: &mut dyn OutlineBuilder,
955 ) -> Result<Rect, CFFError> {
956 let data = self
957 .char_strings
958 .get(u32::from(glyph_id.0))
959 .ok_or(CFFError::NoGlyph)?;
960 parse_char_string(data, self, glyph_id, false, builder).map(|v| v.0)
961 }
962
963 pub fn glyph_index(&self, code_point: u8) -> Option<GlyphId> {
968 match self.kind {
969 FontKind::SID(ref sid_meta) => {
970 match sid_meta.encoding.code_to_gid(&self.charset, code_point) {
971 Some(id) => Some(id),
972 None => {
973 Encoding::new_standard().code_to_gid(&self.charset, code_point)
976 }
977 }
978 }
979 FontKind::CID(_) => None,
980 }
981 }
982
983 pub fn glyph_width(&self, glyph_id: GlyphId) -> Option<u16> {
989 match self.kind {
990 FontKind::SID(ref sid) => {
991 let data = self.char_strings.get(u32::from(glyph_id.0))?;
992 let (_, width) =
993 parse_char_string(data, self, glyph_id, true, &mut DummyOutline).ok()?;
994 let width = width
995 .map(|w| sid.nominal_width + w)
996 .unwrap_or(sid.default_width);
997 u16::try_from(width as i32).ok()
998 }
999 FontKind::CID(_) => None,
1000 }
1001 }
1002
1003 #[cfg(feature = "glyph-names")]
1005 pub fn glyph_index_by_name(&self, name: &str) -> Option<GlyphId> {
1006 match self.kind {
1007 FontKind::SID(_) => {
1008 let sid = if let Some(index) = STANDARD_NAMES.iter().position(|n| *n == name) {
1009 StringId(index as u16)
1010 } else {
1011 let index = self
1012 .strings
1013 .into_iter()
1014 .position(|n| n == name.as_bytes())?;
1015 StringId((STANDARD_NAMES.len() + index) as u16)
1016 };
1017
1018 self.charset.sid_to_gid(sid)
1019 }
1020 FontKind::CID(_) => None,
1021 }
1022 }
1023
1024 #[cfg(feature = "glyph-names")]
1026 pub fn glyph_name(&self, glyph_id: GlyphId) -> Option<&'a str> {
1027 match self.kind {
1028 FontKind::SID(_) => {
1029 let sid = self.charset.gid_to_sid(glyph_id)?;
1030 let sid = usize::from(sid.0);
1031 match STANDARD_NAMES.get(sid) {
1032 Some(name) => Some(name),
1033 None => {
1034 let idx = u32::try_from(sid - STANDARD_NAMES.len()).ok()?;
1035 let name = self.strings.get(idx)?;
1036 core::str::from_utf8(name).ok()
1037 }
1038 }
1039 }
1040 FontKind::CID(_) => None,
1041 }
1042 }
1043
1044 #[cfg(feature = "glyph-names")]
1048 pub fn glyph_cid(&self, glyph_id: GlyphId) -> Option<u16> {
1049 match self.kind {
1050 FontKind::SID(_) => None,
1051 FontKind::CID(_) => self.charset.gid_to_sid(glyph_id).map(|id| id.0),
1052 }
1053 }
1054}
1055
1056impl core::fmt::Debug for Table<'_> {
1057 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1058 write!(f, "Table {{ ... }}")
1059 }
1060}