1mod charstring;
4mod charstring_parser;
5mod decrypt;
6mod operator;
7mod standard;
8pub(crate) mod stream;
9
10use crate::font::type1::charstring::{parse_char_string, parse_char_string_width};
11use crate::font::type1::decrypt::{decrypt, decrypt_byte};
12use crate::font::type1::standard::STANDARD;
13use crate::font::type1::stream::Stream;
14use crate::font::{Arc, Map, Matrix, OutlineBuilder};
15use alloc::borrow::Cow;
16use alloc::string::{String, ToString};
17use alloc::vec;
18use alloc::vec::Vec;
19use core::iter::Copied;
20use core::slice::Iter;
21use core::str::FromStr;
22use log::error;
23#[derive(Debug)]
27pub(crate) struct Parameters {
28 font_matrix: Matrix,
29 encoding_type: EncodingType,
30 subroutines: Map<u32, Vec<u8>>,
31 charstrings: Map<String, Vec<u8>>,
32 charstring_names: Vec<String>,
33 charstring_indices: Map<String, u16>,
34 pub(crate) weight_vector: Option<Vec<f32>>,
35}
36
37impl Default for Parameters {
38 fn default() -> Self {
39 Self {
40 font_matrix: Matrix::default(),
41 encoding_type: EncodingType::Standard,
42 subroutines: Map::new(),
43 charstrings: Map::new(),
44 charstring_names: Vec::new(),
45 charstring_indices: Map::new(),
46 weight_vector: None,
47 }
48 }
49}
50
51#[derive(Debug, Clone)]
53pub struct Table {
54 params: Arc<Parameters>,
55}
56
57impl Table {
58 pub fn parse(data: &[u8]) -> Option<Self> {
60 let data = if data.starts_with(&[0x80, 0x01]) {
61 extract_pfb_segments(data)?
62 } else if data.starts_with(b"%!") {
63 Cow::Borrowed(data)
64 } else {
65 error!("type1 font wasn't recognized!");
66
67 return None;
68 };
69
70 let mut s = Stream::new(data.as_ref());
71 let mut params = Parameters::default();
72
73 while let Some(token) = s.next_token() {
74 match token {
75 b"/FontInfo" => s.skip_dict(),
76 b"/FontName" => s.skip_token(),
77 b"/PaintType" => s.skip_token(),
78 b"/FontType" => s.skip_token(),
79 b"/FontBBox" => s.skip_token(),
80 b"/UniqueID" => s.skip_token(),
81 b"/Metrics" => s.skip_dict(),
82 b"/StrokeWidth" => s.skip_token(),
83 b"/FontMatrix" => {
84 let matrix = s.read_font_matrix()?;
85 params.font_matrix = Matrix {
86 sx: matrix[0],
87 kx: matrix[2],
88 ky: matrix[1],
89 sy: matrix[3],
90 tx: matrix[4],
91 ty: matrix[5],
92 };
93 }
94 b"/WeightVector" => {
95 if let Some(wv) = s.read_float_array() {
96 params.weight_vector = Some(wv);
97 }
98 }
99 b"/Encoding" => params.encoding_type = s.read_encoding()?,
100 b"eexec" => {
101 let decrypted = decrypt(s.tail()?, true)?;
102 Self::parse_eexec(&decrypted, &mut params)?;
103 }
104 _ => {}
105 }
106 }
107
108 if params.charstrings.is_empty() {
110 return None;
111 }
112
113 Some(Self {
114 params: Arc::new(params),
115 })
116 }
117
118 fn parse_eexec(data: &[u8], params: &mut Parameters) -> Option<()> {
119 let mut s = Stream::new(data);
120
121 let mut len_iv = 4;
122 let mut use_decryption = true;
123
124 while let Some(token) = s.next_token() {
125 match token {
126 b"/Subrs" => {
127 params.subroutines = s
128 .parse_subroutines(len_iv, use_decryption)
129 .unwrap_or_default();
130 }
131 b"/CharStrings" => {
132 if let Some((chars, names)) = s.parse_charstrings(len_iv, use_decryption) {
133 params.charstring_indices = names
134 .iter()
135 .enumerate()
136 .map(|(i, n)| (n.clone(), i as u16))
137 .collect();
138 params.charstrings = chars;
139 params.charstring_names = names;
140 }
141 }
142 b"/lenIV" => {
143 len_iv = s.next_int()?;
144
145 if len_iv < 0 {
146 use_decryption = false;
147 len_iv = 0;
148 }
149 }
150 b"/WeightVector" => {
151 if let Some(wv) = s.read_float_array() {
152 params.weight_vector = Some(wv);
153 }
154 }
155 _ => {}
156 }
157 }
158
159 Some(())
160 }
161
162 pub fn is_multiple_master(&self) -> bool {
164 self.params.weight_vector.is_some()
165 }
166
167 pub fn matrix(&self) -> Matrix {
169 self.params.font_matrix
170 }
171
172 pub fn outline(&self, string: &str, builder: &mut dyn OutlineBuilder) -> Option<()> {
174 let data = self.params.charstrings.get(string)?;
175
176 parse_char_string(data, &self.params, builder).ok()?;
177
178 Some(())
179 }
180
181 pub fn glyph_width(&self, string: &str) -> Option<f32> {
183 let data = self.params.charstrings.get(string)?;
184 parse_char_string_width(data, &self.params).ok()
185 }
186
187 pub fn code_to_string(&self, code_point: u8) -> Option<&str> {
189 self.params.encoding_type.encode(code_point)
190 }
191
192 pub fn charstring_names(&self) -> &[String] {
194 &self.params.charstring_names
195 }
196
197 pub fn charstring_index(&self, name: &str) -> Option<u16> {
199 self.params.charstring_indices.get(name).copied()
200 }
201}
202
203fn extract_pfb_segments(pfb: &[u8]) -> Option<Cow<'static, [u8]>> {
205 const START_MARKER: u8 = 0x80;
206 const ASCII_MARKER: u8 = 0x01;
207 const BINARY_MARKER: u8 = 0x02;
208 const EOF_MARKER: u8 = 0x03;
209 const PFB_HEADER_LENGTH: usize = 18;
210
211 if pfb.len() < PFB_HEADER_LENGTH {
212 return None;
213 }
214
215 let mut stream = Stream::new(pfb);
216 let mut type_list = Vec::new();
217 let mut barr_list = Vec::new();
218 let mut total = 0;
219
220 loop {
221 let r = stream.read_byte();
222 if r.is_none() && total > 0 {
223 break; }
225 let r = r?;
226
227 if r != START_MARKER {
228 return None;
229 }
230
231 let record_type = stream.read_byte()?;
232 if record_type == EOF_MARKER {
233 break;
234 }
235
236 if record_type != ASCII_MARKER && record_type != BINARY_MARKER {
237 return None;
238 }
239
240 let size_bytes = stream.read_bytes(4)?;
241 let mut size = size_bytes[0] as usize;
242 size += (size_bytes[1] as usize) << 8;
243 size += (size_bytes[2] as usize) << 16;
244 size += (size_bytes[3] as usize) << 24;
245
246 let Some(ar) = stream.read_bytes(size) else {
248 break;
249 };
250
251 total += size;
252 type_list.push(record_type);
253 barr_list.push(ar);
254 }
255
256 let mut pfbdata = Vec::with_capacity(total);
261 let mut cleartomark_segment = None;
262
263 for i in 0..type_list.len() {
265 if type_list[i] != ASCII_MARKER {
266 continue;
267 }
268
269 let ar = barr_list[i];
270 if i == type_list.len() - 1
271 && ar.len() < 600
272 && let Ok(s) = core::str::from_utf8(ar)
273 && s.contains("cleartomark")
274 {
275 cleartomark_segment = Some(ar);
276 continue;
277 }
278 pfbdata.extend_from_slice(ar);
279 }
280
281 for i in 0..type_list.len() {
283 if type_list[i] != BINARY_MARKER {
284 continue;
285 }
286 let ar = barr_list[i];
287 pfbdata.extend_from_slice(ar);
288 }
289
290 if let Some(segment) = cleartomark_segment {
291 pfbdata.extend_from_slice(segment);
292 }
293
294 Some(Cow::Owned(pfbdata))
295}
296
297const ND: &[u8] = b"ND";
298const ND_ALT: &[u8] = b"|-";
299
300const RD: &[u8] = b"RD";
301const RD_ALT: &[u8] = b"-|";
302
303const NP: &[u8] = b"NP";
304const NP_ALT: &[u8] = b"|";
305
306impl<'a> Stream<'a> {
307 fn next_int(&mut self) -> Option<i64> {
308 parse_int(core::str::from_utf8(self.next_token()?).ok()?)
309 }
310
311 #[allow(clippy::type_complexity)]
312 fn parse_charstrings(
313 &mut self,
314 len_iv: i64,
315 use_decryption: bool,
316 ) -> Option<(Map<String, Vec<u8>>, Vec<String>)> {
317 let mut charstrings = Map::new();
318 let mut names = Vec::new();
319
320 let mut first_glyph_name = None;
321 let mut int_token = None;
322
323 while let Some(token) = self.next_token() {
324 if token == b"end" {
325 return Some((charstrings, names));
326 }
327
328 if token.starts_with(b"/") {
329 first_glyph_name = Some(token);
330 } else if token
331 .iter()
332 .all(|b| matches!(*b, b'#') || b.is_ascii_digit())
333 {
334 int_token = parse_int(core::str::from_utf8(token).ok()?);
335 } else if token == RD || token == RD_ALT {
336 break;
337 }
338 }
339
340 let (first_glyph_name, int_token) = (first_glyph_name?, int_token?);
341
342 let mut is_first = true;
343
344 loop {
345 let bin_len;
346 let mut glyph_name;
347
348 if is_first {
349 is_first = false;
350 bin_len = int_token;
351 glyph_name = first_glyph_name;
352
353 if glyph_name.starts_with(b"/") {
354 glyph_name = &glyph_name[1..];
355 }
356
357 self.read_byte();
358 } else {
359 let tok = self.next_token()?;
360 if tok == b"end" {
361 break;
362 }
363
364 if tok.starts_with(b"/") {
365 glyph_name = &tok[1..];
366 } else {
367 glyph_name = tok;
368 }
369
370 let Some(len) = self.next_int() else {
372 break;
373 };
374 bin_len = len;
375 let tok = self.next_token()?;
376
377 if tok == RD || tok == RD_ALT {
378 self.read_byte();
379 } else {
380 error!("invalid charstring in start, expected RD");
381
382 return None;
383 }
384 }
385
386 let encrypted_bytes = self.read_bytes(bin_len as usize)?;
387 let decrypted_bytes = decrypt_charstring(encrypted_bytes, len_iv, use_decryption)?;
388 let name = core::str::from_utf8(glyph_name).ok()?.to_string();
389 names.push(name.clone());
390 charstrings.insert(name, decrypted_bytes);
391
392 let tok = self.next_token()?;
393 if tok == ND || tok == ND_ALT {
394 } else if tok.starts_with(b"/") {
395 self.move_back(tok.len());
398 } else {
399 error!("invalid charstring in end, expected ND, found {tok:?}");
400
401 if charstrings.is_empty() {
402 return None;
403 } else {
404 break;
406 }
407 }
408 }
409
410 Some((charstrings, names))
411 }
412
413 fn parse_subroutines(
414 &mut self,
415 len_iv: i64,
416 use_decryption: bool,
417 ) -> Option<Map<u32, Vec<u8>>> {
418 let mut subroutines = Map::new();
419
420 let num_subrs = parse_int(core::str::from_utf8(self.next_token()?).ok()?)?;
421
422 if num_subrs < 1 {
423 return Some(subroutines);
424 }
425
426 if !self.skip_until_before(b"dup", |b| matches!(b, ND | ND_ALT | b"noaccess")) {
427 return Some(subroutines);
428 }
429
430 while let Some(token) = self.next_token() {
431 if matches!(token, ND | ND_ALT) {
432 break;
433 }
434
435 if token == b"noaccess" {
436 if self.next_token() == Some(b"def") {
437 break;
438 } else {
439 error!("invalid sequence noaccess");
440
441 return None;
442 }
443 }
444
445 if token != b"dup" {
446 error!("expected dup, got token {:?} instead", &token);
447
448 return None;
449 }
450
451 let subr_idx = self.next_int()?;
452 let bin_len = self.next_int()?;
453
454 let tok = self.next_token()?;
455
456 if tok != RD && tok != RD_ALT {
457 error!("invalid subroutine start token {tok:?}");
458
459 return None;
460 } else {
461 self.read_byte();
463 }
464
465 let encrypted_bytes = self.read_bytes(bin_len as usize)?;
466 subroutines.insert(
467 subr_idx as u32,
468 decrypt_charstring(encrypted_bytes, len_iv, use_decryption)?,
469 );
470
471 let mut tok = self.next_token()?;
472 if tok == NP || tok == NP_ALT {
473 } else if tok == b"noaccess" {
474 tok = self.next_token()?;
475 if tok == b"def" {
476 break;
477 }
478
479 if tok == b"put" {
480 } else {
481 error!("invalid subroutine end {tok:?}");
482
483 return None;
484 }
485 } else {
486 error!("invalid subroutine end token {tok:?}");
487
488 return None;
489 }
490 }
491
492 Some(subroutines)
493 }
494
495 fn peek_token(&mut self) -> Option<&'a [u8]> {
496 self.clone().next_token()
497 }
498
499 fn next_token(&mut self) -> Option<&'a [u8]> {
500 let skip_token = |st: &mut Stream<'_>| -> usize {
501 let mut count = 1;
502 while let Some(ch) = st.read_bytes(1) {
503 if is_whitespace(ch[0]) || is_self_delim_after_token(ch[0]) {
504 st.move_back(1);
505 break;
506 }
507
508 count += 1;
509 }
510
511 count
512 };
513
514 self.skip_whitespaces();
515
516 while let Some(ch) = self.clone().read_bytes(1) {
517 let tail = self.tail()?;
518 self.read_bytes(1);
519
520 match ch[0] {
521 b'%' => self.skip_line_comment(),
522 b'(' => return Some(b"("),
523 b'<' => {
524 if let Some(ch2) = self.read_bytes(1) {
525 if ch2[0] == b'>' {
526 return Some(b"( )");
527 } else if ch2[0] == b'<' {
528 return Some(b"<<");
529 } else {
530 return Some(b"<");
531 }
532 }
533 }
534 b'>' => {
535 if let Some(ch2) = self.read_bytes(1) {
536 if ch2[0] == b'>' {
537 return Some(b">>");
538 } else {
539 self.move_back(1);
540 return Some(b">");
541 }
542 }
543 }
544 b'[' => {
545 return Some(b"[");
546 }
547 b']' => {
548 return Some(b"]");
549 }
550 b'{' => {
551 return Some(b"{");
552 }
553 b'}' => {
554 return Some(b"}");
555 }
556 b'/' => {
557 if let Some(ch2) = self.read_bytes(1) {
558 if is_whitespace(ch2[0]) || is_self_delim_after_token(ch2[0]) {
559 let token = b"/";
560
561 if is_self_delim_after_token(ch2[0]) {
562 self.move_back(1);
563 }
564
565 return Some(token);
566 } else {
567 let count = skip_token(self);
568
569 return Some(&tail[0..(count + 1)]);
570 }
571 }
572 }
573 _ => {
574 let count = skip_token(self);
575 return Some(&tail[0..count]);
576 }
577 }
578
579 self.skip_whitespaces();
580 }
581
582 None
583 }
584
585 fn read_float_array(&mut self) -> Option<Vec<f32>> {
587 let mut entries = Vec::new();
588
589 if self.next_token()? != b"[" {
590 return None;
591 }
592
593 while let Some(token) = self.next_token() {
594 if token == b"]" {
595 break;
596 }
597 if let Ok(s) = core::str::from_utf8(token)
598 && let Ok(v) = f32::from_str(s)
599 {
600 entries.push(v);
601 }
602 }
603
604 Some(entries)
605 }
606
607 fn read_font_matrix(&mut self) -> Option<[f32; 6]> {
608 let mut entries = [0.0_f32; 6];
609 let mut idx = 0;
610
611 self.skip_token();
613
614 while let Some(token) = self.next_token() {
615 entries[idx] = f32::from_str(core::str::from_utf8(token).ok()?).ok()?;
616
617 idx += 1;
618 if idx == 5 {
619 break;
620 }
621 }
622
623 self.skip_token();
625
626 Some(entries)
627 }
628
629 fn read_encoding(&mut self) -> Option<EncodingType> {
630 let mut map = Map::new();
631
632 let t1 = self.next_token()?;
633 let t2 = self.next_token()?;
634
635 if t1 == b"StandardEncoding" && t2 == b"def" {
636 return Some(EncodingType::Standard);
637 }
638
639 if !self.skip_until_before(b"dup", |b| matches!(b, b"def" | b"readonly")) {
640 return Some(EncodingType::Custom(Arc::new(map)));
641 }
642
643 while let Some(token) = self.next_token() {
644 if matches!(token, b"def" | b"readonly") {
645 break;
646 }
647
648 if token != b"dup" {
649 error!("Unexpected token {token:?}");
650
651 return None;
652 }
653
654 let next = self.next_token();
655 let code = parse_int(core::str::from_utf8(next?).ok()?)?;
657 let glyph_name = core::str::from_utf8(&self.next_token()?[1..])
658 .ok()?
659 .to_string();
660
661 if self.next_token()? != b"put" {
662 error!("Unexpected token {token:?}");
663
664 return None;
665 }
666
667 map.insert(u8::try_from(code).ok()?, glyph_name);
668 }
669
670 Some(EncodingType::Custom(Arc::new(map)))
671 }
672
673 fn skip_dict(&mut self) {
674 self.skip_until(b"begin", |b| matches!(b, b"end"));
675 }
676
677 fn skip_token(&mut self) {
678 self.next_token();
679 }
680
681 fn skip_line_comment(&mut self) {
682 while let Some(ch) = self.read_byte() {
683 if matches!(ch, b'\n' | b'\r') {
684 break;
685 }
686 }
687 }
688
689 fn skip_until(&mut self, find: &[u8], stop: impl Fn(&[u8]) -> bool) -> bool {
690 while let Some(token) = self.next_token() {
691 if token == find {
692 return true;
693 }
694
695 if stop(token) {
696 break;
697 }
698 }
699
700 false
701 }
702
703 fn skip_whitespaces(&mut self) {
704 while let Some(ch) = self.peek_byte() {
705 if is_whitespace(ch) {
706 self.read_byte();
707 } else {
708 break;
709 }
710 }
711 }
712
713 fn skip_until_before(&mut self, find: &[u8], stop: impl Fn(&[u8]) -> bool) -> bool {
714 while let Some(token) = self.peek_token() {
715 if token == find {
716 return true;
717 }
718
719 if self.next_token().is_none() {
720 return false;
721 }
722
723 if stop(token) {
724 break;
725 }
726 }
727
728 false
729 }
730}
731
732fn decrypt_charstring(data: &[u8], len_iv: i64, use_decryption: bool) -> Option<Vec<u8>> {
733 let mut r = 4330;
734 let mut cb: Copied<Iter<'_, u8>> = data.iter().copied();
735 let mut decrypted = vec![];
736
737 for _ in 0..len_iv {
738 let _ = decrypt_byte(cb.next()?, &mut r, use_decryption);
739 }
740
741 for byte in cb {
742 decrypted.push(decrypt_byte(byte, &mut r, use_decryption));
743 }
744
745 Some(decrypted)
746}
747
748fn is_whitespace(c: u8) -> bool {
749 if c <= 32 {
750 return matches!(c, b' ' | b'\n' | b'\r' | b'\t' | 0x00 | 0x0C);
751 }
752
753 false
754}
755
756fn is_self_delim_after_token(c: u8) -> bool {
757 matches!(
762 c,
763 b'(' | b'<' | b'>' | b'[' | b']' | b'{' | b'}' | b'/' | b'%' | b')'
764 )
765
766 }
770
771#[derive(Debug, Clone)]
772pub(crate) enum EncodingType {
773 Standard,
774 Custom(Arc<Map<u8, String>>),
775}
776
777impl EncodingType {
778 pub(crate) fn encode(&self, code: u8) -> Option<&str> {
779 match self {
780 Self::Standard => STANDARD.get(&code).copied(),
781 Self::Custom(c) => c.get(&code).map(|s| s.as_str()),
782 }
783 }
784}
785
786fn parse_int(str: &str) -> Option<i64> {
787 if let Some(hash_idx) = str.find('#') {
788 if hash_idx == 1 || hash_idx == 2 {
789 let radix_str = &str[0..hash_idx];
791 let number_str = &str[hash_idx + 1..];
792
793 let radix = radix_str.parse::<u32>().ok()?;
794
795 if (2..=36).contains(&radix) {
796 i64::from_str_radix(number_str, radix).ok()
797 } else {
798 None
799 }
800 } else {
801 str.parse::<i64>().ok()
802 }
803 } else {
804 str.parse::<i64>().ok()
805 }
806}
807
808#[cfg(test)]
809mod tests {
810 use crate::font::type1::stream::Stream;
811
812 macro_rules! assert_token {
813 ($content:expr, $token:expr) => {
814 assert_eq!($content.next_token(), Some(&$token[..]))
815 };
816 }
817
818 #[test]
819 fn lexing_1() {
820 let mut content = Stream::new(b"/FontInfo ");
821
822 assert_token!(content, b"/FontInfo");
823 }
824
825 #[test]
826 fn lexing_2() {
827 let mut content = Stream::new(b"/version (01) readonly def");
828
829 assert_token!(content, b"/version");
830 assert_token!(content, b"(");
831 assert_token!(content, b"01");
832 assert_token!(content, b")");
833 assert_token!(content, b"readonly");
834 assert_token!(content, b"def");
835 }
836}