1use core::convert::TryFrom;
7use core::num::NonZeroU16;
8use core::ops::Range;
9
10use super::argstack::ArgumentsStack;
11use super::charset::{parse_charset, Charset};
12use super::charstring::CharStringParser;
13use super::dict::DictionaryParser;
14use super::encoding::{parse_encoding, Encoding, STANDARD_ENCODING};
15use super::index::{parse_index, skip_index, Index};
16use super::std_names::STANDARD_NAMES;
17use super::{calc_subroutine_bias, conv_subroutine_index, Builder, CFFError, IsEven, StringId};
18use crate::parser::{LazyArray16, NumFrom, Stream, TryNumFrom};
19use crate::{DummyOutline, GlyphId, OutlineBuilder, Rect, RectF};
20
21const MAX_OPERANDS_LEN: usize = 48;
23
24const STACK_LIMIT: u8 = 10;
26const MAX_ARGUMENTS_STACK_LEN: usize = 48;
27
28const TWO_BYTE_OPERATOR_MARK: u8 = 12;
29
30mod operator {
32 pub const HORIZONTAL_STEM: u8 = 1;
33 pub const VERTICAL_STEM: u8 = 3;
34 pub const VERTICAL_MOVE_TO: u8 = 4;
35 pub const LINE_TO: u8 = 5;
36 pub const HORIZONTAL_LINE_TO: u8 = 6;
37 pub const VERTICAL_LINE_TO: u8 = 7;
38 pub const CURVE_TO: u8 = 8;
39 pub const CALL_LOCAL_SUBROUTINE: u8 = 10;
40 pub const RETURN: u8 = 11;
41 pub const ENDCHAR: u8 = 14;
42 pub const HORIZONTAL_STEM_HINT_MASK: u8 = 18;
43 pub const HINT_MASK: u8 = 19;
44 pub const COUNTER_MASK: u8 = 20;
45 pub const MOVE_TO: u8 = 21;
46 pub const HORIZONTAL_MOVE_TO: u8 = 22;
47 pub const VERTICAL_STEM_HINT_MASK: u8 = 23;
48 pub const CURVE_LINE: u8 = 24;
49 pub const LINE_CURVE: u8 = 25;
50 pub const VV_CURVE_TO: u8 = 26;
51 pub const HH_CURVE_TO: u8 = 27;
52 pub const SHORT_INT: u8 = 28;
53 pub const CALL_GLOBAL_SUBROUTINE: u8 = 29;
54 pub const VH_CURVE_TO: u8 = 30;
55 pub const HV_CURVE_TO: u8 = 31;
56 pub const HFLEX: u8 = 34;
57 pub const FLEX: u8 = 35;
58 pub const HFLEX1: u8 = 36;
59 pub const FLEX1: u8 = 37;
60 pub const FIXED_16_16: u8 = 255;
61}
62
63mod top_dict_operator {
66 pub const VERSION: u16 = 0;
67 pub const NOTICE: u16 = 1;
68 pub const FULL_NAME: u16 = 2;
69 pub const FAMILY_NAME: u16 = 3;
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 version: Option<StringId>,
151 notice: Option<StringId>,
152 full_name: Option<StringId>,
153 family_name: Option<StringId>,
154 charset_offset: Option<usize>,
155 encoding_offset: Option<usize>,
156 char_strings_offset: usize,
157 private_dict_range: Option<Range<usize>>,
158 matrix: Matrix,
159 has_ros: bool,
160 fd_array_offset: Option<usize>,
161 fd_select_offset: Option<usize>,
162}
163
164fn parse_top_dict(s: &mut Stream) -> Option<TopDict> {
165 let mut top_dict = TopDict::default();
166
167 let index = parse_index::<u16>(s)?;
168
169 let data = index.get(0)?;
171
172 let mut operands_buffer = [0.0; MAX_OPERANDS_LEN];
173 let mut dict_parser = DictionaryParser::new(data, &mut operands_buffer);
174 while let Some(operator) = dict_parser.parse_next() {
175 match operator.get() {
176 top_dict_operator::VERSION => {
177 top_dict.version = dict_parser.parse_sid();
178 }
179 top_dict_operator::NOTICE => {
180 top_dict.notice = dict_parser.parse_sid();
181 }
182 top_dict_operator::FULL_NAME => {
183 top_dict.full_name = dict_parser.parse_sid();
184 }
185 top_dict_operator::FAMILY_NAME => {
186 top_dict.family_name = dict_parser.parse_sid();
187 }
188 top_dict_operator::CHARSET_OFFSET => {
189 top_dict.charset_offset = dict_parser.parse_offset();
190 }
191 top_dict_operator::ENCODING_OFFSET => {
192 top_dict.encoding_offset = dict_parser.parse_offset();
193 }
194 top_dict_operator::CHAR_STRINGS_OFFSET => {
195 top_dict.char_strings_offset = dict_parser.parse_offset()?;
196 }
197 top_dict_operator::PRIVATE_DICT_SIZE_AND_OFFSET => {
198 top_dict.private_dict_range = dict_parser.parse_range();
199 }
200 top_dict_operator::FONT_MATRIX => {
201 dict_parser.parse_operands()?;
202 let operands = dict_parser.operands();
203 if operands.len() == 6 {
204 top_dict.matrix = Matrix {
205 sx: operands[0] as f32,
206 ky: operands[1] as f32,
207 kx: operands[2] as f32,
208 sy: operands[3] as f32,
209 tx: operands[4] as f32,
210 ty: operands[5] as f32,
211 };
212 }
213 }
214 top_dict_operator::ROS => {
215 top_dict.has_ros = true;
216 }
217 top_dict_operator::FD_ARRAY => {
218 top_dict.fd_array_offset = dict_parser.parse_offset();
219 }
220 top_dict_operator::FD_SELECT => {
221 top_dict.fd_select_offset = dict_parser.parse_offset();
222 }
223 _ => {}
224 }
225 }
226
227 Some(top_dict)
228}
229
230#[cfg(test)]
232mod tests {
233 use super::*;
234
235 #[test]
236 fn private_dict_size_overflow() {
237 let data = &[
238 0x00, 0x01, 0x01, 0x01, 0x0C, 0x1D, 0x7F, 0xFF, 0xFF, 0xFF, 0x1D, 0x7F, 0xFF, 0xFF, 0xFF, 0x12, ];
246
247 let top_dict = parse_top_dict(&mut Stream::new(data)).unwrap();
248 assert_eq!(top_dict.private_dict_range, Some(2147483647..4294967294));
249 }
250
251 #[test]
252 fn private_dict_negative_char_strings_offset() {
253 let data = &[
254 0x00, 0x01, 0x01, 0x01, 0x03, 0x8A, 0x11, ];
262
263 assert!(parse_top_dict(&mut Stream::new(data)).is_none());
264 }
265
266 #[test]
267 fn private_dict_no_char_strings_offset_operand() {
268 let data = &[
269 0x00, 0x01, 0x01, 0x01, 0x02, 0x11, ];
277
278 assert!(parse_top_dict(&mut Stream::new(data)).is_none());
279 }
280
281 #[test]
282 fn negative_private_dict_offset_and_size() {
283 let data = &[
284 0x00, 0x01, 0x01, 0x01, 0x04, 0x8A, 0x8A, 0x12, ];
293
294 let top_dict = parse_top_dict(&mut Stream::new(data)).unwrap();
295 assert!(top_dict.private_dict_range.is_none());
296 }
297}
298
299#[derive(Default, Debug)]
300struct PrivateDict {
301 local_subroutines_offset: Option<usize>,
302 default_width: Option<f32>,
303 nominal_width: Option<f32>,
304}
305
306fn parse_private_dict(data: &[u8]) -> PrivateDict {
307 let mut dict = PrivateDict::default();
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() == private_dict_operator::LOCAL_SUBROUTINES_OFFSET {
312 dict.local_subroutines_offset = dict_parser.parse_offset();
313 } else if operator.get() == private_dict_operator::DEFAULT_WIDTH {
314 dict.default_width = dict_parser.parse_number().map(|n| n as f32);
315 } else if operator.get() == private_dict_operator::NOMINAL_WIDTH {
316 dict.nominal_width = dict_parser.parse_number().map(|n| n as f32);
317 }
318 }
319
320 dict
321}
322
323fn parse_font_dict(data: &[u8]) -> Option<Range<usize>> {
324 let mut operands_buffer = [0.0; MAX_OPERANDS_LEN];
325 let mut dict_parser = DictionaryParser::new(data, &mut operands_buffer);
326 while let Some(operator) = dict_parser.parse_next() {
327 if operator.get() == top_dict_operator::PRIVATE_DICT_SIZE_AND_OFFSET {
328 return dict_parser.parse_range();
329 }
330 }
331
332 None
333}
334
335fn parse_cid_local_subrs<'a>(
342 data: &'a [u8],
343 glyph_id: GlyphId,
344 cid: &CIDMetadata,
345) -> Option<Index<'a>> {
346 let font_dict_index = cid.fd_select.font_dict_index(glyph_id)?;
347 let font_dict_data = cid.fd_array.get(u32::from(font_dict_index))?;
348 let private_dict_range = parse_font_dict(font_dict_data)?;
349 let private_dict_data = data.get(private_dict_range.clone())?;
350 let private_dict = parse_private_dict(private_dict_data);
351 let subroutines_offset = private_dict.local_subroutines_offset?;
352
353 let start = private_dict_range.start.checked_add(subroutines_offset)?;
356 let subrs_data = data.get(start..)?;
357 let mut s = Stream::new(subrs_data);
358 parse_index::<u16>(&mut s)
359}
360
361pub fn string_by_id<'a>(metadata: &'a Table, sid: StringId) -> Option<&'a str> {
362 let sid = usize::from(sid.0);
363 match STANDARD_NAMES.get(sid) {
364 Some(name) => Some(name),
365 None => {
366 let idx = u32::try_from(sid - STANDARD_NAMES.len()).ok()?;
367 let name = metadata.strings.get(idx)?;
368 core::str::from_utf8(name).ok()
369 }
370 }
371}
372
373struct CharStringParserContext<'a> {
374 metadata: &'a Table<'a>,
375 width: Option<f32>,
376 stems_len: u32,
377 has_endchar: bool,
378 has_seac: bool,
379 glyph_id: GlyphId, local_subrs: Option<Index<'a>>,
381}
382
383fn parse_char_string(
384 data: &[u8],
385 metadata: &Table,
386 glyph_id: GlyphId,
387 width_only: bool,
388 builder: &mut dyn OutlineBuilder,
389) -> Result<(Rect, Option<f32>), CFFError> {
390 let local_subrs = match metadata.kind {
391 FontKind::SID(ref sid) => Some(sid.local_subrs),
392 FontKind::CID(_) => None, };
394
395 let mut ctx = CharStringParserContext {
396 metadata,
397 width: None,
398 stems_len: 0,
399 has_endchar: false,
400 has_seac: false,
401 glyph_id,
402 local_subrs,
403 };
404
405 let mut inner_builder = Builder {
406 builder,
407 bbox: RectF::new(),
408 };
409
410 let stack = ArgumentsStack {
411 data: &mut [0.0; MAX_ARGUMENTS_STACK_LEN], len: 0,
413 max_len: MAX_ARGUMENTS_STACK_LEN,
414 };
415 let mut parser = CharStringParser {
416 stack,
417 builder: &mut inner_builder,
418 x: 0.0,
419 y: 0.0,
420 has_move_to: false,
421 is_first_move_to: true,
422 width_only,
423 };
424 _parse_char_string(&mut ctx, data, 0, &mut parser)?;
425
426 if width_only {
427 return Ok((Rect::zero(), ctx.width));
428 }
429
430 if !ctx.has_endchar {
431 return Err(CFFError::MissingEndChar);
432 }
433
434 let bbox = parser.builder.bbox;
435
436 if bbox.is_default() {
438 return Err(CFFError::ZeroBBox);
439 }
440
441 let rect = bbox.to_rect().ok_or(CFFError::BboxOverflow)?;
442 Ok((rect, ctx.width))
443}
444
445fn _parse_char_string(
446 ctx: &mut CharStringParserContext,
447 char_string: &[u8],
448 depth: u8,
449 p: &mut CharStringParser,
450) -> Result<(), CFFError> {
451 let mut s = Stream::new(char_string);
452 while !s.at_end() {
453 let op = s.read::<u8>().ok_or(CFFError::ReadOutOfBounds)?;
454 match op {
455 0 | 2 | 9 | 13 | 15 | 16 | 17 => {
456 return Err(CFFError::InvalidOperator);
458 }
459 operator::HORIZONTAL_STEM
460 | operator::VERTICAL_STEM
461 | operator::HORIZONTAL_STEM_HINT_MASK
462 | operator::VERTICAL_STEM_HINT_MASK => {
463 let len = if p.stack.len().is_odd() && ctx.width.is_none() {
470 ctx.width = Some(p.stack.at(0));
471 p.stack.len() - 1
472 } else {
473 p.stack.len()
474 };
475
476 ctx.stems_len += len as u32 >> 1;
477
478 p.stack.clear();
480 }
481 operator::VERTICAL_MOVE_TO => {
482 let mut i = 0;
483 if p.stack.len() == 2 {
484 i += 1;
485 if ctx.width.is_none() {
486 ctx.width = Some(p.stack.at(0));
487 }
488 }
489
490 p.parse_vertical_move_to(i)?;
491 }
492 operator::LINE_TO => {
493 p.parse_line_to()?;
494 }
495 operator::HORIZONTAL_LINE_TO => {
496 p.parse_horizontal_line_to()?;
497 }
498 operator::VERTICAL_LINE_TO => {
499 p.parse_vertical_line_to()?;
500 }
501 operator::CURVE_TO => {
502 p.parse_curve_to()?;
503 }
504 operator::CALL_LOCAL_SUBROUTINE => {
505 if p.stack.is_empty() {
506 return Err(CFFError::InvalidArgumentsStackLength);
507 }
508
509 if depth == STACK_LIMIT {
510 return Err(CFFError::NestingLimitReached);
511 }
512
513 if ctx.local_subrs.is_none() {
517 if let FontKind::CID(ref cid) = ctx.metadata.kind {
518 ctx.local_subrs =
519 parse_cid_local_subrs(ctx.metadata.table_data, ctx.glyph_id, cid);
520 }
521 }
522
523 if let Some(local_subrs) = ctx.local_subrs {
524 let subroutine_bias = calc_subroutine_bias(local_subrs.len());
525 let index = conv_subroutine_index(p.stack.pop(), subroutine_bias)?;
526 let char_string = local_subrs
527 .get(index)
528 .ok_or(CFFError::InvalidSubroutineIndex)?;
529 _parse_char_string(ctx, char_string, depth + 1, p)?;
530 } else {
531 return Err(CFFError::NoLocalSubroutines);
532 }
533
534 if ctx.has_endchar && !ctx.has_seac {
535 if !s.at_end() {
536 return Err(CFFError::DataAfterEndChar);
537 }
538
539 break;
540 }
541 }
542 operator::RETURN => {
543 break;
544 }
545 TWO_BYTE_OPERATOR_MARK => {
546 let op2 = s.read::<u8>().ok_or(CFFError::ReadOutOfBounds)?;
548 match op2 {
549 operator::HFLEX => p.parse_hflex()?,
550 operator::FLEX => p.parse_flex()?,
551 operator::HFLEX1 => p.parse_hflex1()?,
552 operator::FLEX1 => p.parse_flex1()?,
553 _ => return Err(CFFError::UnsupportedOperator),
554 }
555 }
556 operator::ENDCHAR => {
557 if p.stack.len() == 4 || (ctx.width.is_none() && p.stack.len() == 5) {
558 let accent_char = seac_code_to_glyph_id(&ctx.metadata.charset, p.stack.pop())
560 .ok_or(CFFError::InvalidSeacCode)?;
561 let base_char = seac_code_to_glyph_id(&ctx.metadata.charset, p.stack.pop())
562 .ok_or(CFFError::InvalidSeacCode)?;
563 let dy = p.stack.pop();
564 let dx = p.stack.pop();
565
566 if ctx.width.is_none() && !p.stack.is_empty() {
567 ctx.width = Some(p.stack.pop())
568 }
569
570 ctx.has_seac = true;
571
572 if depth == STACK_LIMIT {
573 return Err(CFFError::NestingLimitReached);
574 }
575
576 let base_char_string = ctx
577 .metadata
578 .char_strings
579 .get(u32::from(base_char.0))
580 .ok_or(CFFError::InvalidSeacCode)?;
581 _parse_char_string(ctx, base_char_string, depth + 1, p)?;
582 p.x = dx;
583 p.y = dy;
584
585 let accent_char_string = ctx
586 .metadata
587 .char_strings
588 .get(u32::from(accent_char.0))
589 .ok_or(CFFError::InvalidSeacCode)?;
590 _parse_char_string(ctx, accent_char_string, depth + 1, p)?;
591 } else if p.stack.len() == 1 && ctx.width.is_none() {
592 ctx.width = Some(p.stack.pop());
593 }
594
595 if !p.is_first_move_to {
596 p.is_first_move_to = true;
597 p.builder.close();
598 }
599
600 if !s.at_end() {
601 return Err(CFFError::DataAfterEndChar);
602 }
603
604 ctx.has_endchar = true;
605
606 break;
607 }
608 operator::HINT_MASK | operator::COUNTER_MASK => {
609 let mut len = p.stack.len();
610
611 p.stack.clear();
613
614 if len.is_odd() {
616 len -= 1;
617 if ctx.width.is_none() {
618 ctx.width = Some(p.stack.at(0));
619 }
620 }
621
622 ctx.stems_len += len as u32 >> 1;
623
624 s.advance(usize::num_from((ctx.stems_len + 7) >> 3));
625 }
626 operator::MOVE_TO => {
627 let mut i = 0;
628 if p.stack.len() == 3 {
629 i += 1;
630 if ctx.width.is_none() {
631 ctx.width = Some(p.stack.at(0));
632 }
633 }
634
635 p.parse_move_to(i)?;
636 }
637 operator::HORIZONTAL_MOVE_TO => {
638 let mut i = 0;
639 if p.stack.len() == 2 {
640 i += 1;
641 if ctx.width.is_none() {
642 ctx.width = Some(p.stack.at(0));
643 }
644 }
645
646 p.parse_horizontal_move_to(i)?;
647 }
648 operator::CURVE_LINE => {
649 p.parse_curve_line()?;
650 }
651 operator::LINE_CURVE => {
652 p.parse_line_curve()?;
653 }
654 operator::VV_CURVE_TO => {
655 p.parse_vv_curve_to()?;
656 }
657 operator::HH_CURVE_TO => {
658 p.parse_hh_curve_to()?;
659 }
660 operator::SHORT_INT => {
661 let n = s.read::<i16>().ok_or(CFFError::ReadOutOfBounds)?;
662 p.stack.push(f32::from(n))?;
663 }
664 operator::CALL_GLOBAL_SUBROUTINE => {
665 if p.stack.is_empty() {
666 return Err(CFFError::InvalidArgumentsStackLength);
667 }
668
669 if depth == STACK_LIMIT {
670 return Err(CFFError::NestingLimitReached);
671 }
672
673 let subroutine_bias = calc_subroutine_bias(ctx.metadata.global_subrs.len());
674 let index = conv_subroutine_index(p.stack.pop(), subroutine_bias)?;
675 let char_string = ctx
676 .metadata
677 .global_subrs
678 .get(index)
679 .ok_or(CFFError::InvalidSubroutineIndex)?;
680 _parse_char_string(ctx, char_string, depth + 1, p)?;
681
682 if ctx.has_endchar && !ctx.has_seac {
683 if !s.at_end() {
684 return Err(CFFError::DataAfterEndChar);
685 }
686
687 break;
688 }
689 }
690 operator::VH_CURVE_TO => {
691 p.parse_vh_curve_to()?;
692 }
693 operator::HV_CURVE_TO => {
694 p.parse_hv_curve_to()?;
695 }
696 32..=246 => {
697 p.parse_int1(op)?;
698 }
699 247..=250 => {
700 p.parse_int2(op, &mut s)?;
701 }
702 251..=254 => {
703 p.parse_int3(op, &mut s)?;
704 }
705 operator::FIXED_16_16 => {
706 p.parse_fixed(&mut s)?;
707 }
708 }
709
710 if p.width_only && ctx.width.is_some() {
711 break;
712 }
713 }
714
715 Ok(())
718}
719
720fn seac_code_to_glyph_id(charset: &Charset, n: f32) -> Option<GlyphId> {
721 let code = u8::try_num_from(n)?;
722
723 let sid = STANDARD_ENCODING[usize::from(code)];
724 let sid = StringId(u16::from(sid));
725
726 match charset {
727 Charset::ISOAdobe => {
728 if code <= 228 {
730 Some(GlyphId(sid.0))
731 } else {
732 None
733 }
734 }
735 Charset::Expert | Charset::ExpertSubset => None,
736 _ => charset.sid_to_gid(sid),
737 }
738}
739
740#[derive(Clone, Copy, Debug)]
741enum FDSelect<'a> {
742 Format0(LazyArray16<'a, u8>),
743 Format3(&'a [u8]), }
745
746impl Default for FDSelect<'_> {
747 fn default() -> Self {
748 FDSelect::Format0(LazyArray16::default())
749 }
750}
751
752impl FDSelect<'_> {
753 fn font_dict_index(&self, glyph_id: GlyphId) -> Option<u8> {
754 match self {
755 FDSelect::Format0(ref array) => array.get(glyph_id.0),
756 FDSelect::Format3(data) => {
757 let mut s = Stream::new(data);
758 let number_of_ranges = s.read::<u16>()?;
759 if number_of_ranges == 0 {
760 return None;
761 }
762
763 let number_of_ranges = number_of_ranges.checked_add(1)?;
767
768 let mut prev_first_glyph = s.read::<GlyphId>()?;
770 let mut prev_index = s.read::<u8>()?;
771 for _ in 1..number_of_ranges {
772 let curr_first_glyph = s.read::<GlyphId>()?;
773 if (prev_first_glyph..curr_first_glyph).contains(&glyph_id) {
774 return Some(prev_index);
775 } else {
776 prev_index = s.read::<u8>()?;
777 }
778
779 prev_first_glyph = curr_first_glyph;
780 }
781
782 None
783 }
784 }
785 }
786}
787
788fn parse_fd_select<'a>(number_of_glyphs: u16, s: &mut Stream<'a>) -> Option<FDSelect<'a>> {
789 let format = s.read::<u8>()?;
790 match format {
791 0 => Some(FDSelect::Format0(s.read_array16::<u8>(number_of_glyphs)?)),
792 3 => Some(FDSelect::Format3(s.tail()?)),
793 _ => None,
794 }
795}
796
797fn parse_sid_metadata<'a>(
798 data: &'a [u8],
799 top_dict: TopDict,
800 encoding: Encoding<'a>,
801) -> Option<FontKind<'a>> {
802 let mut metadata = SIDMetadata::default();
803 metadata.encoding = encoding;
804
805 let private_dict = if let Some(range) = top_dict.private_dict_range.clone() {
806 parse_private_dict(data.get(range)?)
807 } else {
808 return Some(FontKind::SID(metadata));
809 };
810
811 metadata.default_width = private_dict.default_width.unwrap_or(0.0);
812 metadata.nominal_width = private_dict.nominal_width.unwrap_or(0.0);
813
814 if let (Some(private_dict_range), Some(subroutines_offset)) = (
815 top_dict.private_dict_range,
816 private_dict.local_subroutines_offset,
817 ) {
818 if let Some(start) = private_dict_range.start.checked_add(subroutines_offset) {
821 let data = data.get(start..data.len())?;
822 let mut s = Stream::new(data);
823 metadata.local_subrs = parse_index::<u16>(&mut s)?;
824 }
825 }
826
827 Some(FontKind::SID(metadata))
828}
829
830fn parse_cid_metadata(data: &[u8], top_dict: TopDict, number_of_glyphs: u16) -> Option<FontKind> {
831 let (charset_offset, fd_array_offset, fd_select_offset) = match (
832 top_dict.charset_offset,
833 top_dict.fd_array_offset,
834 top_dict.fd_select_offset,
835 ) {
836 (Some(a), Some(b), Some(c)) => (a, b, c),
837 _ => return None, };
839
840 if charset_offset <= charset_id::EXPERT_SUBSET {
841 return None;
844 }
845
846 let mut metadata = CIDMetadata::default();
847
848 metadata.fd_array = {
849 let mut s = Stream::new_at(data, fd_array_offset)?;
850 parse_index::<u16>(&mut s)?
851 };
852
853 metadata.fd_select = {
854 let mut s = Stream::new_at(data, fd_select_offset)?;
855 parse_fd_select(number_of_glyphs, &mut s)?
856 };
857
858 Some(FontKind::CID(metadata))
859}
860
861#[derive(Clone, Copy)]
864pub struct Table<'a> {
865 table_data: &'a [u8],
868
869 #[allow(dead_code)]
870 strings: Index<'a>,
871 global_subrs: Index<'a>,
872 pub encoding: Encoding<'a>,
873 pub charset: Charset<'a>,
874 number_of_glyphs: NonZeroU16,
875 matrix: Matrix,
876 char_strings: Index<'a>,
877 kind: FontKind<'a>,
878 version: Option<StringId>,
879 notice: Option<StringId>,
880 full_name: Option<StringId>,
881 family_name: Option<StringId>,
882}
883
884impl<'a> Table<'a> {
885 pub fn parse(data: &'a [u8]) -> Option<Self> {
887 let mut s = Stream::new(data);
888
889 let major = s.read::<u8>()?;
891 s.skip::<u8>(); let header_size = s.read::<u8>()?;
893 s.skip::<u8>(); if major != 1 {
896 return None;
897 }
898
899 if header_size > 4 {
901 s.advance(usize::from(header_size) - 4);
902 }
903
904 skip_index::<u16>(&mut s)?;
906
907 let top_dict = parse_top_dict(&mut s)?;
908
909 if top_dict.char_strings_offset == 0 {
911 return None;
912 }
913
914 let strings = parse_index::<u16>(&mut s)?;
916
917 let global_subrs = parse_index::<u16>(&mut s)?;
919
920 let char_strings = {
921 let mut s = Stream::new_at(data, top_dict.char_strings_offset)?;
922 parse_index::<u16>(&mut s)?
923 };
924
925 let number_of_glyphs = u16::try_from(char_strings.len())
927 .ok()
928 .and_then(NonZeroU16::new)?;
929
930 let charset = match top_dict.charset_offset {
931 Some(charset_id::ISO_ADOBE) => Charset::ISOAdobe,
932 Some(charset_id::EXPERT) => Charset::Expert,
933 Some(charset_id::EXPERT_SUBSET) => Charset::ExpertSubset,
934 Some(offset) => {
935 let mut s = Stream::new_at(data, offset)?;
936 parse_charset(number_of_glyphs, &mut s)?
937 }
938 None => Charset::ISOAdobe, };
940
941 let matrix = top_dict.matrix;
942 let version = top_dict.version;
943 let notice = top_dict.notice;
944 let full_name = top_dict.full_name;
945 let family_name = top_dict.family_name;
946
947 let encoding = match top_dict.encoding_offset {
949 Some(encoding_id::STANDARD) => Encoding::new_standard(),
950 Some(encoding_id::EXPERT) => Encoding::new_expert(),
951 Some(offset) => parse_encoding(&mut Stream::new_at(data, offset)?)?,
952 None => Encoding::new_standard(), };
954
955 let kind = if top_dict.has_ros {
956 parse_cid_metadata(data, top_dict, number_of_glyphs.get())?
957 } else {
958 parse_sid_metadata(data, top_dict, encoding.clone())?
959 };
960
961 Some(Self {
962 table_data: data,
963 strings,
964 global_subrs,
965 encoding,
966 charset,
967 number_of_glyphs,
968 matrix,
969 char_strings,
970 kind,
971 version,
972 notice,
973 full_name,
974 family_name,
975 })
976 }
977
978 #[inline]
982 pub fn number_of_glyphs(&self) -> u16 {
983 self.number_of_glyphs.get()
984 }
985
986 #[inline]
988 pub fn matrix(&self) -> Matrix {
989 self.matrix
990 }
991
992 pub fn outline(
994 &self,
995 glyph_id: GlyphId,
996 builder: &mut dyn OutlineBuilder,
997 ) -> Result<Rect, CFFError> {
998 let data = self
999 .char_strings
1000 .get(u32::from(glyph_id.0))
1001 .ok_or(CFFError::NoGlyph)?;
1002 parse_char_string(data, self, glyph_id, false, builder).map(|v| v.0)
1003 }
1004
1005 pub fn glyph_index(&self, code_point: u8) -> Option<GlyphId> {
1010 match self.kind {
1011 FontKind::SID(ref sid_meta) => {
1012 match sid_meta.encoding.code_to_gid(&self.charset, code_point) {
1013 Some(id) => Some(id),
1014 None => {
1015 Encoding::new_standard().code_to_gid(&self.charset, code_point)
1018 }
1019 }
1020 }
1021 FontKind::CID(_) => None,
1022 }
1023 }
1024
1025 pub fn glyph_width(&self, glyph_id: GlyphId) -> Option<u16> {
1031 match self.kind {
1032 FontKind::SID(ref sid) => {
1033 let data = self.char_strings.get(u32::from(glyph_id.0))?;
1034 let (_, width) =
1035 parse_char_string(data, self, glyph_id, true, &mut DummyOutline).ok()?;
1036 let width = width
1037 .map(|w| sid.nominal_width + w)
1038 .unwrap_or(sid.default_width);
1039 u16::try_from(width as i32).ok()
1040 }
1041 FontKind::CID(_) => None,
1042 }
1043 }
1044
1045 pub fn glyph_index_by_name(&self, name: &str) -> Option<GlyphId> {
1047 match self.kind {
1048 FontKind::SID(_) => {
1049 let sid = if let Some(index) = STANDARD_NAMES.iter().position(|n| *n == name) {
1050 StringId(index as u16)
1051 } else {
1052 let index = self
1053 .strings
1054 .into_iter()
1055 .position(|n| n == name.as_bytes())?;
1056 StringId((STANDARD_NAMES.len() + index) as u16)
1057 };
1058
1059 self.charset.sid_to_gid(sid)
1060 }
1061 FontKind::CID(_) => None,
1062 }
1063 }
1064
1065 pub fn glyph_name(&self, glyph_id: GlyphId) -> Option<&'a str> {
1067 match self.kind {
1068 FontKind::SID(_) => {
1069 let sid = self.charset.gid_to_sid(glyph_id)?;
1070 let sid = usize::from(sid.0);
1071 match STANDARD_NAMES.get(sid) {
1072 Some(name) => Some(name),
1073 None => {
1074 let idx = u32::try_from(sid - STANDARD_NAMES.len()).ok()?;
1075 let name = self.strings.get(idx)?;
1076 core::str::from_utf8(name).ok()
1077 }
1078 }
1079 }
1080 FontKind::CID(_) => None,
1081 }
1082 }
1083
1084 pub fn glyph_cid(&self, glyph_id: GlyphId) -> Option<u16> {
1088 match self.kind {
1089 FontKind::SID(_) => None,
1090 FontKind::CID(_) => self.charset.gid_to_sid(glyph_id).map(|id| id.0),
1091 }
1092 }
1093
1094 pub fn version(&self) -> Option<&str> {
1095 self.version.and_then(|sid| string_by_id(&self, sid))
1096 }
1097
1098 pub fn notice(&self) -> Option<&str> {
1099 self.notice.and_then(|sid| string_by_id(&self, sid))
1100 }
1101
1102 pub fn full_name(&self) -> Option<&str> {
1103 self.full_name.and_then(|sid| string_by_id(&self, sid))
1104 }
1105
1106 pub fn family_name(&self) -> Option<&str> {
1107 self.family_name.and_then(|sid| string_by_id(&self, sid))
1108 }
1109}
1110
1111impl core::fmt::Debug for Table<'_> {
1112 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1113 write!(f, "Table {{ ... }}")
1114 }
1115}