1use super::{
4 charmap::Charmap,
5 cs::{self, CharstringContext, CharstringKind, CommandSink, NopFilterSink, TransformSink},
6 encoding::PredefinedEncoding,
7 error::Error,
8 transform::{self, FontMatrix, ScaledFontMatrix, Transform},
9};
10use crate::{
11 model::pen::OutlinePen,
12 types::{BoundingBox, Fixed, GlyphId},
13 ReadError,
14};
15use alloc::{string::String, vec::Vec};
16use core::ops::Range;
17
18pub struct Type1Font {
20 name: Option<String>,
21 full_name: Option<String>,
22 family_name: Option<String>,
23 weight: Option<String>,
24 bbox: BoundingBox<Fixed>,
25 italic_angle: i32,
26 is_fixed_pitch: bool,
27 underline_position: i32,
28 underline_thickness: i32,
29 matrix: ScaledFontMatrix,
30 charstrings: Charstrings,
31 subrs: Subrs,
32 encoding: Option<RawEncoding>,
33 weight_vector: Vec<Fixed>,
34 unicode_charmap: Charmap,
35}
36
37impl Type1Font {
38 pub fn new(data: &[u8]) -> Result<Self, Error> {
40 Self::new_impl(data).ok_or(Error::InvalidFontFormat)
43 }
44
45 fn new_impl(data: &[u8]) -> Option<Self> {
46 let raw_dicts = RawDicts::new(data)?;
47 Self::from_dicts(raw_dicts.base, &raw_dicts.private)
48 }
49
50 fn empty() -> Self {
51 Self {
52 name: None,
53 full_name: None,
54 family_name: None,
55 weight: None,
56 italic_angle: 0,
57 is_fixed_pitch: false,
58 underline_position: 0,
59 underline_thickness: 0,
60 matrix: ScaledFontMatrix {
61 matrix: FontMatrix::IDENTITY,
62 scale: 1000,
63 },
64 bbox: BoundingBox::default(),
65 charstrings: Charstrings::default(),
66 subrs: Subrs::default(),
67 encoding: None,
68 weight_vector: Vec::new(),
69 unicode_charmap: Charmap::default(),
70 }
71 }
72
73 fn from_dicts(base: &[u8], private: &[u8]) -> Option<Self> {
74 let mut font = Self::empty();
75 let mut encoding_offset = None;
77 let mut parser = Parser::new(base);
78 while let Some(token) = parser.next() {
79 match token {
80 Token::Name(b"FontName") => font.name = parser.read_string(),
81 Token::Name(b"FullName") => font.full_name = parser.read_string(),
82 Token::Name(b"FamilyName") => font.family_name = parser.read_string(),
83 Token::Name(b"Weight") => {
84 if font.weight.is_none() {
87 font.weight = parser.read_string();
88 }
89 }
90 Token::Name(b"ItalicAngle") => {
91 font.italic_angle = parser.read_num_as_int().unwrap_or(0)
92 }
93 Token::Name(b"IsFixedPitch") => {
94 font.is_fixed_pitch = parser.next() == Some(Token::Raw(b"true"))
95 }
96 Token::Name(b"UnderlinePosition") => {
97 font.underline_position = parser.read_num_as_int().unwrap_or(0);
98 }
99 Token::Name(b"UnderlineThickness") => {
100 font.underline_thickness = parser.read_num_as_int().unwrap_or(0);
101 }
102 Token::Name(b"FontBBox") => {
103 if let Some([x_min, y_min, x_max, y_max]) = parser.read_font_bbox() {
104 font.bbox = BoundingBox {
105 x_min,
106 y_min,
107 x_max,
108 y_max,
109 };
110 }
111 }
112 Token::Name(b"FontMatrix") => font.matrix = parser.read_font_matrix()?,
113 Token::Name(b"Encoding") => encoding_offset = Some(parser.pos),
117 Token::Name(b"WeightVector") => {
118 if let Some(weights) = parser.read_weight_vector() {
122 font.weight_vector = weights;
123 }
124 }
125 _ => {}
126 }
127 }
128 let mut parser = Parser::new(private);
130 let mut len_iv = 4;
132 while let Some(token) = parser.next() {
133 match token {
134 Token::Name(b"lenIV") => len_iv = parser.read_int()?,
135 Token::Name(b"Subrs") => {
136 if font.subrs.index.is_empty() {
140 font.subrs = parser.read_subrs(len_iv)?;
141 }
142 }
143 Token::Name(b"CharStrings") => {
144 if font.charstrings.index.is_empty() {
150 font.charstrings = parser.read_charstrings(len_iv)?;
151 }
152 }
153 _ => {}
154 }
155 }
156 if font.charstrings.index.is_empty() {
159 return None;
160 }
161 if let Some(encoding_offset) = encoding_offset {
162 let mut parser = Parser::new(base.get(encoding_offset..)?);
163 font.encoding = Some(parser.read_encoding(&font.charstrings)?);
164 }
165 #[cfg(feature = "agl")]
167 {
168 font.unicode_charmap = Charmap::from_glyph_names(font.glyph_names());
169 }
170 Some(font)
171 }
172
173 pub fn name(&self) -> Option<&str> {
175 self.name.as_deref()
176 }
177
178 pub fn full_name(&self) -> Option<&str> {
180 self.full_name.as_deref()
181 }
182
183 pub fn family_name(&self) -> Option<&str> {
185 self.family_name.as_deref()
186 }
187
188 pub fn weight(&self) -> Option<&str> {
190 self.weight.as_deref()
191 }
192
193 pub fn italic_angle(&self) -> i32 {
195 self.italic_angle
196 }
197
198 pub fn is_fixed_pitch(&self) -> bool {
200 self.is_fixed_pitch
201 }
202
203 pub fn underline_position(&self) -> i32 {
205 self.underline_position
206 }
207
208 pub fn underline_thickness(&self) -> i32 {
210 self.underline_thickness
211 }
212
213 pub fn bbox(&self) -> BoundingBox<Fixed> {
215 self.bbox
216 }
217
218 pub fn num_glyphs(&self) -> u32 {
220 self.charstrings.num_glyphs()
221 }
222
223 pub fn upem(&self) -> i32 {
225 self.matrix.scale
226 }
227
228 pub fn matrix(&self) -> FontMatrix {
230 self.matrix.matrix
231 }
232
233 pub fn transform(&self, ppem: Option<f32>) -> Transform {
235 let scale = ppem.map(|ppem| Transform::compute_scale(ppem, self.upem()));
236 Transform {
237 matrix: self.matrix(),
238 scale,
239 }
240 }
241
242 pub fn encoding(&self) -> Option<Encoding<'_>> {
244 self.encoding.as_ref().map(|enc| Encoding {
245 encoding: enc,
246 charstrings: &self.charstrings,
247 })
248 }
249
250 pub fn unicode_charmap(&self) -> &Charmap {
254 &self.unicode_charmap
255 }
256
257 pub fn glyph_name(&self, gid: GlyphId) -> Option<&str> {
259 self.charstrings.name(gid.to_u32())
260 }
261
262 pub fn glyph_names(&self) -> impl Iterator<Item = (GlyphId, &str)> {
265 (0..self.num_glyphs())
266 .filter_map(|idx| Some((GlyphId::new(idx), self.charstrings.name(idx)?)))
267 }
268
269 pub fn remapped_gid(&self, original_gid: GlyphId) -> GlyphId {
274 if let Some(orig_notdef) = self.charstrings.orig_notdef_index {
275 if original_gid == GlyphId::NOTDEF {
276 GlyphId::new(orig_notdef as u32)
277 } else if orig_notdef == original_gid.to_u32() as usize {
278 GlyphId::NOTDEF
279 } else {
280 original_gid
281 }
282 } else {
283 original_gid
284 }
285 }
286
287 pub fn evaluate_charstring(
293 &self,
294 gid: GlyphId,
295 sink: &mut impl CommandSink,
296 ) -> Result<Option<Fixed>, Error> {
297 let charstring_data = self
298 .charstrings
299 .get(gid.to_u32())
300 .ok_or(ReadError::OutOfBounds)?;
301 cs::evaluate(self, None, charstring_data, sink)
302 }
303
304 pub fn draw(
309 &self,
310 gid: GlyphId,
311 ppem: Option<f32>,
312 pen: &mut impl OutlinePen,
313 ) -> Result<Option<f32>, Error> {
314 let mut nop_filter = NopFilterSink::new(pen);
315 let transform = self.transform(ppem);
316 let mut transformer = TransformSink::new(&mut nop_filter, transform);
317 let width = self.evaluate_charstring(gid, &mut transformer)?;
318 Ok(width.map(|w| transform.transform_h_metric(w).to_f32().max(0.0)))
319 }
320}
321
322impl CharstringContext for Type1Font {
323 fn kind(&self) -> CharstringKind {
324 CharstringKind::Type1
325 }
326
327 fn seac_components(&self, base_code: i32, accent_code: i32) -> Result<[&[u8]; 2], Error> {
328 let decode = |code: i32| {
329 let name = PredefinedEncoding::Standard
330 .name(code.try_into().map_err(|_| Error::InvalidSeacCode(code))?);
331 self.charstrings
332 .index_for_name(name)
333 .and_then(|idx| self.charstrings.get(idx))
334 .ok_or(Error::InvalidSeacCode(code))
335 };
336 let base = decode(base_code)?;
337 let accent = decode(accent_code)?;
338 Ok([base, accent])
339 }
340
341 fn subr(&self, index: i32) -> Result<&[u8], Error> {
342 Ok(self.subrs.get(index as u32).ok_or(ReadError::OutOfBounds)?)
343 }
344
345 fn global_subr(&self, _index: i32) -> Result<&[u8], Error> {
346 Err(Error::MissingSubroutines)
348 }
349
350 fn weight_vector(&self) -> &[Fixed] {
351 &self.weight_vector
352 }
353}
354
355#[derive(Clone)]
357pub struct Encoding<'a> {
358 encoding: &'a RawEncoding,
359 charstrings: &'a Charstrings,
360}
361
362impl<'a> Encoding<'a> {
363 pub fn predefined(&self) -> Option<PredefinedEncoding> {
365 if let RawEncoding::Predefined(pre) = self.encoding {
366 Some(*pre)
367 } else {
368 None
369 }
370 }
371
372 pub fn glyph_name(&self, code: u8) -> Option<&'a str> {
374 match self.encoding {
375 RawEncoding::Predefined(pre) => Some(pre.name(code)),
376 RawEncoding::Custom(custom) => {
377 self.charstrings.name(custom.get(code as usize)?.to_u32())
378 }
379 }
380 }
381
382 pub fn map(&self, code: u8) -> Option<GlyphId> {
384 match self.encoding {
385 RawEncoding::Predefined(pre) => self
386 .charstrings
387 .index_for_name(pre.name(code))
388 .map(GlyphId::new),
389 RawEncoding::Custom(custom) => custom.get(code as usize).copied(),
390 }
391 }
392}
393
394struct RawDicts<'a> {
396 base: &'a [u8],
398 private: Vec<u8>,
400}
401
402impl<'a> RawDicts<'a> {
403 fn new(data: &'a [u8]) -> Option<Self> {
404 if let Some((PFB_TEXT_SEGMENT_TAG, base_size)) = decode_pfb_tag(data, 0) {
405 let data = data.get(6..)?;
407 verify_header(data)?;
408 let (base_dict, raw_private_dict) = data.split_at_checked(base_size as usize)?;
409 let private_dict = decrypt(
411 decode_pfb_binary_segments(raw_private_dict)
412 .flat_map(|segment| segment.iter().copied()),
413 EEXEC_SEED,
414 )
415 .skip(4)
417 .collect::<Vec<_>>();
418 Some(Self {
419 base: base_dict,
420 private: private_dict,
421 })
422 } else {
423 verify_header(data)?;
425 let start = find_eexec_data(data)?;
427 let (base_dict, raw_private_dict) = data.split_at_checked(start)?;
428 let private_dict = if raw_private_dict.len() > 3
429 && raw_private_dict[..4].iter().all(|b| b.is_ascii_hexdigit())
430 {
431 decrypt(decode_hex(raw_private_dict.iter().copied()), EEXEC_SEED)
433 .skip(4)
434 .collect::<Vec<_>>()
435 } else {
436 decrypt(raw_private_dict.iter().copied(), EEXEC_SEED)
438 .skip(4)
439 .collect::<Vec<_>>()
440 };
441 Some(Self {
442 base: base_dict,
443 private: private_dict,
444 })
445 }
446 }
447}
448
449fn verify_header(data: &[u8]) -> Option<()> {
450 (data.starts_with(b"%!PS-AdobeFont") || data.starts_with(b"%!FontType")).then_some(())
451}
452
453const PFB_TEXT_SEGMENT_TAG: u16 = 0x8001;
454const PFB_BINARY_SEGMENT_TAG: u16 = 0x8002;
455
456fn decode_pfb_tag(data: &[u8], start: usize) -> Option<(u16, u32)> {
460 let header: [u8; 6] = data.get(start..start + 6)?.try_into().ok()?;
461 let tag = ((header[0] as u16) << 8) | header[1] as u16;
462 if matches!(tag, PFB_BINARY_SEGMENT_TAG | PFB_TEXT_SEGMENT_TAG) {
463 let size = u32::from_le_bytes(header[2..].try_into().unwrap());
464 Some((tag, size))
465 } else {
466 None
467 }
468}
469
470fn decode_pfb_binary_segments(data: &[u8]) -> impl Iterator<Item = &[u8]> + '_ {
472 let mut pos = 0usize;
473 core::iter::from_fn(move || {
474 let (tag, len) = decode_pfb_tag(data, pos)?;
475 if tag != PFB_BINARY_SEGMENT_TAG {
478 return None;
479 }
480 let start = pos + 6;
482 let end = start + len as usize;
483 let segment = data.get(start..end)?;
484 pos = end;
485 Some(segment)
486 })
487}
488
489fn find_eexec_data(data: &[u8]) -> Option<usize> {
493 let mut parser = Parser::new(data);
496 while let Some(token) = parser.next() {
497 if token != Token::Raw(b"eexec") {
498 continue;
499 }
500 let mut start = parser.pos;
501 let mut linefeed_pos = None;
505 while start < data.len() {
506 match data[start] {
507 b' ' | b'\t' => {}
508 b'\n' => linefeed_pos = Some(start),
509 b'\r' => {
510 if *linefeed_pos.get_or_insert_with(|| {
513 data[start..]
514 .iter()
515 .position(|b| *b == b'\n')
516 .map(|pos| pos + start)
517 .unwrap_or(0)
518 }) < start
519 {
520 break;
521 }
522 }
523 _ => break,
524 }
525 start += 1;
526 }
527 if start == data.len() {
528 return None;
530 }
531 return Some(start);
532 }
533 None
534}
535
536fn decode_hex(mut bytes: impl Iterator<Item = u8>) -> impl Iterator<Item = u8> {
540 const DIGIT_TO_NUM: [i8; 128] = [
542 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
543 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
544 -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15,
545 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1,
546 -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
547 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
548 ];
549 let mut pad = 0x1_u32;
550 core::iter::from_fn(move || {
551 loop {
552 let Some(c) = bytes.next() else {
553 break;
554 };
555 if is_whitespace(c) {
556 continue;
557 }
558 if c >= 0x80 {
559 break;
560 }
561 let c = DIGIT_TO_NUM[(c & 0x7F) as usize] as u32;
562 if c >= 16 {
563 break;
564 }
565 pad = (pad << 4) | c;
566 if pad & 0x100 != 0 {
567 let res = pad as u8;
568 pad = 0x1;
569 return Some(res);
570 } else {
571 continue;
572 }
573 }
574 if pad != 0x1 {
575 let res = (pad << 4) as u8;
576 pad = 0x1;
577 return Some(res);
578 }
579 None
580 })
581}
582
583const EEXEC_SEED: u32 = 55665;
585
586const CHARSTRING_SEED: u32 = 4330;
588
589fn decrypt(bytes: impl Iterator<Item = u8>, mut seed: u32) -> impl Iterator<Item = u8> {
593 bytes.map(move |b| {
594 let b = b as u32;
595 let plain = b ^ (seed >> 8);
596 seed = b.wrapping_add(seed).wrapping_mul(52845).wrapping_add(22719) & 0xFFFF;
597 plain as u8
598 })
599}
600
601fn is_whitespace(c: u8) -> bool {
602 if c <= 32 {
603 return matches!(c, b' ' | b'\n' | b'\r' | b'\t' | b'\0' | 0x0C);
604 }
605 false
606}
607
608fn is_special(c: u8) -> bool {
612 matches!(
613 c,
614 b'(' | b')' | b'<' | b'>' | b'[' | b']' | b'{' | b'}' | b'/' | b'%'
615 )
616}
617
618fn is_special_or_whitespace(c: u8) -> bool {
619 is_special(c) || is_whitespace(c)
620}
621
622#[derive(Copy, Clone, PartialEq, Eq, Debug)]
623enum Token<'a> {
624 Int(i64),
626 LitString(&'a [u8]),
628 HexString(&'a [u8]),
630 Proc(&'a [u8]),
632 Binary(&'a [u8]),
634 Name(&'a [u8]),
636 Raw(&'a [u8]),
638}
639
640#[derive(Default)]
642struct Subrs {
643 data: Vec<u8>,
645 index: Vec<(u32, Range<usize>)>,
648 is_dense: bool,
651}
652
653impl Subrs {
654 fn get(&self, index: u32) -> Option<&[u8]> {
655 let entry_idx = if self.is_dense {
656 index as usize
657 } else {
658 self.index.binary_search_by_key(&index, |e| e.0).ok()?
659 };
660 self.data.get(self.index.get(entry_idx)?.1.clone())
661 }
662}
663
664struct CharstringEntry {
665 name: Range<usize>,
666 data: Range<usize>,
667}
668
669#[derive(Default)]
671struct Charstrings {
672 data: Vec<u8>,
674 names: Vec<u8>,
676 index: Vec<CharstringEntry>,
678 orig_notdef_index: Option<usize>,
681}
682
683impl Charstrings {
684 fn num_glyphs(&self) -> u32 {
685 self.index.len() as u32
686 }
687
688 fn get(&self, index: u32) -> Option<&[u8]> {
689 self.data.get(self.index.get(index as usize)?.data.clone())
690 }
691
692 fn name(&self, index: u32) -> Option<&str> {
693 core::str::from_utf8(
694 self.names
695 .get(self.index.get(index as usize)?.name.clone())?,
696 )
697 .ok()
698 }
699
700 fn index_for_name(&self, name: &str) -> Option<u32> {
701 let name = name.as_bytes();
702 for (idx, entry) in self.index.iter().enumerate() {
703 if self.names.get(entry.name.clone()) == Some(name) {
704 return Some(idx as u32);
705 }
706 }
707 None
708 }
709
710 fn push(&mut self, name: &[u8], data: &[u8], len_iv: i64) {
711 let start = self.data.len();
712 if len_iv >= 0 {
713 self.data
715 .extend(decrypt(data.iter().copied(), CHARSTRING_SEED).skip(len_iv as usize));
716 } else {
717 self.data.extend_from_slice(data);
719 }
720 let end = self.data.len();
721 let name_start = self.names.len();
722 self.names.extend_from_slice(name);
723 let name_end = self.names.len();
724 self.index.push(CharstringEntry {
725 name: name_start..name_end,
726 data: start..end,
727 });
728 }
729}
730
731#[derive(PartialEq, Debug)]
733enum RawEncoding {
734 Predefined(PredefinedEncoding),
735 Custom(Vec<GlyphId>),
736}
737
738const NOTDEF_GLYPH: &[u8] = &[0x8B, 0xF7, 0xE1, 0x0D, 0x0E];
744
745#[derive(Clone)]
746struct Parser<'a> {
747 data: &'a [u8],
748 pos: usize,
749}
750
751impl<'a> Parser<'a> {
752 fn new(data: &'a [u8]) -> Self {
753 Self { data, pos: 0 }
754 }
755
756 fn next(&mut self) -> Option<Token<'a>> {
757 loop {
760 self.skip_whitespace()?;
761 let start = self.pos;
762 let c = self.next_byte()?;
763 match c {
764 b'%' => self.skip_line(),
766 b'{' => return self.read_proc(start),
768 b'(' => return self.read_lit_string(start),
770 b'<' => {
771 if self.peek_byte() == Some(b'<') {
772 self.pos += 1;
774 continue;
775 }
776 return self.read_hex_string(start);
778 }
779 b'>' => {
780 if self.next_byte()? != b'>' {
783 return None;
784 }
785 }
786 b'/' => {
788 if let Some(c) = self.peek_byte() {
789 if is_whitespace(c) || is_special(c) {
790 if !is_special(c) {
791 self.pos += 1;
792 }
793 return Some(Token::Name(&[]));
794 } else {
795 let count = self.skip_until(|c| is_whitespace(c) || is_special(c));
796 return self.data.get(start + 1..start + count).map(Token::Name);
797 }
798 }
799 }
800 b'[' | b']' => {
802 let data = self.data.get(start..start + 1)?;
803 return Some(Token::Raw(data));
804 }
805 _ => {
806 let count = self.skip_until(is_special_or_whitespace);
807 let content = self.data.get(start..start + count)?;
808 if (c.is_ascii_digit() || c == b'-') && !content.contains(&b'.') {
812 if let Some(int) = decode_int(content) {
813 if matches!(
820 self.peek(),
821 Some(Token::Raw(b"RD")) | Some(Token::Raw(b"-|"))
822 ) {
823 self.next();
825 self.pos += 1;
827 let data = self.read_bytes(int as usize)?;
829 return Some(Token::Binary(data));
833 }
834 return Some(Token::Int(int));
835 }
836 }
837 return Some(Token::Raw(content));
838 }
839 }
840 }
841 }
842
843 fn peek(&self) -> Option<Token<'a>> {
844 self.clone().next()
845 }
846
847 fn accept(&mut self, token: Token) -> bool {
848 if self.peek() == Some(token) {
849 self.next();
850 true
851 } else {
852 false
853 }
854 }
855
856 fn expect(&mut self, token: Token) -> Option<()> {
857 (self.next()? == token).then_some(())
858 }
859
860 fn next_byte(&mut self) -> Option<u8> {
861 let byte = self.peek_byte()?;
862 self.pos += 1;
863 Some(byte)
864 }
865
866 fn peek_byte(&self) -> Option<u8> {
867 self.data.get(self.pos).copied()
868 }
869
870 fn read_bytes(&mut self, len: usize) -> Option<&'a [u8]> {
871 let end = self.pos.checked_add(len)?;
872 let content = self.data.get(self.pos..end)?;
873 self.pos = end;
874 Some(content)
875 }
876
877 fn skip_whitespace(&mut self) -> Option<()> {
878 while is_whitespace(*self.data.get(self.pos)?) {
879 self.pos += 1;
880 }
881 Some(())
882 }
883
884 fn skip_line(&mut self) {
885 while let Some(c) = self.next_byte() {
886 if c == b'\n' || c == b'\r' {
887 break;
888 }
889 }
890 }
891
892 fn skip_until(&mut self, f: impl Fn(u8) -> bool) -> usize {
893 let mut count = 0;
894 while let Some(byte) = self.peek_byte() {
895 if f(byte) {
896 break;
897 }
898 self.pos += 1;
899 count += 1;
900 }
901 count + 1
902 }
903
904 fn read_proc(&mut self, start: usize) -> Option<Token<'a>> {
905 while self.next_byte()? != b'}' {
906 self.next()?;
908 self.skip_whitespace();
909 }
910 let end = self.pos;
911 if self.data.get(end - 1) != Some(&b'}') {
912 return None;
914 }
915 Some(Token::Proc(self.data.get(start + 1..end - 1)?))
916 }
917
918 fn read_lit_string(&mut self, start: usize) -> Option<Token<'a>> {
919 let mut nest_depth = 1;
920 while let Some(c) = self.next_byte() {
921 match c {
922 b'(' => nest_depth += 1,
923 b')' => {
924 nest_depth -= 1;
925 if nest_depth == 0 {
926 break;
927 }
928 }
929 b'\\' => {
931 self.next_byte()?;
934 }
935 _ => {}
936 }
937 }
938 if nest_depth != 0 {
939 return None;
941 }
942 let end = self.pos;
943 self.pos += 1;
944 Some(Token::LitString(self.data.get(start + 1..end - 1)?))
945 }
946
947 fn read_hex_string(&mut self, start: usize) -> Option<Token<'a>> {
948 while let Some(c) = self.next_byte() {
949 if !is_whitespace(c) && !c.is_ascii_hexdigit() {
950 break;
951 }
952 }
953 let end = self.pos;
954 if self.data.get(end - 1) != Some(&b'>') {
955 return None;
957 }
958 Some(Token::HexString(self.data.get(start + 1..end - 1)?))
959 }
960
961 fn read_int(&mut self) -> Option<i64> {
962 self.next().and_then(|t| match t {
963 Token::Int(n) => Some(n),
964 _ => None,
965 })
966 }
967
968 fn read_num_as_int(&mut self) -> Option<i32> {
969 match self.next()? {
970 Token::Int(n) => Some(n as i32),
971 Token::Raw(bytes) => decode_int_prefix(bytes, 0).map(|n| n.0 as i32),
975 _ => None,
976 }
977 }
978
979 fn read_string(&mut self) -> Option<String> {
980 use alloc::borrow::ToOwned;
981 let bytes = match self.next()? {
982 Token::Name(bytes) | Token::LitString(bytes) => bytes,
985 _ => return None,
986 };
987 core::str::from_utf8(bytes).ok().map(|s| s.to_owned())
988 }
989}
990
991impl Parser<'_> {
992 fn read_font_matrix(&mut self) -> Option<ScaledFontMatrix> {
1000 let mut components = [Fixed::ZERO; 6];
1001 if !self.accept(Token::Raw(b"[")) {
1003 self.expect(Token::Raw(b"{"))?;
1004 }
1005 for component in &mut components {
1007 *component = match self.next()? {
1008 Token::Int(int) => Fixed::from_i32((int as i32).checked_mul(1000)?),
1009 Token::Raw(bytes) => decode_fixed(bytes, 3)?,
1010 _ => return None,
1011 }
1012 }
1013 self.next()?;
1015 let temp_scale = components[3].abs();
1016 if temp_scale == Fixed::ZERO {
1017 return None;
1018 }
1019 let mut upem = 1000;
1020 if temp_scale != Fixed::ONE {
1021 upem = (Fixed::from_bits(1000) / temp_scale).to_bits();
1022 components[0] /= temp_scale;
1023 components[1] /= temp_scale;
1024 components[2] /= temp_scale;
1025 components[4] /= temp_scale;
1027 components[5] /= temp_scale;
1028 if components[3] < Fixed::ZERO {
1029 components[3] = -Fixed::ONE;
1030 } else {
1031 components[3] = Fixed::ONE;
1032 }
1033 }
1034 for offset in components.iter_mut().skip(4) {
1036 *offset = Fixed::from_bits(offset.to_bits() >> 16);
1037 }
1038 let matrix = FontMatrix::from_elements(components);
1039 if transform::is_degenerate(&matrix) {
1040 return None;
1041 }
1042 Some(ScaledFontMatrix {
1043 matrix,
1044 scale: upem,
1045 })
1046 }
1047
1048 fn read_subrs(&mut self, len_iv: i64) -> Option<Subrs> {
1055 let mut subrs = Subrs::default();
1056 let _: usize = match self.next()? {
1057 Token::Raw(b"[") => {
1058 self.expect(Token::Raw(b"]"))?;
1060 return Some(subrs);
1061 }
1062 Token::Int(n) => n.try_into().ok()?,
1063 _ => return None,
1064 };
1065 self.expect(Token::Raw(b"array"))?;
1066 let mut is_dense = true;
1067 while self.accept(Token::Raw(b"dup")) {
1069 let (Token::Int(n), Token::Binary(data)) = (self.next()?, self.next()?) else {
1070 return None;
1071 };
1072 self.next();
1075 self.accept(Token::Raw(b"put"));
1077 let subr_num: u32 = n.try_into().ok()?;
1078 if subr_num as usize != subrs.index.len() {
1079 is_dense = false;
1080 }
1081 let start = subrs.data.len();
1082 if len_iv >= 0 {
1083 subrs
1085 .data
1086 .extend(decrypt(data.iter().copied(), CHARSTRING_SEED).skip(len_iv as usize));
1087 } else {
1088 subrs.data.extend_from_slice(data);
1090 }
1091 let end = subrs.data.len();
1092 subrs.index.push((subr_num, start..end));
1093 }
1094 if !is_dense {
1096 subrs.index.sort_unstable_by_key(|(n, ..)| *n);
1097 }
1098 subrs.is_dense = is_dense;
1099 subrs.data.shrink_to_fit();
1100 subrs.index.shrink_to_fit();
1101 Some(subrs)
1102 }
1103
1104 fn read_charstrings(&mut self, len_iv: i64) -> Option<Charstrings> {
1111 let mut charstrings = Charstrings::default();
1112 let _: usize = match self.next()? {
1113 Token::Int(n) => n.try_into().ok()?,
1114 _ => return None,
1115 };
1116 let mut notdef_idx = None;
1117 while let Some(token) = self.next() {
1118 let name = match token {
1119 Token::Raw(b"end") => {
1124 if self
1125 .peek_byte()
1126 .map(is_special_or_whitespace)
1127 .unwrap_or_default()
1128 {
1129 break;
1130 } else {
1131 continue;
1132 }
1133 }
1134 Token::Raw(b"def") => {
1135 if self
1137 .peek_byte()
1138 .map(is_special_or_whitespace)
1139 .unwrap_or_default()
1140 && !charstrings.index.is_empty()
1141 {
1142 break;
1143 } else {
1144 continue;
1145 }
1146 }
1147 Token::Name(name) => name,
1148 _ => continue,
1149 };
1150 if name == b".notdef" {
1151 notdef_idx = Some(charstrings.index.len());
1152 }
1153 let Token::Binary(data) = self.next()? else {
1154 return None;
1155 };
1156 charstrings.push(name, data, len_iv);
1157 }
1158 match notdef_idx {
1159 Some(0) => {
1160 }
1162 Some(idx) => {
1163 charstrings.index.swap(0, idx);
1166 charstrings.orig_notdef_index = Some(idx);
1167 }
1168 None => {
1169 let idx = charstrings.index.len();
1172 charstrings.push(b".notdef", NOTDEF_GLYPH, -1);
1173 charstrings.index.swap(0, idx);
1174 charstrings.orig_notdef_index = Some(idx);
1175 }
1176 }
1177 charstrings.data.shrink_to_fit();
1178 charstrings.names.shrink_to_fit();
1179 charstrings.index.shrink_to_fit();
1180 Some(charstrings)
1181 }
1182
1183 fn read_font_bbox(&mut self) -> Option<[Fixed; 4]> {
1184 let mut bbox = [Fixed::ZERO; 4];
1185 let mut parser;
1189 let parser = if self.accept(Token::Raw(b"[")) {
1190 self
1191 } else if let Token::Proc(proc) = self.next()? {
1192 parser = Parser::new(proc);
1193 &mut parser
1194 } else {
1195 return None;
1196 };
1197 for component in &mut bbox {
1199 *component = match parser.next()? {
1200 Token::Int(int) => Fixed::from_i32(int as i32),
1201 Token::Raw(bytes) => decode_fixed(bytes, 0)?,
1202 _ => return None,
1203 }
1204 }
1205 Some(bbox)
1206 }
1207
1208 fn read_weight_vector(&mut self) -> Option<Vec<Fixed>> {
1209 self.accept(Token::Raw(b"["));
1210 let mut weights = Vec::new();
1211 while let Some(token) = self.next() {
1212 match token {
1213 Token::Raw(b"]") => break,
1214 Token::Int(val) => weights.push(Fixed::from_i32(val as _)),
1215 Token::Raw(raw) => weights.push(decode_fixed(raw, 0)?),
1216 _ => return None,
1217 }
1218 }
1219 Some(weights)
1220 }
1221
1222 fn read_encoding(&mut self, charstrings: &Charstrings) -> Option<RawEncoding> {
1226 match self.next()? {
1227 Token::Raw(b"[") => {
1229 let mut map = Vec::new();
1230 map.resize(256, GlyphId::NOTDEF);
1232 self.read_dense_encoding(|idx, name| {
1233 if let Some((slot, gid)) = map
1234 .get_mut(idx as usize)
1235 .zip(charstrings.index_for_name(name))
1236 {
1237 *slot = gid.into();
1238 }
1239 });
1240 Some(RawEncoding::Custom(map))
1241 }
1242 Token::Int(count) => {
1244 let count: usize = count.clamp(0, 256) as usize;
1247 let mut map = Vec::new();
1248 map.resize(count, GlyphId::NOTDEF);
1250 self.read_sparse_encoding(|idx, name| {
1251 if let Some((slot, gid)) = map
1252 .get_mut(idx as usize)
1253 .zip(charstrings.index_for_name(name))
1254 {
1255 *slot = gid.into();
1256 }
1257 });
1258 Some(RawEncoding::Custom(map))
1259 }
1260 Token::Raw(b"StandardEncoding") => {
1261 Some(RawEncoding::Predefined(PredefinedEncoding::Standard))
1262 }
1263 Token::Raw(b"ExpertEncoding") => {
1264 Some(RawEncoding::Predefined(PredefinedEncoding::Expert))
1265 }
1266 Token::Raw(b"ISOLatin1Encoding") => {
1267 Some(RawEncoding::Predefined(PredefinedEncoding::IsoLatin1))
1268 }
1269 _ => None,
1270 }
1271 }
1272
1273 fn read_dense_encoding(&mut self, mut f: impl FnMut(i64, &str)) -> Option<()> {
1277 self.accept(Token::Raw(b"["));
1279 let mut idx = 0;
1282 while let Some(token) = self.next() {
1283 match token {
1284 Token::Raw(b"]") => break,
1285 Token::Name(name) => {
1286 let code = idx;
1287 idx += 1;
1288 let Ok(name) = core::str::from_utf8(name) else {
1289 continue;
1290 };
1291 f(code, name);
1292 }
1293 _ => {
1294 return None;
1296 }
1297 }
1298 }
1299 Some(())
1300 }
1301
1302 fn read_sparse_encoding(&mut self, mut f: impl FnMut(i64, &str)) -> Option<()> {
1305 while let Some(token) = self.next() {
1306 match token {
1307 Token::Raw(b"def") => break,
1309 Token::Int(code) => {
1310 let Some(Token::Name(name)) = self.next() else {
1312 continue;
1313 };
1314 let Ok(name) = core::str::from_utf8(name) else {
1315 continue;
1316 };
1317 f(code, name);
1318 }
1319 _ => {}
1320 }
1321 }
1322 Some(())
1323 }
1324}
1325
1326fn decode_int(bytes: &[u8]) -> Option<i64> {
1330 let s = std::str::from_utf8(bytes).ok()?;
1331 if let Some(hash_idx) = s.find('#') {
1332 if hash_idx == 1 || hash_idx == 2 {
1333 let radix_str = s.get(0..hash_idx)?;
1335 let number_str = s.get(hash_idx + 1..)?;
1336 let radix = radix_str
1337 .parse::<u32>()
1338 .ok()
1339 .filter(|n| (2..=36).contains(n))?;
1340 i64::from_str_radix(number_str, radix).ok()
1341 } else {
1342 s.parse::<i64>().ok()
1343 }
1344 } else {
1345 s.parse::<i64>().ok()
1346 }
1347}
1348
1349fn decode_int_prefix(bytes: &[u8], start: usize) -> Option<(i64, usize)> {
1352 let tail = bytes.get(start..)?;
1353 let end = tail
1354 .iter()
1355 .position(|c| *c != b'-' && !c.is_ascii_digit())
1356 .unwrap_or(tail.len());
1357 let int = decode_int(tail.get(..end)?)?;
1358 Some((int, start + end))
1359}
1360
1361fn decode_fixed(bytes: &[u8], mut power_ten: i32) -> Option<Fixed> {
1366 const LIMIT: i32 = 0xCCCCCCC;
1367 let mut idx = 0;
1368 let &first = bytes.get(idx)?;
1369 let sign = if first == b'-' || first == b'+' {
1370 idx += 1;
1371 if first == b'-' {
1372 -1
1373 } else {
1374 1
1375 }
1376 } else {
1377 1
1378 };
1379 let overflow = || Some(Fixed::from_bits(0x7FFFFFFF * sign));
1380 let mut integral = 0;
1381 if *bytes.get(idx)? != b'.' {
1382 let (int, end_idx) = decode_int_prefix(bytes, idx)?;
1383 if int > 0x7FFF {
1384 return overflow();
1385 }
1386 integral = (int << 16) as i32;
1387 idx = end_idx;
1388 }
1389 let mut decimal = 0;
1390 let mut divider = 1;
1391 if bytes.get(idx) == Some(&b'.') {
1392 idx += 1;
1393 while let Some(byte) = bytes.get(idx).copied() {
1394 if !byte.is_ascii_digit() {
1395 break;
1396 }
1397 let digit = (byte - b'0') as i32;
1398 if divider < LIMIT && decimal < LIMIT {
1399 decimal = decimal * 10 + digit;
1400 if integral == 0 && power_ten > 0 {
1401 power_ten -= 1;
1402 } else {
1403 divider *= 10;
1404 }
1405 }
1406 idx += 1;
1407 }
1408 }
1409 if bytes.get(idx).map(|b| b.to_ascii_lowercase()) == Some(b'e') {
1410 idx += 1;
1411 let (exponent, _) = decode_int_prefix(bytes, idx)?;
1412 if exponent > 1000 {
1413 return overflow();
1414 } else if exponent < -1000 {
1415 return Some(Fixed::ZERO);
1417 } else {
1418 power_ten = power_ten.checked_add(exponent as i32)?;
1419 }
1420 }
1421 if integral == 0 && decimal == 0 {
1422 return Some(Fixed::ZERO);
1423 }
1424 while power_ten > 0 {
1425 if integral >= LIMIT {
1426 return overflow();
1427 }
1428 integral *= 10;
1429 if decimal >= LIMIT {
1430 if divider == 1 {
1431 return overflow();
1432 }
1433 divider /= 10;
1434 } else {
1435 decimal *= 10;
1436 }
1437 power_ten -= 1;
1438 }
1439 while power_ten < 0 {
1440 integral /= 10;
1441 if divider < LIMIT {
1442 divider *= 10;
1443 } else {
1444 decimal /= 10;
1445 }
1446 if integral == 0 && decimal == 0 {
1447 return Some(Fixed::ZERO);
1448 }
1449 power_ten += 1;
1450 }
1451 if decimal != 0 {
1452 decimal = (Fixed::from_bits(decimal) / Fixed::from_bits(divider)).to_bits();
1453 integral += decimal;
1454 }
1455 Some(Fixed::from_bits(integral * sign))
1456}
1457
1458#[cfg(test)]
1459mod tests {
1460 use super::*;
1461 use cs::test_helpers::*;
1462
1463 #[test]
1464 fn pfb_tags() {
1465 let data = [0x80, 0x01, 0x01, 0x02, 0x00, 0x00];
1467 let (tag, len) = decode_pfb_tag(&data, 0).unwrap();
1468 assert_eq!(tag, PFB_TEXT_SEGMENT_TAG);
1469 assert_eq!(len, 513);
1470 let data = [0x80, 0x02, 0x01, 0x03, 0x00, 0x00];
1472 let (tag, len) = decode_pfb_tag(&data, 0).unwrap();
1473 assert_eq!(tag, PFB_BINARY_SEGMENT_TAG);
1474 assert_eq!(len, 769);
1475 let data = [0x00; 6];
1477 assert!(decode_pfb_tag(&data, 0).is_none());
1478 let data = [0x00; 5];
1480 assert!(decode_pfb_tag(&data, 0).is_none());
1481 }
1482
1483 #[test]
1484 fn pfb_segments() {
1485 let segments = [
1486 vec![0x01; 8],
1487 vec![0x02; 10],
1488 vec![0x03; 4],
1489 vec![0x04; 255],
1490 ];
1491 let mut buf = vec![];
1493 for segment in &segments {
1494 buf.push(0x80);
1495 buf.push(0x02);
1496 buf.push(segment.len() as u8);
1497 buf.extend_from_slice(&[0; 3]);
1498 for byte in segment {
1499 buf.push(*byte);
1500 }
1501 }
1502 let mut parsed_count = 0;
1504 for (parsed, expected) in decode_pfb_binary_segments(&buf).zip(&segments) {
1505 assert_eq!(parsed, expected);
1506 parsed_count += 1;
1507 }
1508 assert_eq!(parsed_count, segments.len());
1509 }
1510
1511 #[test]
1512 fn hex_decode() {
1513 check_hex_decode(
1514 b"743F8413F3636CA85A9FFEFB50B4BB27",
1515 &[
1516 116, 63, 132, 19, 243, 99, 108, 168, 90, 159, 254, 251, 80, 180, 187, 39,
1517 ],
1518 );
1519 }
1520
1521 #[test]
1522 fn hex_decode_ignores_whitespace() {
1523 check_hex_decode(
1524 b"743F 8413F3636C\nA85A9FFEF\tB50B 4BB27",
1525 &[
1526 116, 63, 132, 19, 243, 99, 108, 168, 90, 159, 254, 251, 80, 180, 187, 39,
1527 ],
1528 );
1529 }
1530
1531 #[test]
1532 fn hex_decode_truncate() {
1533 check_hex_decode(b"743F.8413F3636CA85A9FFEFB50B4BB27", &[116, 63]);
1534 }
1535
1536 #[test]
1537 fn hex_decode_odd_chars() {
1538 check_hex_decode(b"743", &[116, 48]);
1539 }
1540
1541 #[track_caller]
1542 fn check_hex_decode(hex: &[u8], expected: &[u8]) {
1543 let decoded = decode_hex(hex.iter().copied()).collect::<Vec<_>>();
1544 assert_eq!(decoded, expected);
1545 }
1546
1547 #[test]
1548 fn decrypt_bytes() {
1549 let cipher = [
1550 0x74, 0x3f, 0x84, 0x13, 0xf3, 0x63, 0x6c, 0xa8, 0x5a, 0x9f, 0xfe, 0xfb, 0x50, 0xb4,
1551 0xbb, 0x27,
1552 ];
1553 let plain = decrypt(cipher.iter().copied(), EEXEC_SEED).collect::<Vec<_>>();
1554 assert_eq!(&plain[4..], b"dup\n/Private");
1556 }
1557
1558 #[test]
1559 fn find_eexec() {
1560 assert_eq!(
1562 find_eexec_data(b"dup\n/Private\ncurrentfile eexec *&&FW"),
1563 Some(31)
1564 );
1565 assert_eq!(
1567 find_eexec_data(b"dup\n/Private\ncurrentfile eexec *&&FW"),
1568 Some(35)
1569 );
1570 assert_eq!(
1572 find_eexec_data(b"dup\n/Private\ncurrentfile eexec\n\n*&&FW"),
1573 Some(32)
1574 );
1575 assert_eq!(
1577 find_eexec_data(b"dup\n/Private\ncurrentfile eexec\r\n\r*&&FW"),
1578 Some(32)
1579 );
1580 assert_eq!(
1582 find_eexec_data(b"% eexec in comment\n(eexec in string) currentfile eexec $$$$"),
1583 Some(55)
1584 );
1585 assert!(find_eexec_data(b"% eexec in comment\n(eexec in string) currentfile").is_none());
1587 }
1588
1589 #[test]
1590 fn read_pfb_raw_dicts() {
1591 let dicts = RawDicts::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFB).unwrap();
1592 check_noto_serif_base(dicts.base);
1593 check_noto_serif_private(&dicts.private);
1594 }
1595
1596 #[test]
1597 fn read_pfa_raw_dicts() {
1598 let dicts = RawDicts::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
1599 check_noto_serif_base(dicts.base);
1600 check_noto_serif_private(&dicts.private);
1601 }
1602
1603 fn check_noto_serif_base(base: &[u8]) {
1604 const EXPECTED_PREFIX: &str = r#"%!PS-AdobeFont-1.0: NotoSerif-Regular 2.007; ttfautohint (v1.8) -l 8 -r 50 -G 200 -x 14 -D latn -f none -a qsq -X ""
1605%%Title: NotoSerif-Regular
1606%Version: 2.007; ttfautohint (v1.8) -l 8 -r 50 -G 200 -x 14 -D latn -f none -a qsq -X ""
1607%%CreationDate: Tue Feb 10 16:07:25 2026
1608%%Creator: www-data
1609%Copyright: Copyright 2015-2021 Google LLC. All Rights Reserved.
1610% Generated by FontForge 20190801 (http://fontforge.sf.net/)
1611%%EndComments
1612
161310 dict begin
1614/FontType 1 def
1615/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
1616/FontName /NotoSerif-Regular def
1617/FontBBox {5 0 989 775 }readonly def
1618"#;
1619 assert!(base.starts_with(EXPECTED_PREFIX.as_bytes()));
1620 }
1621
1622 fn check_noto_serif_private(private: &[u8]) {
1623 const EXPECTED_PREFIX: &str = r#"dup
1624/Private 8 dict dup begin
1625/RD{string currentfile exch readstring pop}executeonly def
1626/ND{noaccess def}executeonly def
1627/NP{noaccess put}executeonly def
1628/MinFeature{16 16}ND
1629/password 5839 def
1630/BlueValues [0 0 536 536 714 714 770 770 ]ND
1631/OtherSubrs"#;
1632 assert!(private.starts_with(EXPECTED_PREFIX.as_bytes()))
1633 }
1634
1635 #[test]
1636 fn parse_ints() {
1637 check_tokens(
1638 "% a comment\n20 -30 2#1011 10#-5 %another!\r 16#fC",
1639 &[
1640 Token::Int(20),
1641 Token::Int(-30),
1642 Token::Int(11),
1643 Token::Int(-5),
1644 Token::Int(252),
1645 ],
1646 );
1647 }
1648
1649 #[test]
1650 fn parse_num_to_int() {
1651 let mut parser =
1652 Parser::new(b"102 102.1 102.4 102.5 102.9 -102.1 -102.5 -102.9 8#146 16#66");
1653 for _ in 0..10 {
1654 assert_eq!(parser.read_num_as_int().unwrap().abs(), 102);
1655 }
1656 assert!(parser.next().is_none());
1657 }
1658
1659 #[test]
1660 fn parse_strings() {
1661 check_tokens(
1662 "(string (nested) 1) % and a hex string:\n <DEAD BEEF>",
1663 &[
1664 Token::LitString(b"string (nested) 1"),
1665 Token::HexString(b"DEAD BEEF"),
1666 ],
1667 );
1668 }
1669
1670 #[test]
1671 fn parse_unterminated_strings() {
1672 check_tokens("(string (nested) 1", &[]);
1673 check_tokens("<DEAD BEEF", &[]);
1674 }
1675
1676 #[test]
1677 fn parse_procs() {
1678 check_tokens(
1679 "{a {nested 20} proc } % and a\n {simple proc}",
1680 &[
1681 Token::Proc(b"a {nested 20} proc "),
1682 Token::Proc(b"simple proc"),
1683 ],
1684 );
1685 }
1686
1687 #[test]
1688 fn parse_unterminated_procs() {
1689 check_tokens("{a {nested 20} proc", &[]);
1690 }
1691
1692 #[test]
1693 fn parse_names() {
1694 check_tokens(
1695 "/FontMatrix\r %comment\n /CharStrings",
1696 &[Token::Name(b"FontMatrix"), Token::Name(b"CharStrings")],
1697 );
1698 }
1699
1700 #[test]
1701 fn parse_binary_blobs() {
1702 check_tokens(
1703 "/.notdef 4 RD abcd \n5 11\n \t-| a83jnshf7 3 ",
1704 &[
1705 Token::Name(b".notdef"),
1707 Token::Binary(b"abcd"),
1708 Token::Int(5),
1710 Token::Binary(b"a83jnshf7 3"),
1711 ],
1712 )
1713 }
1714
1715 #[test]
1716 fn parse_base_dict_prefix() {
1717 let dicts = RawDicts::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
1718 let ts = parse_to_tokens(dicts.base);
1719 assert_eq!(
1720 &ts[..19],
1721 &[
1722 Token::Int(10),
1723 Token::Raw(b"dict"),
1724 Token::Raw(b"begin"),
1725 Token::Name(b"FontType"),
1726 Token::Int(1),
1727 Token::Raw(b"def"),
1728 Token::Name(b"FontMatrix"),
1729 Token::Raw(b"["),
1730 Token::Raw(b"0.001"),
1731 Token::Int(0),
1732 Token::Int(0),
1733 Token::Raw(b"0.001"),
1734 Token::Int(0),
1735 Token::Int(0),
1736 Token::Raw(b"]"),
1737 Token::Raw(b"readonly"),
1738 Token::Raw(b"def"),
1739 Token::Name(b"FontName"),
1740 Token::Name(b"NotoSerif-Regular"),
1741 ]
1742 );
1743 }
1744
1745 #[track_caller]
1746 fn check_tokens(source: &str, expected: &[Token]) {
1747 let ts = parse_to_tokens(source.as_bytes());
1748 assert_eq!(ts, expected);
1749 }
1750
1751 fn parse_to_tokens(data: &'_ [u8]) -> Vec<Token<'_>> {
1752 let mut tokens = vec![];
1753 let mut parser = Parser::new(data);
1754 while let Some(token) = parser.next() {
1755 tokens.push(token);
1756 }
1757 tokens
1758 }
1759
1760 #[test]
1761 fn parse_fixed() {
1762 assert_eq!(decode_fixed(b"42.5", 0).unwrap(), Fixed::from_f64(42.5));
1764 assert_eq!(
1765 decode_fixed(b"0.0015", 0).unwrap(),
1766 Fixed::from_f64(0.001495361328125)
1767 );
1768 assert_eq!(
1769 decode_fixed(b"425.000e-1", 0).unwrap(),
1770 Fixed::from_f64(42.5)
1771 );
1772 assert_eq!(
1773 decode_fixed(b"1.5e-3", 0).unwrap(),
1774 Fixed::from_f64(0.001495361328125)
1775 );
1776 assert_eq!(decode_fixed(b"1.5", 3).unwrap(), Fixed::from_f64(1500.0));
1778 assert_eq!(decode_fixed(b"0.001", 3).unwrap(), Fixed::from_f64(1.0));
1779 assert_eq!(
1780 decode_fixed(b"15000e-4", 3).unwrap(),
1781 Fixed::from_f64(1500.0)
1782 );
1783 assert_eq!(decode_fixed(b"1.000e-3", 3).unwrap(), Fixed::from_f64(1.0));
1784 }
1785
1786 #[test]
1787 fn parse_font_matrix() {
1788 assert_eq!(
1790 Parser::new(b"[0.001 0 0 0.001 0 0]")
1791 .read_font_matrix()
1792 .unwrap()
1793 .matrix,
1794 FontMatrix::IDENTITY,
1795 );
1796 assert_eq!(
1799 Parser::new(b"[0.002 0 0 0.001 1 2e1]")
1800 .read_font_matrix()
1801 .unwrap()
1802 .matrix,
1803 FontMatrix::from_elements([
1804 Fixed::from_i32(2),
1805 Fixed::ZERO,
1806 Fixed::ZERO,
1807 Fixed::ONE,
1808 Fixed::from_bits(1000),
1809 Fixed::from_bits(20000)
1810 ])
1811 );
1812 assert_eq!(
1814 Parser::new(b"[0.001 0 0 0.0005 0.0 0.0]")
1815 .read_font_matrix()
1816 .unwrap(),
1817 ScaledFontMatrix {
1818 matrix: FontMatrix::from_elements([
1819 Fixed::from_i32(2),
1820 Fixed::ZERO,
1821 Fixed::ZERO,
1822 Fixed::ONE,
1823 Fixed::from_i32(0),
1824 Fixed::from_i32(0)
1825 ]),
1826 scale: 2000,
1827 }
1828 );
1829 }
1830
1831 #[test]
1832 fn parse_subrs() {
1833 let dicts = RawDicts::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
1834 let mut parser = Parser::new(&dicts.private);
1835 let mut subrs = None;
1836 while let Some(token) = parser.next() {
1837 if let Token::Name(b"Subrs") = token {
1838 subrs = parser.read_subrs(4);
1839 break;
1840 }
1841 }
1842 let mut subrs = subrs.unwrap();
1843 let expected_subrs: [&[u8]; 5] = [
1845 &[142, 139, 12, 16, 12, 17, 12, 17, 12, 33, 11],
1846 &[139, 140, 12, 16, 11],
1847 &[139, 141, 12, 16, 11],
1848 &[11],
1849 &[140, 142, 12, 16, 12, 17, 10, 11],
1850 ];
1851 assert_eq!(subrs.index.len(), expected_subrs.len());
1852 assert!(subrs.is_dense);
1853 for is_dense in [true, false] {
1856 subrs.is_dense = is_dense;
1857 for (idx, &expected) in expected_subrs.iter().enumerate() {
1858 let subr = subrs.get(idx as u32).unwrap();
1859 assert_eq!(subr, expected);
1860 }
1861 }
1862 }
1863
1864 #[test]
1865 fn parse_empty_array_subrs() {
1866 let subrs = Parser::new(b"[ ]").read_subrs(4).unwrap();
1867 assert!(subrs.data.is_empty());
1868 assert!(subrs.index.is_empty());
1869 }
1870
1871 #[test]
1872 fn parse_empty_subrs() {
1873 let subrs = Parser::new(b" 0 array\nND\n").read_subrs(4).unwrap();
1874 assert!(subrs.data.is_empty());
1875 assert!(subrs.index.is_empty());
1876 }
1877
1878 #[test]
1879 fn parse_malformed_subrs() {
1880 assert!(Parser::new(b" 20 \nND\n").read_subrs(4).is_none());
1881 }
1882
1883 #[test]
1884 fn parse_subrs_duplicate_def() {
1885 let private = b"/Subrs 2 array dup 5 2 RD nd NP dup 42 2 RD ab NP ND\n/Subrs 1 array dup 0 2 RD xy NP ND /CharStrings 0";
1888 let font = Type1Font::from_dicts(b"", private).unwrap();
1889 assert_eq!(font.subrs.index.len(), 2);
1890 assert_eq!(font.subrs.index[0].0, 5);
1891 assert_eq!(font.subrs.index[1].0, 42);
1892 }
1893
1894 #[test]
1895 fn parse_charstrings() {
1896 let dicts = RawDicts::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
1897 let mut parser = Parser::new(&dicts.private);
1898 let mut charstrings = None;
1899 while let Some(token) = parser.next() {
1900 if let Token::Name(b"CharStrings") = token {
1901 charstrings = parser.read_charstrings(4);
1902 break;
1903 }
1904 }
1905 let charstrings = charstrings.unwrap();
1906 assert_eq!(charstrings.num_glyphs(), 9);
1907 assert!(charstrings.orig_notdef_index.is_none());
1908 let expected_names = [
1909 ".notdef",
1910 "H",
1911 "f",
1912 "i",
1913 "x",
1914 "f_f.liga",
1915 "f_f_i.liga",
1916 "f_i.liga",
1917 "H.c2sc",
1918 ];
1919 let names = (0..charstrings.num_glyphs())
1920 .map(|idx| charstrings.name(idx).unwrap())
1921 .collect::<Vec<_>>();
1922 assert_eq!(names, expected_names);
1923 let expected_charstrings_prefix: [&[u8]; 9] = [
1925 &[139, 248, 236, 13, 14],
1926 &[177, 249, 173, 13, 139, 4, 247, 183],
1927 &[166, 248, 5, 13, 139, 4, 247, 201],
1928 &[162, 247, 212, 13, 247, 30, 249, 16],
1929 &[144, 248, 214, 13, 139, 4, 247, 130],
1930 &[166, 249, 88, 13, 139, 4, 247, 181],
1931 &[166, 250, 126, 13, 139, 4, 247, 181],
1932 &[166, 249, 43, 13, 139, 4, 247, 181],
1933 &[180, 249, 60, 13, 139, 4, 247, 141],
1934 ];
1935 for (idx, &expected) in expected_charstrings_prefix.iter().enumerate() {
1936 let charstring = charstrings.get(idx as u32).unwrap();
1937 assert_eq!(&charstring[..expected.len()], expected);
1938 }
1939 }
1940
1941 #[test]
1942 fn parse_charstrings_duplicate_def() {
1943 let private = b"/CharStrings 2 /.notdef 2 RD nd ND /H 2 RD ab ND /I 2 RD cd ND def\n/CharStrings 1 /B 2 RD xy ND def";
1946 let font = Type1Font::from_dicts(b"", private).unwrap();
1947 assert_eq!(font.num_glyphs(), 3);
1948 assert_eq!(font.charstrings.name(0).unwrap(), ".notdef");
1949 assert_eq!(font.charstrings.name(1).unwrap(), "H");
1950 assert_eq!(font.charstrings.name(2).unwrap(), "I");
1951 }
1952
1953 #[test]
1954 fn parse_charstrings_missing_notdef() {
1955 let mut parser = Parser::new(b"1 /H 2 RD ab ND /B 2 RD xy ND");
1956 let charstrings = parser.read_charstrings(-1).unwrap();
1957 assert_eq!(charstrings.num_glyphs(), 3);
1958 assert_eq!(charstrings.orig_notdef_index, Some(2));
1959 let expected_glyphs: &[(&str, &[u8])] =
1960 &[(".notdef", NOTDEF_GLYPH), ("B", b"xy"), ("H", b"ab")];
1961 check_charstrings(&charstrings, expected_glyphs);
1962 let mut font = Type1Font::empty();
1963 font.charstrings = charstrings;
1964 assert_eq!(font.remapped_gid(GlyphId::new(0)), GlyphId::new(2));
1965 assert_eq!(font.remapped_gid(GlyphId::new(1)), GlyphId::new(1));
1966 assert_eq!(font.remapped_gid(GlyphId::new(2)), GlyphId::new(0));
1967 }
1968
1969 #[test]
1970 fn parse_charstrings_notdef_moved() {
1971 let mut parser = Parser::new(b"1 /H 2 RD ab ND /.notdef 2 RD nd ND /B 2 RD xy ND");
1972 let charstrings = parser.read_charstrings(-1).unwrap();
1973 assert_eq!(charstrings.num_glyphs(), 3);
1974 assert_eq!(charstrings.orig_notdef_index, Some(1));
1975 let expected_glyphs: &[(&str, &[u8])] = &[(".notdef", b"nd"), ("H", b"ab"), ("B", b"xy")];
1976 check_charstrings(&charstrings, expected_glyphs);
1977 let mut font = Type1Font::empty();
1978 font.charstrings = charstrings;
1979 assert_eq!(font.remapped_gid(GlyphId::new(0)), GlyphId::new(1));
1980 assert_eq!(font.remapped_gid(GlyphId::new(1)), GlyphId::new(0));
1981 assert_eq!(font.remapped_gid(GlyphId::new(2)), GlyphId::new(2));
1982 }
1983
1984 #[track_caller]
1985 fn check_charstrings(charstrings: &Charstrings, expected_glyphs: &[(&str, &[u8])]) {
1986 for (idx, expected) in expected_glyphs.iter().enumerate() {
1987 let idx = idx as u32;
1988 let name = charstrings.name(idx).unwrap();
1989 let data = charstrings.get(idx).unwrap();
1990 assert_eq!((name, data), *expected);
1991 }
1992 }
1993
1994 #[test]
1995 fn parse_weight_vector() {
1996 let mut parser = Parser::new(b"[0 0.125, 1.25 -0.87]");
1997 let weights = parser
1998 .read_weight_vector()
1999 .unwrap()
2000 .drain(..)
2001 .map(|w| w.to_f32())
2002 .collect::<Vec<_>>();
2003 assert_eq!(weights, &[0.0, 0.125, 1.25, -0.8699951]);
2004 }
2005
2006 #[test]
2007 fn parse_type1_font_pfb() {
2008 check_type1_font(
2009 &Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFB).unwrap(),
2010 );
2011 }
2012
2013 #[test]
2014 fn parse_type1_font_pfa() {
2015 check_type1_font(
2016 &Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap(),
2017 );
2018 }
2019
2020 #[track_caller]
2021 fn check_type1_font(font: &Type1Font) {
2022 assert_eq!(font.name(), Some("NotoSerif-Regular"));
2023 assert_eq!(font.full_name(), Some("Noto Serif Regular"));
2024 assert_eq!(font.family_name(), Some("Noto Serif"));
2025 assert_eq!(font.weight(), Some("Book"));
2026 assert_eq!(font.italic_angle(), 0);
2027 assert!(!font.is_fixed_pitch());
2028 assert_eq!(font.underline_position(), -125);
2029 assert_eq!(font.underline_thickness(), 50);
2030 assert_eq!(
2031 font.bbox(),
2032 BoundingBox {
2033 x_min: Fixed::from_i32(5),
2034 y_min: Fixed::ZERO,
2035 x_max: Fixed::from_i32(989),
2036 y_max: Fixed::from_i32(775)
2037 }
2038 );
2039 assert_eq!(font.num_glyphs(), 9);
2040 assert_eq!(font.subrs.index.len(), 5);
2041 assert_eq!(
2042 font.matrix,
2043 ScaledFontMatrix {
2044 matrix: FontMatrix::IDENTITY,
2045 scale: 1000
2046 }
2047 );
2048 assert!(font
2049 .glyph_names()
2050 .map(|(_, name)| name)
2051 .take(4)
2052 .eq([".notdef", "H", "f", "i"].into_iter()))
2053 }
2054
2055 #[test]
2056 fn parse_encoding() {
2057 assert!(matches!(
2058 Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA)
2059 .unwrap()
2060 .encoding,
2061 Some(RawEncoding::Predefined(PredefinedEncoding::Standard)),
2062 ));
2063 }
2064
2065 #[test]
2066 fn parse_known_encodings() {
2067 for (blob, encoding) in [
2068 (
2069 "StandardEncoding",
2070 RawEncoding::Predefined(PredefinedEncoding::Standard),
2071 ),
2072 (
2073 "ExpertEncoding",
2074 RawEncoding::Predefined(PredefinedEncoding::Expert),
2075 ),
2076 (
2077 "ISOLatin1Encoding",
2078 RawEncoding::Predefined(PredefinedEncoding::IsoLatin1),
2079 ),
2080 ] {
2081 assert_eq!(
2082 Parser::new(blob.as_bytes())
2083 .read_encoding(&Charstrings::default())
2084 .unwrap(),
2085 encoding
2086 );
2087 }
2088 }
2089
2090 #[test]
2091 fn parse_custom_dense_encoding() {
2092 let mut map = Vec::new();
2093 map.resize(256, ".notdef".to_string());
2094 let mut parser = Parser::new(b"[/.notdef /A /b /.notdef /comma /at]");
2095 parser.read_dense_encoding(|idx, name| {
2096 map[idx as usize] = name.to_string();
2097 });
2098 for (ch, entry) in map.iter().enumerate() {
2099 let expected = match ch {
2100 1 => "A",
2101 2 => "b",
2102 4 => "comma",
2103 5 => "at",
2104 _ => ".notdef",
2105 };
2106 assert_eq!(entry, expected);
2107 }
2108 }
2109
2110 #[test]
2111 fn parse_custom_sparse_encoding() {
2112 let mut map = Vec::new();
2113 map.resize(256, ".notdef".to_string());
2114 let mut parser = Parser::new(CUSTOM_SPARSE_ENCODING.as_bytes());
2115 parser.read_sparse_encoding(|idx, name| {
2116 map[idx as usize] = name.to_string();
2117 });
2118 for (ch, entry) in map.iter().enumerate() {
2119 let expected = match ch {
2120 66 => "B",
2121 97 => "a",
2122 64 => "at",
2123 44 => "comma",
2124 56 => "eight",
2125 _ => ".notdef",
2126 };
2127 assert_eq!(entry, expected);
2128 }
2129 }
2130
2131 const CUSTOM_SPARSE_ENCODING: &str = r#"
2132 array
2133 0 1 255 {1 index exch /.notdef put} for
2134 dup 66 /B put
2135 dup 97 /a put
2136 dup 64 /at put
2137 dup 44 /comma put
2138 dup 56 /eight put
2139 readonly def
2140 "#;
2141
2142 #[test]
2143 fn eval_charstrings() {
2144 let font = Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
2145 let expected_eval_prefix = [
2146 "M38,0 L329,0 L329,42 L316,42 C293,42 274,46 258,54 C242,63 234,83 234,114",
2147 "M27,0 L336,0 L336,42 L298,42 C275,42 256,46 240,54 C224,63 216,83 216,114",
2148 "M161,636 C176,636 190,641 201,650 C212,659 218,675 218,698 C218,721 212,738 201,746",
2149 "M5,0 L243,0 L243,42 L240,42 C218,42 202,44 192,50 C183,54 178,62 178,73",
2150 "M27,0 L316,0 L316,42 L298,42 C275,42 256,46 240,54 C224,63 216,83 216,114",
2151 "M27,0 L316,0 L316,42 L298,42 C275,42 256,46 240,54 C224,63 216,83 216,114",
2152 "M27,0 L316,0 L316,42 L298,42 C275,42 256,46 240,54 C224,63 216,83 216,114",
2153 "M41,0 L290,0 L290,42 L269,42 C254,42 240,45 229,52 C218,58 212,73 212,98",
2154 ];
2155 assert_eq!(font.num_glyphs() as usize - 1, expected_eval_prefix.len());
2157 let mut commands = CaptureCommandSink::default();
2158 for (gid, expected_prefix) in (1..font.num_glyphs()).zip(&expected_eval_prefix) {
2159 commands.0.clear();
2160 font.evaluate_charstring(gid.into(), &mut commands).unwrap();
2161 assert!(commands.to_svg().starts_with(expected_prefix));
2162 }
2163 }
2164
2165 #[test]
2166 fn eval_charstring_widths() {
2167 let font = Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
2168 let expected_widths = [
2169 600.0, 793.0, 369.0, 320.0, 578.0, 708.0, 1002.0, 663.0, 680.0,
2170 ];
2171 let mut commands = CaptureCommandSink::default();
2172 let widths = (0..font.num_glyphs())
2173 .map(|gid| {
2174 commands.0.clear();
2175 font.evaluate_charstring(gid.into(), &mut commands)
2176 .unwrap()
2177 .unwrap()
2178 .to_f32()
2179 })
2180 .collect::<Vec<_>>();
2181 assert_eq!(widths, expected_widths);
2182 }
2183
2184 #[test]
2185 fn csctx_seac_components() {
2186 let font = Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
2187 let x_code = 120;
2189 let i_code = 105;
2190 let [x_data, i_data] = font.seac_components(x_code, i_code).unwrap();
2191 let name_to_gid = |name| {
2192 font.glyph_names()
2193 .find_map(|(gid, gname)| (name == gname).then_some(gid.to_u32()))
2194 .unwrap()
2195 };
2196 assert_eq!(x_data, font.charstrings.get(name_to_gid("x")).unwrap());
2197 assert_eq!(i_data, font.charstrings.get(name_to_gid("i")).unwrap());
2198 }
2199
2200 #[test]
2201 fn csctx_subrs() {
2202 let font = Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
2203 assert!(!font.subrs.index.is_empty());
2204 for subr_idx in 0..font.subrs.index.len() {
2205 assert_eq!(
2206 font.subrs.get(subr_idx as u32).unwrap(),
2207 font.subr(subr_idx as _).unwrap()
2208 )
2209 }
2210 }
2211
2212 #[test]
2213 fn encoding_mapping() {
2214 let font = Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
2215 let encoding = font.encoding().unwrap();
2216 let expected = [
2217 (0, 0, ".notdef"),
2219 (72, 1, "H"),
2220 (102, 2, "f"),
2221 (105, 3, "i"),
2222 (120, 4, "x"),
2223 ];
2224 for (code, gid, name) in expected {
2225 assert_eq!(encoding.glyph_name(code).unwrap(), name);
2226 assert_eq!(encoding.map(code).unwrap().to_u32(), gid);
2227 }
2228 }
2229}