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