xref: /aosp_15_r20/external/freetype/src/truetype/ttinterp.h (revision 63949dbd25bcc50c4e1178497ff9e9574d44fc5a)
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 
25 FT_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 
460 FT_END_HEADER
461 
462 #endif /* TTINTERP_H_ */
463 
464 
465 /* END */
466