skrifa/outline/glyf/hint/engine/
dispatch.rs
1use read_fonts::tables::glyf::bytecode::Opcode;
4
5use super::{super::program::Program, Engine, HintError, HintErrorKind, Instruction};
6
7const MAX_RUN_INSTRUCTIONS: usize = 1_000_000;
11
12impl<'a> Engine<'a> {
13 pub fn run_program(&mut self, program: Program, is_pedantic: bool) -> Result<(), HintError> {
15 self.reset(program, is_pedantic);
16 self.run()
17 }
18
19 pub fn reset(&mut self, program: Program, is_pedantic: bool) {
21 self.program.reset(program);
22 self.graphics.reset();
24 self.graphics.is_pedantic = is_pedantic;
25 self.loop_budget.reset();
26 match program {
28 Program::Font => {
29 self.definitions.functions.reset();
30 self.definitions.instructions.reset();
31 }
32 Program::ControlValue => {
33 self.graphics.backward_compatibility = false;
34 }
35 Program::Glyph => {
36 if self.graphics.instruct_control & 2 != 0 {
39 self.graphics.reset_retained();
40 }
41 if self.graphics.target.preserve_linear_metrics() {
43 self.graphics.backward_compatibility = true;
44 } else if self.graphics.target.is_smooth() {
45 self.graphics.backward_compatibility =
46 (self.graphics.instruct_control & 0x4) == 0;
47 } else {
48 self.graphics.backward_compatibility = false;
49 }
50 }
51 }
52 }
53
54 pub fn run(&mut self) -> Result<(), HintError> {
56 let mut count = 0;
57 while let Some(ins) = self.decode() {
58 let ins = ins?;
59 self.dispatch(&ins)?;
60 count += 1;
61 if count > MAX_RUN_INSTRUCTIONS {
62 return Err(HintError {
63 program: self.program.current,
64 glyph_id: None,
65 pc: ins.pc,
66 opcode: Some(ins.opcode),
67 kind: HintErrorKind::ExceededExecutionBudget,
68 });
69 }
70 }
71 Ok(())
72 }
73
74 pub fn decode(&mut self) -> Option<Result<Instruction<'a>, HintError>> {
76 let ins = self.program.decoder.decode()?;
77 Some(ins.map_err(|_| HintError {
78 program: self.program.current,
79 glyph_id: None,
80 pc: self.program.decoder.pc,
81 opcode: None,
82 kind: HintErrorKind::UnexpectedEndOfBytecode,
83 }))
84 }
85
86 pub fn dispatch(&mut self, ins: &Instruction) -> Result<(), HintError> {
88 let current_program = self.program.current;
89 self.dispatch_inner(ins).map_err(|kind| HintError {
90 program: current_program,
91 glyph_id: None,
92 pc: ins.pc,
93 opcode: Some(ins.opcode),
94 kind,
95 })
96 }
97
98 fn dispatch_inner(&mut self, ins: &Instruction) -> Result<(), HintErrorKind> {
99 use Opcode::*;
100 let opcode = ins.opcode;
101 let raw_opcode = opcode as u8;
102 match ins.opcode {
103 SVTCA0 | SVTCA1 | SPVTCA0 | SPVTCA1 | SFVTCA0 | SFVTCA1 => self.op_svtca(raw_opcode)?,
104 SPVTL0 | SPVTL1 | SFVTL0 | SFVTL1 => self.op_svtl(raw_opcode)?,
105 SPVFS => self.op_spvfs()?,
106 SFVFS => self.op_sfvfs()?,
107 GPV => self.op_gpv()?,
108 GFV => self.op_gfv()?,
109 SFVTPV => self.op_sfvtpv()?,
110 ISECT => self.op_isect()?,
111 SRP0 => self.op_srp0()?,
112 SRP1 => self.op_srp1()?,
113 SRP2 => self.op_srp2()?,
114 SZP0 => self.op_szp0()?,
115 SZP1 => self.op_szp1()?,
116 SZP2 => self.op_szp2()?,
117 SZPS => self.op_szps()?,
118 SLOOP => self.op_sloop()?,
119 RTG => self.op_rtg()?,
120 RTHG => self.op_rthg()?,
121 SMD => self.op_smd()?,
122 ELSE => self.op_else()?,
123 JMPR => self.op_jmpr()?,
124 SCVTCI => self.op_scvtci()?,
125 SSWCI => self.op_sswci()?,
126 SSW => self.op_ssw()?,
127 DUP => self.op_dup()?,
128 POP => self.op_pop()?,
129 CLEAR => self.op_clear()?,
130 SWAP => self.op_swap()?,
131 DEPTH => self.op_depth()?,
132 CINDEX => self.op_cindex()?,
133 MINDEX => self.op_mindex()?,
134 ALIGNPTS => self.op_alignpts()?,
135 UTP => self.op_utp()?,
137 LOOPCALL => self.op_loopcall()?,
138 CALL => self.op_call()?,
139 FDEF => self.op_fdef()?,
140 ENDF => self.op_endf()?,
141 MDAP0 | MDAP1 => self.op_mdap(raw_opcode)?,
142 IUP0 | IUP1 => self.op_iup(raw_opcode)?,
143 SHP0 | SHP1 => self.op_shp(raw_opcode)?,
144 SHC0 | SHC1 => self.op_shc(raw_opcode)?,
145 SHZ0 | SHZ1 => self.op_shz(raw_opcode)?,
146 SHPIX => self.op_shpix()?,
147 IP => self.op_ip()?,
148 MSIRP0 | MSIRP1 => self.op_msirp(raw_opcode)?,
149 ALIGNRP => self.op_alignrp()?,
150 RTDG => self.op_rtdg()?,
151 MIAP0 | MIAP1 => self.op_miap(raw_opcode)?,
152 NPUSHB | NPUSHW => self.op_push(&ins.inline_operands)?,
153 WS => self.op_ws()?,
154 RS => self.op_rs()?,
155 WCVTP => self.op_wcvtp()?,
156 RCVT => self.op_rcvt()?,
157 GC0 | GC1 => self.op_gc(raw_opcode)?,
158 SCFS => self.op_scfs()?,
159 MD0 | MD1 => self.op_md(raw_opcode)?,
160 MPPEM => self.op_mppem()?,
161 MPS => self.op_mps()?,
162 FLIPON => self.op_flipon()?,
163 FLIPOFF => self.op_flipoff()?,
164 DEBUG => {
168 self.value_stack.pop()?;
169 }
170 LT => self.op_lt()?,
171 LTEQ => self.op_lteq()?,
172 GT => self.op_gt()?,
173 GTEQ => self.op_gteq()?,
174 EQ => self.op_eq()?,
175 NEQ => self.op_neq()?,
176 ODD => self.op_odd()?,
177 EVEN => self.op_even()?,
178 IF => self.op_if()?,
179 EIF => self.op_eif()?,
180 AND => self.op_and()?,
181 OR => self.op_or()?,
182 NOT => self.op_not()?,
183 DELTAP1 => self.op_deltap(opcode)?,
184 SDB => self.op_sdb()?,
185 SDS => self.op_sds()?,
186 ADD => self.op_add()?,
187 SUB => self.op_sub()?,
188 DIV => self.op_div()?,
189 MUL => self.op_mul()?,
190 ABS => self.op_abs()?,
191 NEG => self.op_neg()?,
192 FLOOR => self.op_floor()?,
193 CEILING => self.op_ceiling()?,
194 ROUND00 | ROUND01 | ROUND10 | ROUND11 => self.op_round()?,
195 NROUND00 | NROUND01 | NROUND10 | NROUND11 => {}
197 WCVTF => self.op_wcvtf()?,
198 DELTAP2 | DELTAP3 => self.op_deltap(opcode)?,
199 DELTAC1 | DELTAC2 | DELTAC3 => self.op_deltac(opcode)?,
200 SROUND => self.op_sround()?,
201 S45ROUND => self.op_s45round()?,
202 JROT => self.op_jrot()?,
203 JROF => self.op_jrof()?,
204 ROFF => self.op_roff()?,
205 RUTG => self.op_rutg()?,
207 RDTG => self.op_rdtg()?,
208 SANGW => self.op_sangw()?,
209 AA => {}
211 FLIPPT => self.op_flippt()?,
212 FLIPRGON => self.op_fliprgon()?,
213 FLIPRGOFF => self.op_fliprgoff()?,
214 SCANCTRL => self.op_scanctrl()?,
216 SDPVTL0 | SDPVTL1 => self.op_sdpvtl(raw_opcode)?,
217 GETINFO => self.op_getinfo()?,
218 IDEF => self.op_idef()?,
219 ROLL => self.op_roll()?,
220 MAX => self.op_max()?,
221 MIN => self.op_min()?,
222 SCANTYPE => self.op_scantype()?,
223 INSTCTRL => self.op_instctrl()?,
224 GETVARIATION => self.op_getvariation()?,
226 GETDATA => self.op_getdata()?,
227 _ => {
228 if opcode >= MIRP00000 {
231 self.op_mirp(raw_opcode)?
232 } else if opcode >= MDRP00000 {
233 self.op_mdrp(raw_opcode)?
234 } else if opcode >= PUSHB000 {
235 self.op_push(&ins.inline_operands)?;
236 } else {
237 return self.op_unknown(opcode as u8);
238 }
239 }
240 }
241 Ok(())
242 }
243}