1pub mod commands;
4pub mod nodes;
5
6use crate::engine::filesystem::{File, VirtualFile};
7use crate::engine::fontsystem::{Font, TfmFont, TfmFontSystem};
8use crate::engine::gullet::DefaultGullet;
9use crate::engine::mouth::DefaultMouth;
10use crate::engine::stomach::DefaultStomach;
11use crate::engine::utils::outputs::LogOutputs;
12use crate::engine::{filesystem, state, DefaultEngine, EngineReferences, EngineTypes, TeXEngine};
13use crate::prelude::CSName;
14use crate::tex;
15use crate::tex::characters::Character;
16use crate::tex::nodes::vertical::VNode;
17use crate::tex::numerics::{Dim32, Mu, Numeric, TeXDimen, TeXInt};
18use crate::tex::tokens::control_sequences::InternedCSName;
19use crate::utils::errors::{ErrorThrower, TeXResult};
20use md5::Digest;
21use nodes::{MinimalPDFExtension, PDFExtension, PDFNode};
22
23pub trait PDFTeXEngine: TeXEngine
24where
25 <Self::Types as EngineTypes>::Extension: PDFExtension<Self::Types>,
26 <Self::Types as EngineTypes>::CustomNode: From<PDFNode<Self::Types>>,
27 <Self::Types as EngineTypes>::File: FileWithMD5,
28 <Self::Types as EngineTypes>::Font: FontWithLpRp,
29{
30 fn do_file_pdf<
33 F: FnMut(&mut EngineReferences<Self::Types>, VNode<Self::Types>) -> TeXResult<(), Self::Types>,
34 >(
35 &mut self,
36 s: &str,
37 f: F,
38 ) -> TeXResult<(), Self::Types> {
39 *self.get_engine_refs().aux.extension.elapsed() = std::time::Instant::now();
40 self.do_file_default(s, f)
41 }
42
43 fn initialize_pdflatex(&mut self) -> TeXResult<(), Self::Types> {
46 self.initialize_etex_primitives();
47 commands::register_pdftex_primitives(self);
48 self.init_file("pdftexconfig.tex")?;
49 self.load_latex()
50 }
51}
52
53pub trait FileWithMD5: File {
54 fn md5(&self) -> [u8;16];
55}
56impl<C: Character> FileWithMD5 for VirtualFile<C> {
57 fn md5(&self) -> [u8;16] {
58 let mut hasher = md5::Md5::default();
59 if let Some(s) = self.source.as_ref() {
60 for r in s.iter() {
61 for c in r {
62 let c = c.to_char();
63 let mut dst = [0u8; 4];
64 c.encode_utf8(&mut dst);
65 let bts = &dst[.. c.len_utf8()];
66 hasher.update(bts);
67 }
68 }
69 } else if let Ok(s) = std::fs::read(&self.path) {
70 hasher.update(&s);
71 }
72 hasher.finalize().into()
73 }
74}
75
76pub trait FontWithLpRp: Font {
77 fn get_lp(&self, c: Self::Char) -> Self::Int;
78 fn set_lp(&mut self, c: Self::Char, d: Self::Int);
79 fn get_rp(&self, c: Self::Char) -> Self::Int;
80 fn set_rp(&mut self, c: Self::Char, d: Self::Int);
81}
82
83impl<I: TeXInt, D: TeXDimen + Numeric<I>, CS: CSName<u8>> FontWithLpRp for TfmFont<I, D, CS> {
84 fn get_lp(&self, c: Self::Char) -> I {
85 let v = &mut self.muts.write().expect("Error mutating font data").lps;
86 v.get(&c).copied().unwrap_or_default()
87 }
88 fn set_lp(&mut self, c: Self::Char, d: I) {
89 let v = &mut self.muts.write().expect("Error mutating font data").lps;
90 v.insert(c, d);
91 }
92
93 fn get_rp(&self, c: Self::Char) -> I {
94 let v = &mut self.muts.write().expect("Error mutating font data").rps;
95 v.get(&c).copied().unwrap_or_default()
96 }
97 fn set_rp(&mut self, c: Self::Char, d: I) {
98 let v = &mut self.muts.write().expect("Error mutating font data").rps;
99 v.insert(c, d);
100 }
101}
102
103#[derive(Copy, Clone, Debug)]
105pub struct DefaultPDFTeXEngineTypes;
106impl EngineTypes for DefaultPDFTeXEngineTypes {
107 type Char = u8;
108 type CSName = InternedCSName<u8>; type Token = super::tex::tokens::CompactToken; type Extension = MinimalPDFExtension<Self>;
111 type Int = i32;
112 type Dim = Dim32;
113 type MuDim = Mu;
114 type Num = tex::numerics::DefaultNumSet;
115 type State = state::tex_state::DefaultState<Self>;
116 type File = VirtualFile<u8>;
117 type FileSystem = filesystem::NoOutputFileSystem<u8>;
118 type Outputs = LogOutputs;
119 type Mouth = DefaultMouth<Self>;
120 type Gullet = DefaultGullet<Self>;
121 type CustomNode = PDFNode<Self>;
122 type Stomach = DefaultStomach<Self>;
123 type ErrorHandler = ErrorThrower<Self>;
124 type Font = TfmFont<i32, Dim32, InternedCSName<u8>>;
125 type FontSystem = TfmFontSystem<i32, Dim32, InternedCSName<u8>>; }
127
128pub type PlainPDFTeXEngine = DefaultEngine<DefaultPDFTeXEngineTypes>;
129
130impl<A> PDFTeXEngine for A
132where
133 A: TeXEngine,
134 <A::Types as EngineTypes>::Extension: PDFExtension<A::Types>,
135 <A::Types as EngineTypes>::CustomNode: From<PDFNode<A::Types>>,
136 <A::Types as EngineTypes>::File: FileWithMD5,
137 <A::Types as EngineTypes>::Font: FontWithLpRp,
138{
139}