Skip to main content

tex_engine/
pdflatex.rs

1/*! Adds support for `pdflatex` nodes and primitive commands to the engine. Requires the `pdflatex` feature to be enabled.
2*/
3pub 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    /// #### Errors
31    /// on LaTeX errors
32    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    /// #### Errors
44    /// on LaTeX errors
45    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/// Example implementation of [`EngineTypes`] for a plain TeX engine.
104#[derive(Copy, Clone, Debug)]
105pub struct DefaultPDFTeXEngineTypes;
106impl EngineTypes for DefaultPDFTeXEngineTypes {
107    type Char = u8;
108    type CSName = InternedCSName<u8>; //InternedString;
109    type Token = super::tex::tokens::CompactToken; //::StandardToken<u8,Self::CSName>;//
110    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>>; //InternedString>;
126}
127
128pub type PlainPDFTeXEngine = DefaultEngine<DefaultPDFTeXEngineTypes>;
129
130//impl PDFTeXEngine for PlainPDFTeXEngine {}
131impl<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}