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 self.accept_blob_start() {
820 self.pos += 1;
822 let data = self.read_bytes(int as usize)?;
824 return Some(Token::Binary(data));
828 }
829 return Some(Token::Int(int));
830 }
831 }
832 return Some(Token::Raw(content));
833 }
834 }
835 }
836 }
837
838 fn accept_blob_start(&mut self) -> bool {
841 let mut p = self.clone();
842 p.skip_whitespace();
843 let start = p.pos;
844 p.skip_until(is_special_or_whitespace);
845 let end = p.pos;
846 if matches!(self.data.get(start..end), Some(b"RD") | Some(b"-|")) {
847 self.pos = end;
848 true
849 } else {
850 false
851 }
852 }
853
854 fn accept(&mut self, token: Token) -> bool {
855 let mut p = self.clone();
856 if p.next() == Some(token) {
857 self.pos = p.pos;
858 true
859 } else {
860 false
861 }
862 }
863
864 fn expect(&mut self, token: Token) -> Option<()> {
865 (self.next()? == token).then_some(())
866 }
867
868 fn next_byte(&mut self) -> Option<u8> {
869 let byte = self.peek_byte()?;
870 self.pos += 1;
871 Some(byte)
872 }
873
874 fn peek_byte(&self) -> Option<u8> {
875 self.data.get(self.pos).copied()
876 }
877
878 fn read_bytes(&mut self, len: usize) -> Option<&'a [u8]> {
879 let end = self.pos.checked_add(len)?;
880 let content = self.data.get(self.pos..end)?;
881 self.pos = end;
882 Some(content)
883 }
884
885 fn skip_whitespace(&mut self) -> Option<()> {
886 while is_whitespace(*self.data.get(self.pos)?) {
887 self.pos += 1;
888 }
889 Some(())
890 }
891
892 fn skip_line(&mut self) {
893 while let Some(c) = self.next_byte() {
894 if c == b'\n' || c == b'\r' {
895 break;
896 }
897 }
898 }
899
900 fn skip_until(&mut self, f: impl Fn(u8) -> bool) -> usize {
901 let mut count = 0;
902 while let Some(byte) = self.peek_byte() {
903 if f(byte) {
904 break;
905 }
906 self.pos += 1;
907 count += 1;
908 }
909 count + 1
910 }
911
912 fn read_proc(&mut self, start: usize) -> Option<Token<'a>> {
913 let mut nest_depth = 1i32;
914 while let Some(c) = self.next_byte() {
915 match c {
916 b'{' => nest_depth = nest_depth.checked_add(1)?,
917 b'}' => {
918 nest_depth -= 1;
919 if nest_depth == 0 {
920 break;
921 }
922 }
923 b'%' => self.skip_line(),
925 b'(' => {
927 self.read_lit_string(self.pos - 1)?;
928 }
929 _ => {}
930 }
931 }
932 if nest_depth != 0 {
933 return None;
935 }
936 let end = self.pos;
937 Some(Token::Proc(self.data.get(start + 1..end - 1)?))
938 }
939
940 fn read_lit_string(&mut self, start: usize) -> Option<Token<'a>> {
941 let mut nest_depth = 1i32;
942 while let Some(c) = self.next_byte() {
943 match c {
944 b'(' => nest_depth = nest_depth.checked_add(1)?,
945 b')' => {
946 nest_depth -= 1;
947 if nest_depth == 0 {
948 break;
949 }
950 }
951 b'\\' => {
953 self.next_byte()?;
956 }
957 _ => {}
958 }
959 }
960 if nest_depth != 0 {
961 return None;
963 }
964 let end = self.pos;
965 Some(Token::LitString(self.data.get(start + 1..end - 1)?))
966 }
967
968 fn read_hex_string(&mut self, start: usize) -> Option<Token<'a>> {
969 while let Some(c) = self.next_byte() {
970 if !is_whitespace(c) && !c.is_ascii_hexdigit() {
971 break;
972 }
973 }
974 let end = self.pos;
975 if self.data.get(end - 1) != Some(&b'>') {
976 return None;
978 }
979 Some(Token::HexString(self.data.get(start + 1..end - 1)?))
980 }
981
982 fn read_int(&mut self) -> Option<i64> {
983 self.next().and_then(|t| match t {
984 Token::Int(n) => Some(n),
985 _ => None,
986 })
987 }
988
989 fn read_num_as_int(&mut self) -> Option<i32> {
990 match self.next()? {
991 Token::Int(n) => Some(n as i32),
992 Token::Raw(bytes) => decode_int_prefix(bytes, 0).map(|n| n.0 as i32),
996 _ => None,
997 }
998 }
999
1000 fn read_string(&mut self) -> Option<String> {
1001 use alloc::borrow::ToOwned;
1002 let bytes = match self.next()? {
1003 Token::Name(bytes) | Token::LitString(bytes) => bytes,
1006 _ => return None,
1007 };
1008 core::str::from_utf8(bytes).ok().map(|s| s.to_owned())
1009 }
1010}
1011
1012impl Parser<'_> {
1013 fn read_font_matrix(&mut self) -> Option<ScaledFontMatrix> {
1021 let mut components = [Fixed::ZERO; 6];
1022 if !self.accept(Token::Raw(b"[")) {
1024 self.expect(Token::Raw(b"{"))?;
1025 }
1026 for component in &mut components {
1028 *component = match self.next()? {
1029 Token::Int(int) => Fixed::from_i32((int as i32).checked_mul(1000)?),
1030 Token::Raw(bytes) => decode_fixed(bytes, 3)?,
1031 _ => return None,
1032 }
1033 }
1034 self.next()?;
1036 let temp_scale = components[3].abs();
1037 if temp_scale == Fixed::ZERO {
1038 return None;
1039 }
1040 let mut upem = 1000;
1041 if temp_scale != Fixed::ONE {
1042 upem = (Fixed::from_bits(1000) / temp_scale).to_bits();
1043 components[0] /= temp_scale;
1044 components[1] /= temp_scale;
1045 components[2] /= temp_scale;
1046 components[4] /= temp_scale;
1048 components[5] /= temp_scale;
1049 if components[3] < Fixed::ZERO {
1050 components[3] = -Fixed::ONE;
1051 } else {
1052 components[3] = Fixed::ONE;
1053 }
1054 }
1055 for offset in components.iter_mut().skip(4) {
1057 *offset = Fixed::from_bits(offset.to_bits() >> 16);
1058 }
1059 let matrix = FontMatrix::from_elements(components);
1060 if transform::is_degenerate(&matrix) {
1061 return None;
1062 }
1063 Some(ScaledFontMatrix {
1064 matrix,
1065 scale: upem,
1066 })
1067 }
1068
1069 fn read_subrs(&mut self, len_iv: i64) -> Option<Subrs> {
1076 let mut subrs = Subrs::default();
1077 let _: usize = match self.next()? {
1078 Token::Raw(b"[") => {
1079 self.expect(Token::Raw(b"]"))?;
1081 return Some(subrs);
1082 }
1083 Token::Int(n) => n.try_into().ok()?,
1084 _ => return None,
1085 };
1086 self.expect(Token::Raw(b"array"))?;
1087 let mut is_dense = true;
1088 while self.accept(Token::Raw(b"dup")) {
1090 let (Token::Int(n), Token::Binary(data)) = (self.next()?, self.next()?) else {
1091 return None;
1092 };
1093 self.next();
1096 self.accept(Token::Raw(b"put"));
1098 let subr_num: u32 = n.try_into().ok()?;
1099 if subr_num as usize != subrs.index.len() {
1100 is_dense = false;
1101 }
1102 let start = subrs.data.len();
1103 if len_iv >= 0 {
1104 subrs
1106 .data
1107 .extend(decrypt(data.iter().copied(), CHARSTRING_SEED).skip(len_iv as usize));
1108 } else {
1109 subrs.data.extend_from_slice(data);
1111 }
1112 let end = subrs.data.len();
1113 subrs.index.push((subr_num, start..end));
1114 }
1115 if !is_dense {
1117 subrs.index.sort_unstable_by_key(|(n, ..)| *n);
1118 }
1119 subrs.is_dense = is_dense;
1120 subrs.data.shrink_to_fit();
1121 subrs.index.shrink_to_fit();
1122 Some(subrs)
1123 }
1124
1125 fn read_charstrings(&mut self, len_iv: i64) -> Option<Charstrings> {
1132 let mut charstrings = Charstrings::default();
1133 let _: usize = match self.next()? {
1134 Token::Int(n) => n.try_into().ok()?,
1135 _ => return None,
1136 };
1137 let mut notdef_idx = None;
1138 while let Some(token) = self.next() {
1139 let name = match token {
1140 Token::Raw(b"end") => {
1145 if self
1146 .peek_byte()
1147 .map(is_special_or_whitespace)
1148 .unwrap_or_default()
1149 {
1150 break;
1151 } else {
1152 continue;
1153 }
1154 }
1155 Token::Raw(b"def") => {
1156 if self
1158 .peek_byte()
1159 .map(is_special_or_whitespace)
1160 .unwrap_or_default()
1161 && !charstrings.index.is_empty()
1162 {
1163 break;
1164 } else {
1165 continue;
1166 }
1167 }
1168 Token::Name(name) => name,
1169 _ => continue,
1170 };
1171 if name == b".notdef" {
1172 notdef_idx = Some(charstrings.index.len());
1173 }
1174 let Token::Binary(data) = self.next()? else {
1175 return None;
1176 };
1177 charstrings.push(name, data, len_iv);
1178 }
1179 match notdef_idx {
1180 Some(0) => {
1181 }
1183 Some(idx) => {
1184 charstrings.index.swap(0, idx);
1187 charstrings.orig_notdef_index = Some(idx);
1188 }
1189 None => {
1190 let idx = charstrings.index.len();
1193 charstrings.push(b".notdef", NOTDEF_GLYPH, -1);
1194 charstrings.index.swap(0, idx);
1195 charstrings.orig_notdef_index = Some(idx);
1196 }
1197 }
1198 charstrings.data.shrink_to_fit();
1199 charstrings.names.shrink_to_fit();
1200 charstrings.index.shrink_to_fit();
1201 Some(charstrings)
1202 }
1203
1204 fn read_font_bbox(&mut self) -> Option<[Fixed; 4]> {
1205 let mut bbox = [Fixed::ZERO; 4];
1206 let mut parser;
1210 let parser = if self.accept(Token::Raw(b"[")) {
1211 self
1212 } else if let Token::Proc(proc) = self.next()? {
1213 parser = Parser::new(proc);
1214 &mut parser
1215 } else {
1216 return None;
1217 };
1218 for component in &mut bbox {
1220 *component = match parser.next()? {
1221 Token::Int(int) => Fixed::from_i32(int as i32),
1222 Token::Raw(bytes) => decode_fixed(bytes, 0)?,
1223 _ => return None,
1224 }
1225 }
1226 Some(bbox)
1227 }
1228
1229 fn read_weight_vector(&mut self) -> Option<Vec<Fixed>> {
1230 self.accept(Token::Raw(b"["));
1231 let mut weights = Vec::new();
1232 while let Some(token) = self.next() {
1233 match token {
1234 Token::Raw(b"]") => break,
1235 Token::Int(val) => weights.push(Fixed::from_i32(val as _)),
1236 Token::Raw(raw) => weights.push(decode_fixed(raw, 0)?),
1237 _ => return None,
1238 }
1239 }
1240 Some(weights)
1241 }
1242
1243 fn read_encoding(&mut self, charstrings: &Charstrings) -> Option<RawEncoding> {
1247 match self.next()? {
1248 Token::Raw(b"[") => {
1250 let mut map = Vec::new();
1251 map.resize(256, GlyphId::NOTDEF);
1253 self.read_dense_encoding(|idx, name| {
1254 if let Some((slot, gid)) = map
1255 .get_mut(idx as usize)
1256 .zip(charstrings.index_for_name(name))
1257 {
1258 *slot = gid.into();
1259 }
1260 });
1261 Some(RawEncoding::Custom(map))
1262 }
1263 Token::Int(count) => {
1265 let count: usize = count.clamp(0, 256) as usize;
1268 let mut map = Vec::new();
1269 map.resize(count, GlyphId::NOTDEF);
1271 self.read_sparse_encoding(|idx, name| {
1272 if let Some((slot, gid)) = map
1273 .get_mut(idx as usize)
1274 .zip(charstrings.index_for_name(name))
1275 {
1276 *slot = gid.into();
1277 }
1278 });
1279 Some(RawEncoding::Custom(map))
1280 }
1281 Token::Raw(b"StandardEncoding") => {
1282 Some(RawEncoding::Predefined(PredefinedEncoding::Standard))
1283 }
1284 Token::Raw(b"ExpertEncoding") => {
1285 Some(RawEncoding::Predefined(PredefinedEncoding::Expert))
1286 }
1287 Token::Raw(b"ISOLatin1Encoding") => {
1288 Some(RawEncoding::Predefined(PredefinedEncoding::IsoLatin1))
1289 }
1290 _ => None,
1291 }
1292 }
1293
1294 fn read_dense_encoding(&mut self, mut f: impl FnMut(i64, &str)) -> Option<()> {
1298 self.accept(Token::Raw(b"["));
1300 let mut idx = 0;
1303 while let Some(token) = self.next() {
1304 match token {
1305 Token::Raw(b"]") => break,
1306 Token::Name(name) => {
1307 let code = idx;
1308 idx += 1;
1309 let Ok(name) = core::str::from_utf8(name) else {
1310 continue;
1311 };
1312 f(code, name);
1313 }
1314 _ => {
1315 return None;
1317 }
1318 }
1319 }
1320 Some(())
1321 }
1322
1323 fn read_sparse_encoding(&mut self, mut f: impl FnMut(i64, &str)) -> Option<()> {
1326 while let Some(token) = self.next() {
1327 match token {
1328 Token::Raw(b"def") => break,
1330 Token::Int(code) => {
1331 let Some(Token::Name(name)) = self.next() else {
1333 continue;
1334 };
1335 let Ok(name) = core::str::from_utf8(name) else {
1336 continue;
1337 };
1338 f(code, name);
1339 }
1340 _ => {}
1341 }
1342 }
1343 Some(())
1344 }
1345}
1346
1347fn decode_int(bytes: &[u8]) -> Option<i64> {
1351 let s = std::str::from_utf8(bytes).ok()?;
1352 if let Some(hash_idx) = s.find('#') {
1353 if hash_idx == 1 || hash_idx == 2 {
1354 let radix_str = s.get(0..hash_idx)?;
1356 let number_str = s.get(hash_idx + 1..)?;
1357 let radix = radix_str
1358 .parse::<u32>()
1359 .ok()
1360 .filter(|n| (2..=36).contains(n))?;
1361 i64::from_str_radix(number_str, radix).ok()
1362 } else {
1363 s.parse::<i64>().ok()
1364 }
1365 } else {
1366 s.parse::<i64>().ok()
1367 }
1368}
1369
1370fn decode_int_prefix(bytes: &[u8], start: usize) -> Option<(i64, usize)> {
1373 let tail = bytes.get(start..)?;
1374 let end = tail
1375 .iter()
1376 .position(|c| *c != b'-' && !c.is_ascii_digit())
1377 .unwrap_or(tail.len());
1378 let int = decode_int(tail.get(..end)?)?;
1379 Some((int, start + end))
1380}
1381
1382fn decode_fixed(bytes: &[u8], mut power_ten: i32) -> Option<Fixed> {
1387 const LIMIT: i32 = 0xCCCCCCC;
1388 let mut idx = 0;
1389 let &first = bytes.get(idx)?;
1390 let sign = if first == b'-' || first == b'+' {
1391 idx += 1;
1392 if first == b'-' {
1393 -1
1394 } else {
1395 1
1396 }
1397 } else {
1398 1
1399 };
1400 let overflow = || Some(Fixed::from_bits(0x7FFFFFFF * sign));
1401 let mut integral = 0;
1402 if *bytes.get(idx)? != b'.' {
1403 let (int, end_idx) = decode_int_prefix(bytes, idx)?;
1404 if int > 0x7FFF {
1405 return overflow();
1406 }
1407 integral = (int << 16) as i32;
1408 idx = end_idx;
1409 }
1410 let mut decimal = 0;
1411 let mut divider = 1;
1412 if bytes.get(idx) == Some(&b'.') {
1413 idx += 1;
1414 while let Some(byte) = bytes.get(idx).copied() {
1415 if !byte.is_ascii_digit() {
1416 break;
1417 }
1418 let digit = (byte - b'0') as i32;
1419 if divider < LIMIT && decimal < LIMIT {
1420 decimal = decimal * 10 + digit;
1421 if integral == 0 && power_ten > 0 {
1422 power_ten -= 1;
1423 } else {
1424 divider *= 10;
1425 }
1426 }
1427 idx += 1;
1428 }
1429 }
1430 if bytes.get(idx).map(|b| b.to_ascii_lowercase()) == Some(b'e') {
1431 idx += 1;
1432 let (exponent, _) = decode_int_prefix(bytes, idx)?;
1433 if exponent > 1000 {
1434 return overflow();
1435 } else if exponent < -1000 {
1436 return Some(Fixed::ZERO);
1438 } else {
1439 power_ten = power_ten.checked_add(exponent as i32)?;
1440 }
1441 }
1442 if integral == 0 && decimal == 0 {
1443 return Some(Fixed::ZERO);
1444 }
1445 while power_ten > 0 {
1446 if integral >= LIMIT {
1447 return overflow();
1448 }
1449 integral *= 10;
1450 if decimal >= LIMIT {
1451 if divider == 1 {
1452 return overflow();
1453 }
1454 divider /= 10;
1455 } else {
1456 decimal *= 10;
1457 }
1458 power_ten -= 1;
1459 }
1460 while power_ten < 0 {
1461 integral /= 10;
1462 if divider < LIMIT {
1463 divider *= 10;
1464 } else {
1465 decimal /= 10;
1466 }
1467 if integral == 0 && decimal == 0 {
1468 return Some(Fixed::ZERO);
1469 }
1470 power_ten += 1;
1471 }
1472 if decimal != 0 {
1473 decimal = (Fixed::from_bits(decimal) / Fixed::from_bits(divider)).to_bits();
1474 integral += decimal;
1475 }
1476 Some(Fixed::from_bits(integral * sign))
1477}
1478
1479#[cfg(test)]
1480mod tests {
1481 use super::*;
1482 use cs::test_helpers::*;
1483
1484 #[test]
1485 fn pfb_tags() {
1486 let data = [0x80, 0x01, 0x01, 0x02, 0x00, 0x00];
1488 let (tag, len) = decode_pfb_tag(&data, 0).unwrap();
1489 assert_eq!(tag, PFB_TEXT_SEGMENT_TAG);
1490 assert_eq!(len, 513);
1491 let data = [0x80, 0x02, 0x01, 0x03, 0x00, 0x00];
1493 let (tag, len) = decode_pfb_tag(&data, 0).unwrap();
1494 assert_eq!(tag, PFB_BINARY_SEGMENT_TAG);
1495 assert_eq!(len, 769);
1496 let data = [0x00; 6];
1498 assert!(decode_pfb_tag(&data, 0).is_none());
1499 let data = [0x00; 5];
1501 assert!(decode_pfb_tag(&data, 0).is_none());
1502 }
1503
1504 #[test]
1505 fn pfb_segments() {
1506 let segments = [
1507 vec![0x01; 8],
1508 vec![0x02; 10],
1509 vec![0x03; 4],
1510 vec![0x04; 255],
1511 ];
1512 let mut buf = vec![];
1514 for segment in &segments {
1515 buf.push(0x80);
1516 buf.push(0x02);
1517 buf.push(segment.len() as u8);
1518 buf.extend_from_slice(&[0; 3]);
1519 for byte in segment {
1520 buf.push(*byte);
1521 }
1522 }
1523 let mut parsed_count = 0;
1525 for (parsed, expected) in decode_pfb_binary_segments(&buf).zip(&segments) {
1526 assert_eq!(parsed, expected);
1527 parsed_count += 1;
1528 }
1529 assert_eq!(parsed_count, segments.len());
1530 }
1531
1532 #[test]
1533 fn hex_decode() {
1534 check_hex_decode(
1535 b"743F8413F3636CA85A9FFEFB50B4BB27",
1536 &[
1537 116, 63, 132, 19, 243, 99, 108, 168, 90, 159, 254, 251, 80, 180, 187, 39,
1538 ],
1539 );
1540 }
1541
1542 #[test]
1543 fn hex_decode_ignores_whitespace() {
1544 check_hex_decode(
1545 b"743F 8413F3636C\nA85A9FFEF\tB50B 4BB27",
1546 &[
1547 116, 63, 132, 19, 243, 99, 108, 168, 90, 159, 254, 251, 80, 180, 187, 39,
1548 ],
1549 );
1550 }
1551
1552 #[test]
1553 fn hex_decode_truncate() {
1554 check_hex_decode(b"743F.8413F3636CA85A9FFEFB50B4BB27", &[116, 63]);
1555 }
1556
1557 #[test]
1558 fn hex_decode_odd_chars() {
1559 check_hex_decode(b"743", &[116, 48]);
1560 }
1561
1562 #[track_caller]
1563 fn check_hex_decode(hex: &[u8], expected: &[u8]) {
1564 let decoded = decode_hex(hex.iter().copied()).collect::<Vec<_>>();
1565 assert_eq!(decoded, expected);
1566 }
1567
1568 #[test]
1569 fn decrypt_bytes() {
1570 let cipher = [
1571 0x74, 0x3f, 0x84, 0x13, 0xf3, 0x63, 0x6c, 0xa8, 0x5a, 0x9f, 0xfe, 0xfb, 0x50, 0xb4,
1572 0xbb, 0x27,
1573 ];
1574 let plain = decrypt(cipher.iter().copied(), EEXEC_SEED).collect::<Vec<_>>();
1575 assert_eq!(&plain[4..], b"dup\n/Private");
1577 }
1578
1579 #[test]
1580 fn find_eexec() {
1581 assert_eq!(
1583 find_eexec_data(b"dup\n/Private\ncurrentfile eexec *&&FW"),
1584 Some(31)
1585 );
1586 assert_eq!(
1588 find_eexec_data(b"dup\n/Private\ncurrentfile eexec *&&FW"),
1589 Some(35)
1590 );
1591 assert_eq!(
1593 find_eexec_data(b"dup\n/Private\ncurrentfile eexec\n\n*&&FW"),
1594 Some(32)
1595 );
1596 assert_eq!(
1598 find_eexec_data(b"dup\n/Private\ncurrentfile eexec\r\n\r*&&FW"),
1599 Some(32)
1600 );
1601 assert_eq!(
1603 find_eexec_data(b"% eexec in comment\n(eexec in string) currentfile eexec $$$$"),
1604 Some(55)
1605 );
1606 assert!(find_eexec_data(b"% eexec in comment\n(eexec in string) currentfile").is_none());
1608 }
1609
1610 #[test]
1611 fn read_pfb_raw_dicts() {
1612 let dicts = RawDicts::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFB).unwrap();
1613 check_noto_serif_base(dicts.base);
1614 check_noto_serif_private(&dicts.private);
1615 }
1616
1617 #[test]
1618 fn read_pfa_raw_dicts() {
1619 let dicts = RawDicts::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
1620 check_noto_serif_base(dicts.base);
1621 check_noto_serif_private(&dicts.private);
1622 }
1623
1624 fn check_noto_serif_base(base: &[u8]) {
1625 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 ""
1626%%Title: NotoSerif-Regular
1627%Version: 2.007; ttfautohint (v1.8) -l 8 -r 50 -G 200 -x 14 -D latn -f none -a qsq -X ""
1628%%CreationDate: Tue Feb 10 16:07:25 2026
1629%%Creator: www-data
1630%Copyright: Copyright 2015-2021 Google LLC. All Rights Reserved.
1631% Generated by FontForge 20190801 (http://fontforge.sf.net/)
1632%%EndComments
1633
163410 dict begin
1635/FontType 1 def
1636/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
1637/FontName /NotoSerif-Regular def
1638/FontBBox {5 0 989 775 }readonly def
1639"#;
1640 let mut base = base.to_vec();
1643 base.retain(|&b| b != b'\r');
1644 assert!(base.starts_with(EXPECTED_PREFIX.as_bytes()));
1645 }
1646
1647 fn check_noto_serif_private(private: &[u8]) {
1648 const EXPECTED_PREFIX: &str = r#"dup
1649/Private 8 dict dup begin
1650/RD{string currentfile exch readstring pop}executeonly def
1651/ND{noaccess def}executeonly def
1652/NP{noaccess put}executeonly def
1653/MinFeature{16 16}ND
1654/password 5839 def
1655/BlueValues [0 0 536 536 714 714 770 770 ]ND
1656/OtherSubrs"#;
1657 assert!(private.starts_with(EXPECTED_PREFIX.as_bytes()))
1658 }
1659
1660 #[test]
1661 fn parse_ints() {
1662 check_tokens(
1663 "% a comment\n20 -30 2#1011 10#-5 %another!\r 16#fC",
1664 &[
1665 Token::Int(20),
1666 Token::Int(-30),
1667 Token::Int(11),
1668 Token::Int(-5),
1669 Token::Int(252),
1670 ],
1671 );
1672 }
1673
1674 #[test]
1675 fn parse_num_to_int() {
1676 let mut parser =
1677 Parser::new(b"102 102.1 102.4 102.5 102.9 -102.1 -102.5 -102.9 8#146 16#66");
1678 for _ in 0..10 {
1679 assert_eq!(parser.read_num_as_int().unwrap().abs(), 102);
1680 }
1681 assert!(parser.next().is_none());
1682 }
1683
1684 #[test]
1685 fn parse_strings() {
1686 check_tokens(
1687 "(string (nested) 1) % and a hex string:\n <DEAD BEEF>",
1688 &[
1689 Token::LitString(b"string (nested) 1"),
1690 Token::HexString(b"DEAD BEEF"),
1691 ],
1692 );
1693 }
1694
1695 #[test]
1696 fn parse_unterminated_strings() {
1697 check_tokens("(string (nested) 1", &[]);
1698 check_tokens("<DEAD BEEF", &[]);
1699 }
1700
1701 #[test]
1702 fn parse_procs() {
1703 check_tokens(
1704 "{a {nested 20 % comment\n} proc } % and a\n {simple proc}",
1705 &[
1706 Token::Proc(b"a {nested 20 % comment\n} proc "),
1707 Token::Proc(b"simple proc"),
1708 ],
1709 );
1710 }
1711
1712 #[test]
1713 fn parse_procs_with_string_containing_unbalanced_braces() {
1714 check_tokens(
1715 "{a proc with (string {with braces}} {) }",
1716 &[Token::Proc(b"a proc with (string {with braces}} {) ")],
1717 );
1718 }
1719
1720 #[test]
1721 fn parse_proc_with_single_int() {
1722 check_tokens(
1723 "dup 3 {3} executeonly put",
1724 &[
1725 Token::Raw(b"dup"),
1726 Token::Int(3),
1727 Token::Proc(b"3"),
1728 Token::Raw(b"executeonly"),
1729 Token::Raw(b"put"),
1730 ],
1731 );
1732 }
1733
1734 #[test]
1735 fn parse_unterminated_procs() {
1736 check_tokens("{a {nested 20} proc", &[]);
1737 }
1738
1739 #[test]
1740 fn parse_aggregate_tokens_without_whitespace() {
1741 check_tokens(
1742 "{(string)}3(string1)(string2)",
1743 &[
1744 Token::Proc(b"(string)"),
1745 Token::Int(3),
1746 Token::LitString(b"string1"),
1747 Token::LitString(b"string2"),
1748 ],
1749 );
1750 }
1751
1752 #[test]
1753 fn parse_names() {
1754 check_tokens(
1755 "/FontMatrix\r %comment\n /CharStrings",
1756 &[Token::Name(b"FontMatrix"), Token::Name(b"CharStrings")],
1757 );
1758 }
1759
1760 #[test]
1761 fn parse_binary_blobs() {
1762 check_tokens(
1763 "/.notdef 4 RD abcd \n5 11\n \t-| a83jnshf7 3 ",
1764 &[
1765 Token::Name(b".notdef"),
1767 Token::Binary(b"abcd"),
1768 Token::Int(5),
1770 Token::Binary(b"a83jnshf7 3"),
1771 ],
1772 )
1773 }
1774
1775 #[test]
1776 fn parse_base_dict_prefix() {
1777 let dicts = RawDicts::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
1778 let ts = parse_to_tokens(dicts.base);
1779 assert_eq!(
1780 &ts[..19],
1781 &[
1782 Token::Int(10),
1783 Token::Raw(b"dict"),
1784 Token::Raw(b"begin"),
1785 Token::Name(b"FontType"),
1786 Token::Int(1),
1787 Token::Raw(b"def"),
1788 Token::Name(b"FontMatrix"),
1789 Token::Raw(b"["),
1790 Token::Raw(b"0.001"),
1791 Token::Int(0),
1792 Token::Int(0),
1793 Token::Raw(b"0.001"),
1794 Token::Int(0),
1795 Token::Int(0),
1796 Token::Raw(b"]"),
1797 Token::Raw(b"readonly"),
1798 Token::Raw(b"def"),
1799 Token::Name(b"FontName"),
1800 Token::Name(b"NotoSerif-Regular"),
1801 ]
1802 );
1803 }
1804
1805 #[track_caller]
1806 fn check_tokens(source: &str, expected: &[Token]) {
1807 let ts = parse_to_tokens(source.as_bytes());
1808 assert_eq!(ts, expected);
1809 }
1810
1811 fn parse_to_tokens(data: &'_ [u8]) -> Vec<Token<'_>> {
1812 let mut tokens = vec![];
1813 let mut parser = Parser::new(data);
1814 while let Some(token) = parser.next() {
1815 tokens.push(token);
1816 }
1817 tokens
1818 }
1819
1820 #[test]
1821 fn parse_fixed() {
1822 assert_eq!(decode_fixed(b"42.5", 0).unwrap(), Fixed::from_f64(42.5));
1824 assert_eq!(
1825 decode_fixed(b"0.0015", 0).unwrap(),
1826 Fixed::from_f64(0.001495361328125)
1827 );
1828 assert_eq!(
1829 decode_fixed(b"425.000e-1", 0).unwrap(),
1830 Fixed::from_f64(42.5)
1831 );
1832 assert_eq!(
1833 decode_fixed(b"1.5e-3", 0).unwrap(),
1834 Fixed::from_f64(0.001495361328125)
1835 );
1836 assert_eq!(decode_fixed(b"1.5", 3).unwrap(), Fixed::from_f64(1500.0));
1838 assert_eq!(decode_fixed(b"0.001", 3).unwrap(), Fixed::from_f64(1.0));
1839 assert_eq!(
1840 decode_fixed(b"15000e-4", 3).unwrap(),
1841 Fixed::from_f64(1500.0)
1842 );
1843 assert_eq!(decode_fixed(b"1.000e-3", 3).unwrap(), Fixed::from_f64(1.0));
1844 }
1845
1846 #[test]
1847 fn parse_font_matrix() {
1848 assert_eq!(
1850 Parser::new(b"[0.001 0 0 0.001 0 0]")
1851 .read_font_matrix()
1852 .unwrap()
1853 .matrix,
1854 FontMatrix::IDENTITY,
1855 );
1856 assert_eq!(
1859 Parser::new(b"[0.002 0 0 0.001 1 2e1]")
1860 .read_font_matrix()
1861 .unwrap()
1862 .matrix,
1863 FontMatrix::from_elements([
1864 Fixed::from_i32(2),
1865 Fixed::ZERO,
1866 Fixed::ZERO,
1867 Fixed::ONE,
1868 Fixed::from_bits(1000),
1869 Fixed::from_bits(20000)
1870 ])
1871 );
1872 assert_eq!(
1874 Parser::new(b"[0.001 0 0 0.0005 0.0 0.0]")
1875 .read_font_matrix()
1876 .unwrap(),
1877 ScaledFontMatrix {
1878 matrix: FontMatrix::from_elements([
1879 Fixed::from_i32(2),
1880 Fixed::ZERO,
1881 Fixed::ZERO,
1882 Fixed::ONE,
1883 Fixed::from_i32(0),
1884 Fixed::from_i32(0)
1885 ]),
1886 scale: 2000,
1887 }
1888 );
1889 }
1890
1891 #[test]
1892 fn parse_subrs() {
1893 let dicts = RawDicts::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
1894 let mut parser = Parser::new(&dicts.private);
1895 let mut subrs = None;
1896 while let Some(token) = parser.next() {
1897 if let Token::Name(b"Subrs") = token {
1898 subrs = parser.read_subrs(4);
1899 break;
1900 }
1901 }
1902 let mut subrs = subrs.unwrap();
1903 let expected_subrs: [&[u8]; 5] = [
1905 &[142, 139, 12, 16, 12, 17, 12, 17, 12, 33, 11],
1906 &[139, 140, 12, 16, 11],
1907 &[139, 141, 12, 16, 11],
1908 &[11],
1909 &[140, 142, 12, 16, 12, 17, 10, 11],
1910 ];
1911 assert_eq!(subrs.index.len(), expected_subrs.len());
1912 assert!(subrs.is_dense);
1913 for is_dense in [true, false] {
1916 subrs.is_dense = is_dense;
1917 for (idx, &expected) in expected_subrs.iter().enumerate() {
1918 let subr = subrs.get(idx as u32).unwrap();
1919 assert_eq!(subr, expected);
1920 }
1921 }
1922 }
1923
1924 #[test]
1925 fn parse_empty_array_subrs() {
1926 let subrs = Parser::new(b"[ ]").read_subrs(4).unwrap();
1927 assert!(subrs.data.is_empty());
1928 assert!(subrs.index.is_empty());
1929 }
1930
1931 #[test]
1932 fn parse_empty_subrs() {
1933 let subrs = Parser::new(b" 0 array\nND\n").read_subrs(4).unwrap();
1934 assert!(subrs.data.is_empty());
1935 assert!(subrs.index.is_empty());
1936 }
1937
1938 #[test]
1939 fn parse_malformed_subrs() {
1940 assert!(Parser::new(b" 20 \nND\n").read_subrs(4).is_none());
1941 }
1942
1943 #[test]
1944 fn parse_subrs_duplicate_def() {
1945 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";
1948 let font = Type1Font::from_dicts(b"", private).unwrap();
1949 assert_eq!(font.subrs.index.len(), 2);
1950 assert_eq!(font.subrs.index[0].0, 5);
1951 assert_eq!(font.subrs.index[1].0, 42);
1952 }
1953
1954 #[test]
1955 fn parse_charstrings() {
1956 let dicts = RawDicts::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
1957 let mut parser = Parser::new(&dicts.private);
1958 let mut charstrings = None;
1959 while let Some(token) = parser.next() {
1960 if let Token::Name(b"CharStrings") = token {
1961 charstrings = parser.read_charstrings(4);
1962 break;
1963 }
1964 }
1965 let charstrings = charstrings.unwrap();
1966 assert_eq!(charstrings.num_glyphs(), 9);
1967 assert!(charstrings.orig_notdef_index.is_none());
1968 let expected_names = [
1969 ".notdef",
1970 "H",
1971 "f",
1972 "i",
1973 "x",
1974 "f_f.liga",
1975 "f_f_i.liga",
1976 "f_i.liga",
1977 "H.c2sc",
1978 ];
1979 let names = (0..charstrings.num_glyphs())
1980 .map(|idx| charstrings.name(idx).unwrap())
1981 .collect::<Vec<_>>();
1982 assert_eq!(names, expected_names);
1983 let expected_charstrings_prefix: [&[u8]; 9] = [
1985 &[139, 248, 236, 13, 14],
1986 &[177, 249, 173, 13, 139, 4, 247, 183],
1987 &[166, 248, 5, 13, 139, 4, 247, 201],
1988 &[162, 247, 212, 13, 247, 30, 249, 16],
1989 &[144, 248, 214, 13, 139, 4, 247, 130],
1990 &[166, 249, 88, 13, 139, 4, 247, 181],
1991 &[166, 250, 126, 13, 139, 4, 247, 181],
1992 &[166, 249, 43, 13, 139, 4, 247, 181],
1993 &[180, 249, 60, 13, 139, 4, 247, 141],
1994 ];
1995 for (idx, &expected) in expected_charstrings_prefix.iter().enumerate() {
1996 let charstring = charstrings.get(idx as u32).unwrap();
1997 assert_eq!(&charstring[..expected.len()], expected);
1998 }
1999 }
2000
2001 #[test]
2002 fn parse_charstrings_duplicate_def() {
2003 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";
2006 let font = Type1Font::from_dicts(b"", private).unwrap();
2007 assert_eq!(font.num_glyphs(), 3);
2008 assert_eq!(font.charstrings.name(0).unwrap(), ".notdef");
2009 assert_eq!(font.charstrings.name(1).unwrap(), "H");
2010 assert_eq!(font.charstrings.name(2).unwrap(), "I");
2011 }
2012
2013 #[test]
2014 fn parse_charstrings_missing_notdef() {
2015 let mut parser = Parser::new(b"1 /H 2 RD ab ND /B 2 RD xy ND");
2016 let charstrings = parser.read_charstrings(-1).unwrap();
2017 assert_eq!(charstrings.num_glyphs(), 3);
2018 assert_eq!(charstrings.orig_notdef_index, Some(2));
2019 let expected_glyphs: &[(&str, &[u8])] =
2020 &[(".notdef", NOTDEF_GLYPH), ("B", b"xy"), ("H", b"ab")];
2021 check_charstrings(&charstrings, expected_glyphs);
2022 let mut font = Type1Font::empty();
2023 font.charstrings = charstrings;
2024 assert_eq!(font.remapped_gid(GlyphId::new(0)), GlyphId::new(2));
2025 assert_eq!(font.remapped_gid(GlyphId::new(1)), GlyphId::new(1));
2026 assert_eq!(font.remapped_gid(GlyphId::new(2)), GlyphId::new(0));
2027 }
2028
2029 #[test]
2030 fn parse_charstrings_notdef_moved() {
2031 let mut parser = Parser::new(b"1 /H 2 RD ab ND /.notdef 2 RD nd ND /B 2 RD xy ND");
2032 let charstrings = parser.read_charstrings(-1).unwrap();
2033 assert_eq!(charstrings.num_glyphs(), 3);
2034 assert_eq!(charstrings.orig_notdef_index, Some(1));
2035 let expected_glyphs: &[(&str, &[u8])] = &[(".notdef", b"nd"), ("H", b"ab"), ("B", b"xy")];
2036 check_charstrings(&charstrings, expected_glyphs);
2037 let mut font = Type1Font::empty();
2038 font.charstrings = charstrings;
2039 assert_eq!(font.remapped_gid(GlyphId::new(0)), GlyphId::new(1));
2040 assert_eq!(font.remapped_gid(GlyphId::new(1)), GlyphId::new(0));
2041 assert_eq!(font.remapped_gid(GlyphId::new(2)), GlyphId::new(2));
2042 }
2043
2044 #[track_caller]
2045 fn check_charstrings(charstrings: &Charstrings, expected_glyphs: &[(&str, &[u8])]) {
2046 for (idx, expected) in expected_glyphs.iter().enumerate() {
2047 let idx = idx as u32;
2048 let name = charstrings.name(idx).unwrap();
2049 let data = charstrings.get(idx).unwrap();
2050 assert_eq!((name, data), *expected);
2051 }
2052 }
2053
2054 #[test]
2055 fn parse_weight_vector() {
2056 let mut parser = Parser::new(b"[0 0.125, 1.25 -0.87]");
2057 let weights = parser
2058 .read_weight_vector()
2059 .unwrap()
2060 .drain(..)
2061 .map(|w| w.to_f32())
2062 .collect::<Vec<_>>();
2063 assert_eq!(weights, &[0.0, 0.125, 1.25, -0.8699951]);
2064 }
2065
2066 #[test]
2067 fn parse_type1_font_pfb() {
2068 check_type1_font(
2069 &Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFB).unwrap(),
2070 );
2071 }
2072
2073 #[test]
2074 fn parse_type1_font_pfa() {
2075 check_type1_font(
2076 &Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap(),
2077 );
2078 }
2079
2080 #[track_caller]
2081 fn check_type1_font(font: &Type1Font) {
2082 assert_eq!(font.name(), Some("NotoSerif-Regular"));
2083 assert_eq!(font.full_name(), Some("Noto Serif Regular"));
2084 assert_eq!(font.family_name(), Some("Noto Serif"));
2085 assert_eq!(font.weight(), Some("Book"));
2086 assert_eq!(font.italic_angle(), 0);
2087 assert!(!font.is_fixed_pitch());
2088 assert_eq!(font.underline_position(), -125);
2089 assert_eq!(font.underline_thickness(), 50);
2090 assert_eq!(
2091 font.bbox(),
2092 BoundingBox {
2093 x_min: Fixed::from_i32(5),
2094 y_min: Fixed::ZERO,
2095 x_max: Fixed::from_i32(989),
2096 y_max: Fixed::from_i32(775)
2097 }
2098 );
2099 assert_eq!(font.num_glyphs(), 9);
2100 assert_eq!(font.subrs.index.len(), 5);
2101 assert_eq!(
2102 font.matrix,
2103 ScaledFontMatrix {
2104 matrix: FontMatrix::IDENTITY,
2105 scale: 1000
2106 }
2107 );
2108 assert!(font
2109 .glyph_names()
2110 .map(|(_, name)| name)
2111 .take(4)
2112 .eq([".notdef", "H", "f", "i"].into_iter()))
2113 }
2114
2115 #[test]
2116 fn parse_encoding() {
2117 assert!(matches!(
2118 Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA)
2119 .unwrap()
2120 .encoding,
2121 Some(RawEncoding::Predefined(PredefinedEncoding::Standard)),
2122 ));
2123 }
2124
2125 #[test]
2126 fn parse_known_encodings() {
2127 for (blob, encoding) in [
2128 (
2129 "StandardEncoding",
2130 RawEncoding::Predefined(PredefinedEncoding::Standard),
2131 ),
2132 (
2133 "ExpertEncoding",
2134 RawEncoding::Predefined(PredefinedEncoding::Expert),
2135 ),
2136 (
2137 "ISOLatin1Encoding",
2138 RawEncoding::Predefined(PredefinedEncoding::IsoLatin1),
2139 ),
2140 ] {
2141 assert_eq!(
2142 Parser::new(blob.as_bytes())
2143 .read_encoding(&Charstrings::default())
2144 .unwrap(),
2145 encoding
2146 );
2147 }
2148 }
2149
2150 #[test]
2151 fn parse_custom_dense_encoding() {
2152 let mut map = Vec::new();
2153 map.resize(256, ".notdef".to_string());
2154 let mut parser = Parser::new(b"[/.notdef /A /b /.notdef /comma /at]");
2155 parser.read_dense_encoding(|idx, name| {
2156 map[idx as usize] = name.to_string();
2157 });
2158 for (ch, entry) in map.iter().enumerate() {
2159 let expected = match ch {
2160 1 => "A",
2161 2 => "b",
2162 4 => "comma",
2163 5 => "at",
2164 _ => ".notdef",
2165 };
2166 assert_eq!(entry, expected);
2167 }
2168 }
2169
2170 #[test]
2171 fn parse_custom_sparse_encoding() {
2172 let mut map = Vec::new();
2173 map.resize(256, ".notdef".to_string());
2174 let mut parser = Parser::new(CUSTOM_SPARSE_ENCODING.as_bytes());
2175 parser.read_sparse_encoding(|idx, name| {
2176 map[idx as usize] = name.to_string();
2177 });
2178 for (ch, entry) in map.iter().enumerate() {
2179 let expected = match ch {
2180 66 => "B",
2181 97 => "a",
2182 64 => "at",
2183 44 => "comma",
2184 56 => "eight",
2185 _ => ".notdef",
2186 };
2187 assert_eq!(entry, expected);
2188 }
2189 }
2190
2191 const CUSTOM_SPARSE_ENCODING: &str = r#"
2192 array
2193 0 1 255 {1 index exch /.notdef put} for
2194 dup 66 /B put
2195 dup 97 /a put
2196 dup 64 /at put
2197 dup 44 /comma put
2198 dup 56 /eight put
2199 readonly def
2200 "#;
2201
2202 #[test]
2203 fn eval_charstrings() {
2204 let font = Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
2205 let expected_eval_prefix = [
2206 "M38,0 L329,0 L329,42 L316,42 C293,42 274,46 258,54 C242,63 234,83 234,114",
2207 "M27,0 L336,0 L336,42 L298,42 C275,42 256,46 240,54 C224,63 216,83 216,114",
2208 "M161,636 C176,636 190,641 201,650 C212,659 218,675 218,698 C218,721 212,738 201,746",
2209 "M5,0 L243,0 L243,42 L240,42 C218,42 202,44 192,50 C183,54 178,62 178,73",
2210 "M27,0 L316,0 L316,42 L298,42 C275,42 256,46 240,54 C224,63 216,83 216,114",
2211 "M27,0 L316,0 L316,42 L298,42 C275,42 256,46 240,54 C224,63 216,83 216,114",
2212 "M27,0 L316,0 L316,42 L298,42 C275,42 256,46 240,54 C224,63 216,83 216,114",
2213 "M41,0 L290,0 L290,42 L269,42 C254,42 240,45 229,52 C218,58 212,73 212,98",
2214 ];
2215 assert_eq!(font.num_glyphs() as usize - 1, expected_eval_prefix.len());
2217 let mut commands = CaptureCommandSink::default();
2218 for (gid, expected_prefix) in (1..font.num_glyphs()).zip(&expected_eval_prefix) {
2219 commands.0.clear();
2220 font.evaluate_charstring(gid.into(), &mut commands).unwrap();
2221 assert!(commands.to_svg().starts_with(expected_prefix));
2222 }
2223 }
2224
2225 #[test]
2226 fn eval_charstring_widths() {
2227 let font = Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
2228 let expected_widths = [
2229 600.0, 793.0, 369.0, 320.0, 578.0, 708.0, 1002.0, 663.0, 680.0,
2230 ];
2231 let mut commands = CaptureCommandSink::default();
2232 let widths = (0..font.num_glyphs())
2233 .map(|gid| {
2234 commands.0.clear();
2235 font.evaluate_charstring(gid.into(), &mut commands)
2236 .unwrap()
2237 .unwrap()
2238 .to_f32()
2239 })
2240 .collect::<Vec<_>>();
2241 assert_eq!(widths, expected_widths);
2242 }
2243
2244 #[test]
2245 fn csctx_seac_components() {
2246 let font = Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
2247 let x_code = 120;
2249 let i_code = 105;
2250 let [x_data, i_data] = font.seac_components(x_code, i_code).unwrap();
2251 let name_to_gid = |name| {
2252 font.glyph_names()
2253 .find_map(|(gid, gname)| (name == gname).then_some(gid.to_u32()))
2254 .unwrap()
2255 };
2256 assert_eq!(x_data, font.charstrings.get(name_to_gid("x")).unwrap());
2257 assert_eq!(i_data, font.charstrings.get(name_to_gid("i")).unwrap());
2258 }
2259
2260 #[test]
2261 fn csctx_subrs() {
2262 let font = Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
2263 assert!(!font.subrs.index.is_empty());
2264 for subr_idx in 0..font.subrs.index.len() {
2265 assert_eq!(
2266 font.subrs.get(subr_idx as u32).unwrap(),
2267 font.subr(subr_idx as _).unwrap()
2268 )
2269 }
2270 }
2271
2272 #[test]
2273 fn encoding_mapping() {
2274 let font = Type1Font::new(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA).unwrap();
2275 let encoding = font.encoding().unwrap();
2276 let expected = [
2277 (0, 0, ".notdef"),
2279 (72, 1, "H"),
2280 (102, 2, "f"),
2281 (105, 3, "i"),
2282 (120, 4, "x"),
2283 ];
2284 for (code, gid, name) in expected {
2285 assert_eq!(encoding.glyph_name(code).unwrap(), name);
2286 assert_eq!(encoding.map(code).unwrap().to_u32(), gid);
2287 }
2288 }
2289}