Skip to main content

pdf_font/cmap/bcmap/
embedded.rs

1use std::ops::Range;
2use std::sync::LazyLock;
3
4use super::huffman::{self, HuffmanTable};
5use super::reader::Reader;
6use crate::cmap::CMapName;
7
8pub(super) static BUNDLE: LazyLock<Bundle> = LazyLock::new(|| {
9    let compressed = include_bytes!("../../../assets/cmaps.brotli");
10    let mut decompressed = Vec::new();
11    let mut reader = compressed.as_slice();
12
13    brotli::BrotliDecompress(&mut reader, &mut decompressed)
14        .expect("embedded cmap bundle decompression failed");
15
16    let mut reader = Reader::new(&decompressed);
17    let huff_size = reader
18        .read_u32()
19        .expect("embedded cmap bundle: missing huffman size") as usize;
20    let huff_data = reader
21        .read_bytes(huff_size)
22        .expect("embedded cmap bundle: truncated huffman data");
23    let (delta_table, count_table) =
24        huffman::decode_tables(huff_data).expect("embedded cmap bundle: corrupt huffman tables");
25
26    let mut entries = Vec::new();
27
28    while !reader.at_end() {
29        let start = reader.position();
30
31        // Skip file magic and version.
32        reader
33            .read_bytes(6)
34            .expect("embedded cmap bundle: truncated entry header");
35        let file_len = reader
36            .read_u32()
37            .expect("embedded cmap bundle: missing file_len") as usize;
38
39        reader
40            .read_bytes(file_len - 10)
41            .expect("embedded cmap bundle: truncated entry data");
42        entries.push(start..start + file_len);
43    }
44
45    Bundle {
46        data: decompressed,
47        delta_table,
48        count_table,
49        entries,
50    }
51});
52
53pub(super) struct Bundle {
54    data: Vec<u8>,
55    pub(super) delta_table: HuffmanTable,
56    pub(super) count_table: HuffmanTable,
57    entries: Vec<Range<usize>>,
58}
59
60/// Load the data for a cmap file, by name.
61pub fn load_embedded(name: CMapName<'_>) -> Option<&'static [u8]> {
62    // Get the index of the font of the cmap in the bundle. They are sorted
63    // alphabetically.
64    let idx = match name {
65        CMapName::N83pvRksjH => 0,
66        CMapName::N90msRksjH => 1,
67        CMapName::N90msRksjV => 2,
68        CMapName::N90mspRksjH => 3,
69        CMapName::N90mspRksjV => 4,
70        CMapName::N90pvRksjH => 5,
71        CMapName::AddRksjH => 6,
72        CMapName::AddRksjV => 7,
73        CMapName::AdobeCns1Ucs2 => 8,
74        CMapName::AdobeGb1Ucs2 => 9,
75        CMapName::AdobeJapan1Ucs2 => 10,
76        CMapName::AdobeKorea1Ucs2 => 11,
77        CMapName::B5pcH => 12,
78        CMapName::B5pcV => 13,
79        CMapName::CnsEucH => 14,
80        CMapName::CnsEucV => 15,
81        CMapName::ETenB5H => 16,
82        CMapName::ETenB5V => 17,
83        CMapName::ETenmsB5H => 18,
84        CMapName::ETenmsB5V => 19,
85        CMapName::EucH => 20,
86        CMapName::EucV => 21,
87        CMapName::ExtRksjH => 22,
88        CMapName::ExtRksjV => 23,
89        CMapName::GbEucH => 24,
90        CMapName::GbEucV => 25,
91        CMapName::GbkEucH => 26,
92        CMapName::GbkEucV => 27,
93        CMapName::Gbk2kH => 28,
94        CMapName::Gbk2kV => 29,
95        CMapName::GbkpEucH => 30,
96        CMapName::GbkpEucV => 31,
97        CMapName::GbpcEucH => 32,
98        CMapName::GbpcEucV => 33,
99        CMapName::H => 34,
100        CMapName::HKscsB5H => 35,
101        CMapName::HKscsB5V => 36,
102        CMapName::IdentityH => 37,
103        CMapName::IdentityV => 38,
104        CMapName::KscEucH => 39,
105        CMapName::KscEucV => 40,
106        CMapName::KscmsUhcH => 41,
107        CMapName::KscmsUhcHwH => 42,
108        CMapName::KscmsUhcHwV => 43,
109        CMapName::KscmsUhcV => 44,
110        CMapName::KscpcEucH => 45,
111        CMapName::UniCnsUcs2H => 46,
112        CMapName::UniCnsUcs2V => 47,
113        CMapName::UniCnsUtf16H => 48,
114        CMapName::UniCnsUtf16V => 49,
115        CMapName::UniGbUcs2H => 50,
116        CMapName::UniGbUcs2V => 51,
117        CMapName::UniGbUtf16H => 52,
118        CMapName::UniGbUtf16V => 53,
119        CMapName::UniJisUcs2H => 54,
120        CMapName::UniJisUcs2HwH => 55,
121        CMapName::UniJisUcs2HwV => 56,
122        CMapName::UniJisUcs2V => 57,
123        CMapName::UniJisUtf16H => 58,
124        CMapName::UniJisUtf16V => 59,
125        CMapName::UniKsUcs2H => 60,
126        CMapName::UniKsUcs2V => 61,
127        CMapName::UniKsUtf16H => 62,
128        CMapName::UniKsUtf16V => 63,
129        CMapName::V => 64,
130        CMapName::Custom(_) => return None,
131    };
132
133    let range = BUNDLE.entries.get(idx)?;
134
135    Some(&BUNDLE.data[range.clone()])
136}