1/****************************************************************************
2 *
3 * ttinterp.h
4 *
5 * TrueType bytecode interpreter (specification).
6 *
7 * Copyright (C) 1996-2023 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
10 * This file is part of the FreeType project, and may only be used,
11 * modified, and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
15 *
16 */
17
18
19#ifndef TTINTERP_H_
20#define TTINTERP_H_
21
22#include "ttobjs.h"
23
24
25FT_BEGIN_HEADER
26
27
28 /**************************************************************************
29 *
30 * Rounding mode constants.
31 */
32#define TT_Round_Off 5
33#define TT_Round_To_Half_Grid 0
34#define TT_Round_To_Grid 1
35#define TT_Round_To_Double_Grid 2
36#define TT_Round_Up_To_Grid 4
37#define TT_Round_Down_To_Grid 3
38#define TT_Round_Super 6
39#define TT_Round_Super_45 7
40
41
42 /**************************************************************************
43 *
44 * Function types used by the interpreter, depending on various modes
45 * (e.g. the rounding mode, whether to render a vertical or horizontal
46 * line etc).
47 *
48 */
49
50 /* Rounding function */
51 typedef FT_F26Dot6
52 (*TT_Round_Func)( TT_ExecContext exc,
53 FT_F26Dot6 distance,
54 FT_Int color );
55
56 /* Point displacement along the freedom vector routine */
57 typedef void
58 (*TT_Move_Func)( TT_ExecContext exc,
59 TT_GlyphZone zone,
60 FT_UShort point,
61 FT_F26Dot6 distance );
62
63 /* Distance projection along one of the projection vectors */
64 typedef FT_F26Dot6
65 (*TT_Project_Func)( TT_ExecContext exc,
66 FT_Pos dx,
67 FT_Pos dy );
68
69 /* getting current ppem. Take care of non-square pixels if necessary */
70 typedef FT_Long
71 (*TT_Cur_Ppem_Func)( TT_ExecContext exc );
72
73 /* reading a cvt value. Take care of non-square pixels if necessary */
74 typedef FT_F26Dot6
75 (*TT_Get_CVT_Func)( TT_ExecContext exc,
76 FT_ULong idx );
77
78 /* setting or moving a cvt value. Take care of non-square pixels */
79 /* if necessary */
80 typedef void
81 (*TT_Set_CVT_Func)( TT_ExecContext exc,
82 FT_ULong idx,
83 FT_F26Dot6 value );
84
85
86 /**************************************************************************
87 *
88 * This structure defines a call record, used to manage function calls.
89 */
90 typedef struct TT_CallRec_
91 {
92 FT_Int Caller_Range;
93 FT_Long Caller_IP;
94 FT_Long Cur_Count;
95
96 TT_DefRecord *Def; /* either FDEF or IDEF */
97
98 } TT_CallRec, *TT_CallStack;
99
100
101 /**************************************************************************
102 *
103 * The main structure for the interpreter which collects all necessary
104 * variables and states.
105 *
106 * Members that are initialized by `TT_Load_Context` are marked with '!'.
107 * Members that are initialized by `TT_Run_Context` are marked with '@'.
108 */
109 typedef struct TT_ExecContextRec_
110 {
111 TT_Face face; /* ! */
112 TT_Size size; /* ! */
113 FT_Memory memory;
114
115 /* instructions state */
116
117 FT_Error error; /* last execution error */
118
119 FT_Long top; /* @ top of exec. stack */
120
121 FT_Long stackSize; /* ! size of exec. stack */
122 FT_Long* stack; /* ! current exec. stack */
123
124 FT_Long args;
125 FT_Long new_top; /* new top after exec. */
126
127 TT_GlyphZoneRec zp0, /* @! zone records */
128 zp1, /* @! */
129 zp2, /* @! */
130 pts, /* ! */
131 twilight; /* ! */
132
133 FT_Long pointSize; /* ! in 26.6 format */
134 FT_Size_Metrics metrics; /* ! */
135 TT_Size_Metrics tt_metrics; /* ! size metrics */
136
137 TT_GraphicsState GS; /* !@ current graphics state */
138
139 FT_Int iniRange; /* initial code range number */
140 FT_Int curRange; /* current code range number */
141 FT_Byte* code; /* current code range */
142 FT_Long IP; /* current instruction pointer */
143 FT_Long codeSize; /* size of current range */
144
145 FT_Byte opcode; /* current opcode */
146 FT_Int length; /* length of current opcode */
147
148 FT_Bool step_ins; /* true if the interpreter must */
149 /* increment IP after ins. exec */
150 FT_ULong cvtSize; /* ! */
151 FT_Long* cvt; /* ! */
152 FT_ULong glyfCvtSize;
153 FT_Long* glyfCvt; /* cvt working copy for glyph */
154
155 FT_UInt glyphSize; /* ! glyph instructions buffer size */
156 FT_Byte* glyphIns; /* ! glyph instructions buffer */
157
158 FT_UInt numFDefs; /* ! number of function defs */
159 FT_UInt maxFDefs; /* ! maximum number of function defs */
160 TT_DefArray FDefs; /* table of FDefs entries */
161
162 FT_UInt numIDefs; /* ! number of instruction defs */
163 FT_UInt maxIDefs; /* ! maximum number of ins defs */
164 TT_DefArray IDefs; /* table of IDefs entries */
165
166 FT_UInt maxFunc; /* ! maximum function index */
167 FT_UInt maxIns; /* ! maximum instruction index */
168
169 FT_Int callTop, /* @ top of call stack during execution */
170 callSize; /* size of call stack */
171 TT_CallStack callStack; /* call stack */
172
173 FT_UShort maxPoints; /* capacity of this context's `pts' */
174 FT_Short maxContours; /* record, expressed in points and */
175 /* contours. */
176
177 TT_CodeRangeTable codeRangeTable; /* ! table of valid code ranges */
178 /* useful for the debugger */
179
180 FT_UShort storeSize; /* ! size of current storage */
181 FT_Long* storage; /* ! storage area */
182 FT_UShort glyfStoreSize;
183 FT_Long* glyfStorage; /* storage working copy for glyph */
184
185 FT_F26Dot6 period; /* values used for the */
186 FT_F26Dot6 phase; /* `SuperRounding' */
187 FT_F26Dot6 threshold;
188
189 FT_Bool instruction_trap; /* ! If `True', the interpreter */
190 /* exits after each instruction */
191
192 TT_GraphicsState default_GS; /* graphics state resulting from */
193 /* the prep program */
194 FT_Bool is_composite; /* true if the glyph is composite */
195 FT_Bool pedantic_hinting; /* true if pedantic interpretation */
196
197 /* latest interpreter additions */
198
199 FT_Long F_dot_P; /* dot product of freedom and projection */
200 /* vectors */
201 TT_Round_Func func_round; /* current rounding function */
202
203 TT_Project_Func func_project, /* current projection function */
204 func_dualproj, /* current dual proj. function */
205 func_freeProj; /* current freedom proj. func */
206
207 TT_Move_Func func_move; /* current point move function */
208 TT_Move_Func func_move_orig; /* move original position function */
209
210 TT_Cur_Ppem_Func func_cur_ppem; /* get current proj. ppem value */
211
212 TT_Get_CVT_Func func_read_cvt; /* read a cvt entry */
213 TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */
214 TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */
215
216 FT_Bool grayscale; /* bi-level hinting and */
217 /* grayscale rendering */
218
219#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
220 /*
221 * FreeType supports ClearType-like hinting of TrueType fonts through
222 * the version 40 interpreter. This is achieved through several hacks
223 * in the base (v35) interpreter, as detailed below.
224 *
225 * ClearType is an umbrella term for several rendering techniques
226 * employed by Microsoft's various GUI and rendering toolkit
227 * implementations, most importantly: subpixel rendering for using the
228 * RGB subpixels of LCDs to approximately triple the perceived
229 * resolution on the x-axis and subpixel hinting for positioning stems
230 * on subpixel borders. TrueType programming is explicit, i.e., fonts
231 * must be programmed to take advantage of ClearType's possibilities.
232 *
233 * When ClearType was introduced, it seemed unlikely that all fonts
234 * would be reprogrammed, so Microsoft decided to implement a backward
235 * compatibility mode. It employs several simple to complicated
236 * assumptions and tricks, many of them font-dependent, that modify the
237 * interpretation of the bytecode contained in these fonts to retrofit
238 * them into a ClearType-y look. The quality of the results varies.
239 * Most (web)fonts that were released since then have come to rely on
240 * these hacks to render correctly, even some of Microsoft's flagship
241 * fonts (e.g., Calibri, Cambria, Segoe UI).
242 *
243 * FreeType's minimal subpixel hinting code (interpreter version 40)
244 * employs a small list of font-agnostic hacks loosely based on the
245 * public information available on Microsoft's compatibility mode[2].
246 * The focus is on modern (web)fonts rather than legacy fonts that were
247 * made for monochrome rendering. It will not match ClearType rendering
248 * exactly. Unlike the `Infinality' code (interpreter version 38) that
249 * came before, it will not try to toggle hacks for specific fonts for
250 * performance and complexity reasons. It will fall back to version 35
251 * behavior for tricky fonts[1] or when monochrome rendering is
252 * requested.
253 *
254 * Major hacks
255 *
256 * - Any point movement on the x axis is ignored (cf. `Direct_Move' and
257 * `Direct_Move_X'). This has the smallest code footprint and single
258 * biggest effect. The ClearType way to increase resolution is
259 * supersampling the x axis, the FreeType way is ignoring instructions
260 * on the x axis, which gives the same result in the majority of
261 * cases.
262 *
263 * - Points are not moved post-IUP (neither on the x nor on the y axis),
264 * except the x component of diagonal moves post-IUP (cf.
265 * `Direct_Move', `Direct_Move_Y', `Move_Zp2_Point'). Post-IUP
266 * changes are commonly used to `fix' pixel patterns which has little
267 * use outside monochrome rendering.
268 *
269 * - SHPIX and DELTAP don't execute unless moving a composite on the
270 * y axis or moving a previously y touched point. SHPIX additionally
271 * denies movement on the x axis (cf. `Ins_SHPIX' and `Ins_DELTAP').
272 * Both instructions are commonly used to `fix' pixel patterns for
273 * monochrome or Windows's GDI rendering but make little sense for
274 * FreeType rendering. Both can distort the outline. See [2] for
275 * details.
276 *
277 * - The hdmx table and modifications to phantom points are ignored.
278 * Bearings and advance widths remain unchanged (except rounding them
279 * outside the interpreter!), cf. `compute_glyph_metrics' and
280 * `TT_Hint_Glyph'. Letting non-native-ClearType fonts modify spacing
281 * might mess up spacing.
282 *
283 * Minor hacks
284 *
285 * - FLIPRGON, FLIPRGOFF, and FLIPPT don't execute post-IUP. This
286 * prevents dents in e.g. Arial-Regular's `D' and `G' glyphs at
287 * various sizes.
288 *
289 * (Post-IUP is the state after both IUP[x] and IUP[y] have been
290 * executed.)
291 *
292 * The best results are achieved for fonts that were from the outset
293 * designed with ClearType in mind, meaning they leave the x axis mostly
294 * alone and don't mess with the `final' outline to produce more
295 * pleasing pixel patterns. The harder the designer tried to produce
296 * very specific patterns (`superhinting') for pre-ClearType-displays,
297 * the worse the results.
298 *
299 * Microsoft defines a way to turn off backward compatibility and
300 * interpret instructions as before (called `native ClearType')[2][3].
301 * The font designer then regains full control and is responsible for
302 * making the font work correctly with ClearType without any
303 * hand-holding by the interpreter or rasterizer[4]. The v40
304 * interpreter assumes backward compatibility by default, which can be
305 * turned off the same way by executing the following in the control
306 * program (cf. `Ins_INSTCTRL').
307 *
308 * #PUSH 4,3
309 * INSTCTRL[]
310 *
311 * [1] Tricky fonts as FreeType defines them rely on the bytecode
312 * interpreter to display correctly. Hacks can interfere with them,
313 * so they get treated like native ClearType fonts (v40 with
314 * backward compatibility turned off). Cf. `TT_RunIns'.
315 *
316 * [2] Proposed by Microsoft's Greg Hitchcock in
317 * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
318 *
319 * [3] Beat Stamm describes it in more detail:
320 * http://rastertragedy.com/RTRCh4.htm#Sec12.
321 *
322 * [4] The list of `native ClearType' fonts is small at the time of this
323 * writing; I found the following on a Windows 10 Update 1511
324 * installation: Constantia, Corbel, Sitka, Malgun Gothic, Microsoft
325 * JhengHei (Bold and UI Bold), Microsoft YaHei (Bold and UI Bold),
326 * SimSun, NSimSun, and Yu Gothic.
327 *
328 */
329
330 /* Using v40 implies subpixel hinting, unless FT_RENDER_MODE_MONO has been
331 * requested. Used to detect interpreter */
332 /* version switches. `_lean' to differentiate from the Infinality */
333 /* `subpixel_hinting', which is managed differently. */
334 FT_Bool subpixel_hinting_lean;
335
336 /* Long side of a LCD subpixel is vertical (e.g., screen is rotated). */
337 /* `_lean' to differentiate from the Infinality `vertical_lcd', which */
338 /* is managed differently. */
339 FT_Bool vertical_lcd_lean;
340
341 /* Default to backward compatibility mode in v40 interpreter. If */
342 /* this is false, it implies the interpreter is in v35 or in native */
343 /* ClearType mode. */
344 FT_Bool backward_compatibility;
345
346 /* Useful for detecting and denying post-IUP trickery that is usually */
347 /* used to fix pixel patterns (`superhinting'). */
348 FT_Bool iupx_called;
349 FT_Bool iupy_called;
350
351 /* ClearType hinting and grayscale rendering, as used by Universal */
352 /* Windows Platform apps (Windows 8 and above). Like the standard */
353 /* colorful ClearType mode, it utilizes a vastly increased virtual */
354 /* resolution on the x axis. Different from bi-level hinting and */
355 /* grayscale rendering, the old mode from Win9x days that roughly */
356 /* adheres to the physical pixel grid on both axes. */
357 FT_Bool grayscale_cleartype;
358#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
359
360 /* We maintain two counters (in addition to the instruction counter) */
361 /* that act as loop detectors for LOOPCALL and jump opcodes with */
362 /* negative arguments. */
363 FT_ULong loopcall_counter;
364 FT_ULong loopcall_counter_max;
365 FT_ULong neg_jump_counter;
366 FT_ULong neg_jump_counter_max;
367
368 } TT_ExecContextRec;
369
370
371 extern const TT_GraphicsState tt_default_graphics_state;
372
373
374#ifdef TT_USE_BYTECODE_INTERPRETER
375 FT_LOCAL( void )
376 TT_Goto_CodeRange( TT_ExecContext exec,
377 FT_Int range,
378 FT_Long IP );
379
380 FT_LOCAL( void )
381 TT_Set_CodeRange( TT_ExecContext exec,
382 FT_Int range,
383 void* base,
384 FT_Long length );
385
386 FT_LOCAL( void )
387 TT_Clear_CodeRange( TT_ExecContext exec,
388 FT_Int range );
389#endif /* TT_USE_BYTECODE_INTERPRETER */
390
391
392 /**************************************************************************
393 *
394 * @Function:
395 * TT_New_Context
396 *
397 * @Description:
398 * Create a `TT_ExecContext`. Note that there is now an execution
399 * context per `TT_Size` that is not shared among faces.
400 *
401 * @Input:
402 * driver ::
403 * A handle to the driver, used for memory allocation.
404 *
405 * @Return:
406 * A handle to a new empty execution context.
407 *
408 * @Note:
409 * Only the glyph loader and debugger should call this function.
410 * (And right now only the glyph loader uses it.)
411 */
412 FT_EXPORT( TT_ExecContext )
413 TT_New_Context( TT_Driver driver );
414
415
416#ifdef TT_USE_BYTECODE_INTERPRETER
417 FT_LOCAL( void )
418 TT_Done_Context( TT_ExecContext exec );
419
420 FT_LOCAL( FT_Error )
421 TT_Load_Context( TT_ExecContext exec,
422 TT_Face face,
423 TT_Size size );
424
425 FT_LOCAL( void )
426 TT_Save_Context( TT_ExecContext exec,
427 TT_Size ins );
428
429 FT_LOCAL( FT_Error )
430 TT_Run_Context( TT_ExecContext exec );
431#endif /* TT_USE_BYTECODE_INTERPRETER */
432
433
434 /**************************************************************************
435 *
436 * @Function:
437 * TT_RunIns
438 *
439 * @Description:
440 * Executes one or more instruction in the execution context. This
441 * is the main function of the TrueType opcode interpreter.
442 *
443 * @Input:
444 * exec ::
445 * A handle to the target execution context.
446 *
447 * @Return:
448 * FreeType error code. 0 means success.
449 *
450 * @Note:
451 * Only the object manager and debugger should call this function.
452 *
453 * This function is publicly exported because it is directly
454 * invoked by the TrueType debugger.
455 */
456 FT_EXPORT( FT_Error )
457 TT_RunIns( void* exec );
458
459
460FT_END_HEADER
461
462#endif /* TTINTERP_H_ */
463
464
465/* END */
466