1mod predefined;
10
11pub use predefined::{cid_to_unicode, predefined, CidToUnicode};
12
13use crate::document::decoded_stream_data_with;
14use crate::hash::FastMap;
15use crate::lexer::{decode_hex, decode_hex_fixed, Lexer, RawToken, Token};
16use crate::object::{Dict, Object, Stream};
17use crate::source::AsyncObjectSource;
18use std::sync::Arc;
19
20#[derive(Clone, Copy)]
27struct Codespace {
28 len: u8,
29 lo: [u8; 4],
30 hi: [u8; 4],
31}
32
33impl Codespace {
34 fn contains(&self, code: &[u8]) -> bool {
35 code.iter()
36 .zip(self.lo.iter().zip(&self.hi))
37 .all(|(&b, (&lo, &hi))| lo <= b && b <= hi)
38 }
39}
40
41#[derive(Clone, Copy)]
44struct CidRange {
45 len: u8,
46 lo: u32,
47 hi: u32,
48 cid: u32,
49}
50
51pub struct CidCmap {
55 wmode: u8,
56 codespaces: Vec<Codespace>,
59 singles: FastMap<(u8, u32), u32>,
61 ranges: Vec<CidRange>,
63 notdefs: Vec<CidRange>,
66 parent: Option<Arc<CidCmap>>,
69}
70
71fn code_value(bytes: &[u8]) -> u32 {
73 bytes.iter().fold(0u32, |acc, &b| (acc << 8) | u32::from(b))
74}
75
76fn covering_range(ranges: &[CidRange], code: u32, len: u8) -> Option<&CidRange> {
78 let idx = ranges.partition_point(|r| (r.len, r.lo) <= (len, code));
79 let r = ranges.get(idx.checked_sub(1)?)?;
80 (r.len == len && code <= r.hi).then_some(r)
81}
82
83impl CidCmap {
84 pub fn identity(vertical: bool) -> CidCmap {
87 CidCmap {
88 wmode: u8::from(vertical),
89 codespaces: vec![Codespace {
90 len: 2,
91 lo: [0; 4],
92 hi: [0xFF; 4],
93 }],
94 singles: FastMap::default(),
95 ranges: vec![CidRange {
96 len: 2,
97 lo: 0,
98 hi: 0xFFFF,
99 cid: 0,
100 }],
101 notdefs: Vec::new(),
102 parent: None,
103 }
104 }
105
106 pub fn parse(data: &[u8]) -> CidCmap {
108 CidCmap::parse_with(data, None, &mut |_| None)
109 }
110
111 pub fn parse_with(
118 data: &[u8],
119 parent: Option<Arc<CidCmap>>,
120 resolve: &mut dyn FnMut(&str) -> Option<Arc<CidCmap>>,
121 ) -> CidCmap {
122 let mut out = CidCmap {
123 wmode: 0,
124 codespaces: Vec::new(),
125 singles: FastMap::default(),
126 ranges: Vec::new(),
127 notdefs: Vec::new(),
128 parent,
129 };
130 let mut lx = Lexer::new(data);
131 let mut pending_name: Option<String> = None;
132 let mut wmode_pending = false;
133 loop {
134 match next_or_skip(&mut lx, data.len()) {
135 None => break,
136 Some(RawToken::Keyword(kw)) => {
137 match kw {
138 b"begincodespacerange" => out.parse_codespaces(&mut lx, data.len()),
139 b"begincidchar" => out.parse_cidchars(&mut lx, data.len(), false),
140 b"begincidrange" => out.parse_cidranges(&mut lx, data.len(), false),
141 b"beginnotdefchar" => out.parse_cidchars(&mut lx, data.len(), true),
142 b"beginnotdefrange" => out.parse_cidranges(&mut lx, data.len(), true),
143 b"usecmap" => {
144 if let (None, Some(name)) = (&out.parent, pending_name.take()) {
145 out.parent = resolve(&name);
146 }
147 }
148 _ => {}
149 }
150 pending_name = None;
151 wmode_pending = false;
152 }
153 Some(RawToken::Owned(Token::Name(n))) => {
154 wmode_pending = n.0 == "WMode";
155 pending_name = (!wmode_pending).then_some(n.0);
156 }
157 Some(RawToken::Owned(Token::Int(i))) => {
158 if wmode_pending {
159 out.wmode = u8::from(i == 1);
160 }
161 wmode_pending = false;
162 }
163 Some(_) => {
164 pending_name = None;
165 wmode_pending = false;
166 }
167 }
168 }
169 out.finish();
170 out
171 }
172
173 fn finish(&mut self) {
176 if let Some(parent) = &self.parent {
177 self.codespaces.extend_from_slice(&parent.codespaces);
178 }
179 self.codespaces.sort_by_key(|c| c.len);
180 self.ranges.sort_by_key(|r| (r.len, r.lo));
181 self.notdefs.sort_by_key(|r| (r.len, r.lo));
182 }
183
184 pub fn is_empty(&self) -> bool {
188 self.singles.is_empty() && self.ranges.is_empty() && self.parent.is_none()
189 }
190
191 pub fn vertical(&self) -> bool {
193 self.wmode == 1
194 }
195
196 pub fn parent(&self) -> Option<&Arc<CidCmap>> {
200 self.parent.as_ref()
201 }
202
203 pub fn single_byte(&self, b: u8) -> bool {
207 self.codespaces
208 .iter()
209 .any(|c| c.len == 1 && c.contains(&[b]))
210 }
211
212 pub fn code_at(&self, bytes: &[u8], pos: usize) -> (u32, u8) {
223 let rest = &bytes[pos..];
224 if self.codespaces.is_empty() {
225 let n = rest.len().min(2);
226 return (code_value(&rest[..n]), n as u8);
227 }
228 for cs in &self.codespaces {
229 let n = usize::from(cs.len);
230 if rest.len() >= n && cs.contains(&rest[..n]) {
231 return (code_value(&rest[..n]), cs.len);
232 }
233 }
234 for cs in &self.codespaces {
235 if cs.lo[0] <= rest[0] && rest[0] <= cs.hi[0] {
236 let n = usize::from(cs.len).min(rest.len());
237 return (code_value(&rest[..n]), n as u8);
238 }
239 }
240 (u32::from(rest[0]), 1)
241 }
242
243 pub fn cid(&self, code: u32, len: u8) -> Option<u32> {
247 self.mapped(code, len).or_else(|| self.notdef(code, len))
248 }
249
250 fn mapped(&self, code: u32, len: u8) -> Option<u32> {
251 if let Some(&cid) = self.singles.get(&(len, code)) {
252 return Some(cid);
253 }
254 if let Some(r) = covering_range(&self.ranges, code, len) {
256 return Some(r.cid.saturating_add(code - r.lo));
257 }
258 self.parent.as_ref()?.mapped(code, len)
259 }
260
261 fn notdef(&self, code: u32, len: u8) -> Option<u32> {
263 covering_range(&self.notdefs, code, len)
264 .map(|r| r.cid)
265 .or_else(|| self.parent.as_ref()?.notdef(code, len))
266 }
267
268 fn mappings(&self, push: &mut impl FnMut(u8, u32, u32, u32)) {
273 let mut singles: Vec<(u8, u32, u32)> = self
274 .singles
275 .iter()
276 .map(|(&(len, code), &cid)| (len, code, cid))
277 .collect();
278 singles.sort_unstable();
279 let mut singles = singles.into_iter().peekable();
280 let mut ranges = self.ranges.iter().peekable();
281 loop {
282 let single_first = match (singles.peek(), ranges.peek()) {
283 (None, None) => break,
284 (Some(_), None) => true,
285 (None, Some(_)) => false,
286 (Some(&(len, code, _)), Some(r)) => (len, code) <= (r.len, r.lo),
287 };
288 if single_first {
289 let (len, code, cid) = singles.next().unwrap();
290 push(len, code, code, cid);
291 } else {
292 let r = ranges.next().unwrap();
293 push(r.len, r.lo, r.hi, r.cid);
294 }
295 }
296 if let Some(parent) = &self.parent {
297 parent.mappings(push);
298 }
299 }
300
301 fn parse_codespaces(&mut self, lx: &mut Lexer<'_>, len: usize) {
303 loop {
304 let lo = match next_or_skip(lx, len) {
305 Some(RawToken::Hex(span)) => span,
306 Some(_) | None => return, };
308 let Some(RawToken::Hex(hi)) = next_or_skip(lx, len) else {
309 return;
310 };
311 let (Some((lo, lo_len)), Some((hi, hi_len))) =
314 (decode_hex_fixed::<4>(lo), decode_hex_fixed::<4>(hi))
315 else {
316 continue;
317 };
318 if lo_len == 0 || hi_len != lo_len {
319 continue;
320 }
321 self.codespaces.push(Codespace {
322 len: lo_len as u8,
323 lo,
324 hi,
325 });
326 }
327 }
328
329 fn parse_cidchars(&mut self, lx: &mut Lexer<'_>, len: usize, notdef: bool) {
331 loop {
332 let code = match next_or_skip(lx, len) {
333 Some(RawToken::Hex(span)) => span,
334 Some(_) | None => return,
335 };
336 let Some(RawToken::Owned(Token::Int(cid))) = next_or_skip(lx, len) else {
337 return;
338 };
339 let Some((code, code_len)) = decode_hex_fixed::<4>(code) else {
340 continue;
341 };
342 if code_len == 0 {
343 continue;
344 }
345 let (value, width) = (code_value(&code[..code_len]), code_len as u8);
346 let cid = cid.max(0) as u32;
347 if notdef {
348 self.notdefs.push(CidRange {
349 len: width,
350 lo: value,
351 hi: value,
352 cid,
353 });
354 } else {
355 self.singles.insert((width, value), cid);
356 }
357 }
358 }
359
360 fn parse_cidranges(&mut self, lx: &mut Lexer<'_>, len: usize, notdef: bool) {
362 loop {
363 let lo = match next_or_skip(lx, len) {
364 Some(RawToken::Hex(span)) => span,
365 Some(_) | None => return,
366 };
367 let Some(RawToken::Hex(hi)) = next_or_skip(lx, len) else {
368 return;
369 };
370 let Some(RawToken::Owned(Token::Int(cid))) = next_or_skip(lx, len) else {
371 return;
372 };
373 let Some((lo, lo_len)) = decode_hex_fixed::<4>(lo) else {
374 continue;
375 };
376 if lo_len == 0 {
377 continue;
378 }
379 let hi_v = match decode_hex_fixed::<4>(hi) {
382 Some((hi, hi_len)) => code_value(&hi[..hi_len]),
383 None => code_value(&decode_hex(hi)),
384 };
385 let lo_v = code_value(&lo[..lo_len]);
386 if hi_v < lo_v {
387 continue;
388 }
389 let range = CidRange {
390 len: lo_len as u8,
391 lo: lo_v,
392 hi: hi_v,
393 cid: cid.max(0) as u32,
394 };
395 if notdef {
396 self.notdefs.push(range);
397 } else {
398 self.ranges.push(range);
399 }
400 }
401 }
402}
403
404pub struct Type0Encoding {
406 pub cmap: Option<Arc<CidCmap>>,
410 pub vertical: bool,
412 pub known: bool,
416}
417
418async fn rv<S: AsyncObjectSource>(src: &S, dict: &Dict, key: &str) -> Option<Object> {
420 let obj = dict.get(key)?;
421 let resolved = src.resolve(obj).await.ok()?;
422 (!resolved.is_null()).then_some(resolved)
423}
424
425pub async fn type0_encoding<S: AsyncObjectSource>(src: &S, font: &Dict) -> Type0Encoding {
434 let identity = |vertical: bool, known: bool| Type0Encoding {
435 cmap: None,
436 vertical,
437 known,
438 };
439 let Some(enc) = rv(src, font, "Encoding").await else {
440 return identity(false, false);
441 };
442 match enc {
443 Object::Name(n) if n.0 == "Identity-H" => identity(false, true),
444 Object::Name(n) if n.0 == "Identity-V" => identity(true, true),
445 Object::Name(n) => match predefined(&n.0) {
446 Some(cmap) => Type0Encoding {
447 vertical: cmap.vertical(),
448 cmap: Some(cmap),
449 known: true,
450 },
451 None => identity(n.0.ends_with("-V"), false),
452 },
453 Object::Stream(stream) => match embedded_cmap(src, &stream).await {
454 Some(cmap) => Type0Encoding {
455 vertical: cmap.vertical(),
456 cmap: Some(cmap),
457 known: true,
458 },
459 None => identity(false, false),
460 },
461 _ => identity(false, false),
462 }
463}
464
465async fn embedded_cmap<S: AsyncObjectSource>(src: &S, stream: &Stream) -> Option<Arc<CidCmap>> {
470 let mut layers: Vec<(Vec<u8>, Option<i64>)> = Vec::new();
473 let mut parent: Option<Arc<CidCmap>> = None;
474 let mut current = stream.clone();
475 for _ in 0..4 {
476 let data = decoded_stream_data_with(src, ¤t).await.ok()?;
479 let wmode = rv(src, ¤t.dict, "WMode")
480 .await
481 .and_then(|o| o.as_int());
482 layers.push((data, wmode));
483 match rv(src, ¤t.dict, "UseCMap").await {
484 Some(Object::Name(n)) => {
485 parent = predefined(&n.0);
486 break;
487 }
488 Some(Object::Stream(s)) => current = s,
489 _ => break,
490 }
491 }
492 for (data, wmode) in layers.into_iter().rev() {
493 let mut resolve = |n: &str| predefined(n);
494 let mut cmap = CidCmap::parse_with(&data, parent.take(), &mut resolve);
495 if let Some(w) = wmode {
496 cmap.wmode = u8::from(w == 1);
497 }
498 parent = Some(Arc::new(cmap));
499 }
500 parent.filter(|c| !c.is_empty())
501}
502
503fn next_or_skip<'a>(lx: &mut Lexer<'a>, len: usize) -> Option<RawToken<'a>> {
506 loop {
507 let before = lx.pos();
508 match lx.next_raw_token() {
509 Ok(RawToken::Owned(Token::Eof)) => return None,
510 Ok(t) => return Some(t),
511 Err(_) => {
512 if lx.pos() <= before {
513 if before + 1 >= len {
514 return None;
515 }
516 lx.seek(before + 1);
517 }
518 }
519 }
520 }
521}
522
523#[cfg(test)]
524mod tests {
525 use super::*;
526
527 const RKSJ_CODESPACES: &str = "4 begincodespacerange\n\
530 <00> <80>\n\
531 <8140> <9FFC>\n\
532 <A0> <DF>\n\
533 <E040> <FCFC>\n\
534 endcodespacerange\n";
535
536 fn rksj() -> CidCmap {
537 let data = format!(
538 "{RKSJ_CODESPACES}\
539 1 beginnotdefrange\n<00> <1f> 231\nendnotdefrange\n\
540 3 begincidrange\n\
541 <20> <7d> 231\n\
542 <8140> <817e> 633\n\
543 <e040> <e07e> 100\n\
544 endcidrange\n\
545 1 begincidchar\n<a1> 9000\nendcidchar\n"
546 );
547 CidCmap::parse(data.as_bytes())
548 }
549
550 #[test]
552 fn rksj_codespaces_split_mixed_widths() {
553 let c = rksj();
554 let bytes = [0x41, 0x81, 0x40, 0xA1];
556 assert_eq!(c.code_at(&bytes, 0), (0x41, 1));
557 assert_eq!(c.code_at(&bytes, 1), (0x8140, 2));
558 assert_eq!(c.code_at(&bytes, 3), (0xA1, 1));
559 }
560
561 #[test]
563 fn cidrange_arithmetic_offsets_within_the_range() {
564 let c = rksj();
565 assert_eq!(c.cid(0x20, 1), Some(231));
566 assert_eq!(c.cid(0x7d, 1), Some(324));
567 assert_eq!(c.cid(0x8140, 2), Some(633));
568 assert_eq!(c.cid(0x8163, 2), Some(633 + 0x23));
569 assert_eq!(c.cid(0xe041, 2), Some(101));
570 assert_eq!(c.cid(0x82FF, 2), None);
571 }
572
573 #[test]
575 fn cidchar_singletons_map() {
576 let c = rksj();
577 assert_eq!(c.cid(0xA1, 1), Some(9000));
578 }
579
580 #[test]
582 fn notdef_ranges_lose_to_real_mappings() {
583 let data = format!(
584 "{RKSJ_CODESPACES}\
585 1 beginnotdefrange\n<00> <1f> 231\nendnotdefrange\n\
586 1 begincidrange\n<10> <11> 5\nendcidrange\n"
587 );
588 let c = CidCmap::parse(data.as_bytes());
589 assert_eq!(c.cid(0x10, 1), Some(5)); assert_eq!(c.cid(0x12, 1), Some(231)); assert_eq!(c.cid(0x20, 1), None);
592 }
593
594 #[test]
596 fn a_one_byte_code_and_a_two_byte_code_with_equal_values_stay_apart() {
597 let data = "2 begincodespacerange <00> <20> <4000> <41FF> endcodespacerange\n\
598 2 begincidrange <20> <20> 7 <0020> <0020> 9 endcidrange";
599 let c = CidCmap::parse(data.as_bytes());
600 assert_eq!(c.cid(0x20, 1), Some(7));
601 assert_eq!(c.cid(0x20, 2), Some(9));
602 }
603
604 #[test]
606 fn usecmap_layers_child_over_parent() {
607 let parent = Arc::new(CidCmap::parse(
608 format!(
609 "{RKSJ_CODESPACES}\
610 2 begincidrange <8140> <817e> 633 <20> <7d> 231 endcidrange"
611 )
612 .as_bytes(),
613 ));
614 let mut resolve = |name: &str| (name == "90ms-RKSJ-H").then(|| Arc::clone(&parent));
615 let child = CidCmap::parse_with(
616 b"/90ms-RKSJ-H usecmap\n\
617 /WMode 1 def\n\
618 1 begincidrange <8141> <8142> 7887 endcidrange",
619 None,
620 &mut resolve,
621 );
622 assert!(child.vertical());
623 assert_eq!(child.cid(0x8141, 2), Some(7887)); assert_eq!(child.cid(0x8140, 2), Some(633)); assert_eq!(child.cid(0x21, 1), Some(232)); assert_eq!(child.code_at(&[0x81, 0x40], 0), (0x8140, 2)); assert_eq!(child.parent().map(|p| p.cid(0x8141, 2)), Some(Some(634)));
628 }
629
630 #[test]
632 fn wmode_reads_and_defaults_horizontal() {
633 assert!(!CidCmap::parse(b"/WMode 0 def").vertical());
634 assert!(CidCmap::parse(b"/WMode 1 def").vertical());
635 assert!(!CidCmap::parse(b"").vertical());
636 assert!(CidCmap::identity(true).vertical());
637 }
638
639 #[test]
641 fn identity_maps_code_to_cid() {
642 let c = CidCmap::identity(false);
643 assert_eq!(c.code_at(&[0x12, 0x34], 0), (0x1234, 2));
644 assert_eq!(c.cid(0x1234, 2), Some(0x1234));
645 assert!(!c.single_byte(0x20));
646 }
647
648 #[test]
650 fn word_spacing_evidence_is_a_one_byte_codespace() {
651 assert!(rksj().single_byte(0x20));
652 assert!(!rksj().single_byte(0x81));
653 }
654
655 #[test]
659 fn splitting_always_consumes_at_least_one_byte() {
660 let cmaps = [rksj(), CidCmap::identity(false), CidCmap::parse(b"")];
661 for c in &cmaps {
662 for bytes in [&[0x81][..], &[0xFF][..], &[0x00, 0x81][..]] {
663 let mut pos = 0;
664 let mut codes = 0;
665 while pos < bytes.len() {
666 let (_, n) = c.code_at(bytes, pos);
667 assert!(n >= 1);
668 pos += usize::from(n).min(bytes.len() - pos);
669 codes += 1;
670 }
671 assert!(codes >= 1);
672 }
673 }
674 assert_eq!(rksj().code_at(&[0x81], 0), (0x81, 1));
676 }
677
678 #[test]
680 fn a_truncated_section_keeps_what_parsed_so_far() {
681 let c = CidCmap::parse(b"2 begincidrange <20> <7d> 231 <8140> <81");
682 assert_eq!(c.cid(0x20, 1), Some(231));
683 assert_eq!(c.cid(0x8140, 2), None);
684 let garbage = CidCmap::parse(b"\xFF\xFE ) ] >> begincidchar <41> 12 endcidchar");
685 assert_eq!(garbage.cid(0x41, 1), Some(12));
686 assert!(CidCmap::parse(b"").is_empty());
687 }
688}