1 //! TrueType bytecode interpreter.
2 
3 mod arith;
4 mod graphics_state;
5 mod logical;
6 mod stack;
7 
8 use super::{
9     code_state::ProgramKind, error::HintErrorKind, graphics_state::GraphicsState,
10     value_stack::ValueStack,
11 };
12 
13 pub type OpResult = Result<(), HintErrorKind>;
14 
15 /// TrueType bytecode interpreter.
16 pub struct Engine<'a> {
17     graphics_state: GraphicsState<'a>,
18     value_stack: ValueStack<'a>,
19     initial_program: ProgramKind,
20 }
21 
22 #[cfg(test)]
23 use mock::MockEngine;
24 
25 #[cfg(test)]
26 mod mock {
27     use super::{Engine, GraphicsState, ProgramKind, ValueStack};
28 
29     /// Mock engine for testing.
30     pub(super) struct MockEngine {
31         value_stack: Vec<i32>,
32     }
33 
34     impl MockEngine {
new() -> Self35         pub fn new() -> Self {
36             Self {
37                 value_stack: vec![0; 32],
38             }
39         }
40 
engine(&mut self) -> Engine41         pub fn engine(&mut self) -> Engine {
42             Engine {
43                 graphics_state: GraphicsState::default(),
44                 value_stack: ValueStack::new(&mut self.value_stack),
45                 initial_program: ProgramKind::Font,
46             }
47         }
48     }
49 
50     impl Default for MockEngine {
default() -> Self51         fn default() -> Self {
52             Self::new()
53         }
54     }
55 
56     impl<'a> Engine<'a> {
57         /// Helper to push values to the stack, invoke a callback and check
58         /// the expected result.
test_exec( &mut self, push: &[i32], expected_result: impl Into<i32>, mut f: impl FnMut(&mut Engine), )59         pub(super) fn test_exec(
60             &mut self,
61             push: &[i32],
62             expected_result: impl Into<i32>,
63             mut f: impl FnMut(&mut Engine),
64         ) {
65             for &val in push {
66                 self.value_stack.push(val).unwrap();
67             }
68             f(self);
69             assert_eq!(self.value_stack.pop().ok(), Some(expected_result.into()));
70         }
71     }
72 }
73