1pub mod core;
8pub mod metadata;
9
10mod lzcomp;
11mod stream;
12mod triplet_encodings;
13
14mod ctf {
15 pub(crate) mod sfnt_container;
16 pub(crate) mod ctf_parse;
17 pub(crate) mod ttf_parse;
18}
19
20use core::Error;
21
22use ctf::ctf_parse::parse_ctf;
23use metadata::Metadata;
24use stream::Stream;
25
26const TTEMBED_TTCOMPRESSED: ::core::ffi::c_int = 0x4 as ::core::ffi::c_int;
27const TTEMBED_XORENCRYPTDATA: ::core::ffi::c_int = 0x10000000 as ::core::ffi::c_int;
28
29pub fn eot_to_ttf(data: &[u8]) -> Result<(Metadata, Vec<u8>), Error> {
30 let meta = metadata::read_metadata(data)?;
31 let font_out = decode(
32 &data[meta.font_data_offset as usize..(meta.font_data_offset + meta.font_data_size) as usize],
33 meta.flags & TTEMBED_TTCOMPRESSED as u32 != 0,
34 meta.flags & TTEMBED_XORENCRYPTDATA as u32 != 0,
35 )?;
36 Ok((meta, font_out))
37}
38
39pub fn decode(data: &[u8], is_compressed: bool, is_encrypted: bool) -> Result<Vec<u8>, Error> {
40 const ENCRYPTION_KEY: u8 = 0x50;
41
42 let final_out_buffer: Vec<u8>;
43
44 let mut buf = Vec::from(data);
45 if is_encrypted {
46 for byte in &mut buf {
47 *byte ^= ENCRYPTION_KEY;
48 }
49 }
50
51 if is_compressed {
52 let len = buf.len();
53 let mut s_buf = Stream::new(0);
54 s_buf.buf = buf;
55 let ctfs = lzcomp::unpack_mtx(&mut s_buf, len as _)?;
56
57 let mut streams: [Stream; 3] = [Stream::new2(0, 0), Stream::new2(0, 0), Stream::new2(0, 0)];
58 for (stream, ctf) in streams.iter_mut().zip(ctfs.into_iter()) {
59 stream.buf = ctf;
60 }
61 let mut ctr = parse_ctf(&mut streams)?;
62 final_out_buffer = ctr.dump_to_vec()?;
63 } else {
64 final_out_buffer = buf;
65 }
66
67 Ok(final_out_buffer)
68}