• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * ttinterp.h
4  *
5  *   TrueType bytecode interpreter (specification).
6  *
7  * Copyright (C) 1996-2021 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 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
102 
103   /**************************************************************************
104    *
105    * These structures define rules used to tweak subpixel hinting for
106    * various fonts.  "", 0, "", NULL value indicates to match any value.
107    */
108 
109 #define SPH_MAX_NAME_SIZE      32
110 #define SPH_MAX_CLASS_MEMBERS  100
111 
112   typedef struct  SPH_TweakRule_
113   {
114     const char      family[SPH_MAX_NAME_SIZE];
115     const FT_UInt   ppem;
116     const char      style[SPH_MAX_NAME_SIZE];
117     const FT_ULong  glyph;
118 
119   } SPH_TweakRule;
120 
121 
122   typedef struct  SPH_ScaleRule_
123   {
124     const char      family[SPH_MAX_NAME_SIZE];
125     const FT_UInt   ppem;
126     const char      style[SPH_MAX_NAME_SIZE];
127     const FT_ULong  glyph;
128     const FT_ULong  scale;
129 
130   } SPH_ScaleRule;
131 
132 
133   typedef struct  SPH_Font_Class_
134   {
135     const char  name[SPH_MAX_NAME_SIZE];
136     const char  member[SPH_MAX_CLASS_MEMBERS][SPH_MAX_NAME_SIZE];
137 
138   } SPH_Font_Class;
139 
140 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
141 
142 
143   /**************************************************************************
144    *
145    * The main structure for the interpreter which collects all necessary
146    * variables and states.
147    *
148    * Members that are initialized by `TT_Load_Context` are marked with '!'.
149    * Members that are initialized by `TT_Run_Context` are marked with '@'.
150    */
151   typedef struct  TT_ExecContextRec_
152   {
153     TT_Face            face;       /* ! */
154     TT_Size            size;       /* ! */
155     FT_Memory          memory;
156 
157     /* instructions state */
158 
159     FT_Error           error;      /* last execution error */
160 
161     FT_Long            top;        /* @ top of exec. stack */
162 
163     FT_Long            stackSize;  /* ! size of exec. stack */
164     FT_Long*           stack;      /* ! current exec. stack */
165 
166     FT_Long            args;
167     FT_Long            new_top;    /* new top after exec. */
168 
169     TT_GlyphZoneRec    zp0,        /* @! zone records */
170                        zp1,        /* @!              */
171                        zp2,        /* @!              */
172                        pts,        /*  !              */
173                        twilight;   /*  !              */
174 
175     FT_Long            pointSize;  /* ! in 26.6 format */
176     FT_Size_Metrics    metrics;    /* !                */
177     TT_Size_Metrics    tt_metrics; /* ! size metrics   */
178 
179     TT_GraphicsState   GS;         /* !@ current graphics state */
180 
181     FT_Int             iniRange;  /* initial code range number   */
182     FT_Int             curRange;  /* current code range number   */
183     FT_Byte*           code;      /* current code range          */
184     FT_Long            IP;        /* current instruction pointer */
185     FT_Long            codeSize;  /* size of current range       */
186 
187     FT_Byte            opcode;    /* current opcode              */
188     FT_Int             length;    /* length of current opcode    */
189 
190     FT_Bool            step_ins;  /* true if the interpreter must */
191                                   /* increment IP after ins. exec */
192     FT_ULong           cvtSize;   /* ! */
193     FT_Long*           cvt;       /* ! */
194     FT_ULong           glyfCvtSize;
195     FT_Long*           glyfCvt;   /* cvt working copy for glyph */
196     FT_Long*           origCvt;
197 
198     FT_UInt            glyphSize; /* ! glyph instructions buffer size */
199     FT_Byte*           glyphIns;  /* ! glyph instructions buffer      */
200 
201     FT_UInt            numFDefs;  /* ! number of function defs         */
202     FT_UInt            maxFDefs;  /* ! maximum number of function defs */
203     TT_DefArray        FDefs;     /*   table of FDefs entries          */
204 
205     FT_UInt            numIDefs;  /* ! number of instruction defs */
206     FT_UInt            maxIDefs;  /* ! maximum number of ins defs */
207     TT_DefArray        IDefs;     /*   table of IDefs entries     */
208 
209     FT_UInt            maxFunc;   /* ! maximum function index    */
210     FT_UInt            maxIns;    /* ! maximum instruction index */
211 
212     FT_Int             callTop,    /* @ top of call stack during execution */
213                        callSize;   /*   size of call stack                 */
214     TT_CallStack       callStack;  /*   call stack                         */
215 
216     FT_UShort          maxPoints;    /* capacity of this context's `pts' */
217     FT_Short           maxContours;  /* record, expressed in points and  */
218                                      /* contours.                        */
219 
220     TT_CodeRangeTable  codeRangeTable;  /* ! table of valid code ranges */
221                                         /*   useful for the debugger    */
222 
223     FT_UShort          storeSize;    /* ! size of current storage */
224     FT_Long*           storage;      /* ! storage area            */
225     FT_UShort          glyfStoreSize;
226     FT_Long*           glyfStorage;  /* storage working copy for glyph */
227     FT_Long*           origStorage;
228 
229     FT_F26Dot6         period;     /* values used for the */
230     FT_F26Dot6         phase;      /* `SuperRounding'     */
231     FT_F26Dot6         threshold;
232 
233     FT_Bool            instruction_trap; /* ! If `True', the interpreter   */
234                                          /*   exits after each instruction */
235 
236     TT_GraphicsState   default_GS;       /* graphics state resulting from   */
237                                          /* the prep program                */
238     FT_Bool            is_composite;     /* true if the glyph is composite  */
239     FT_Bool            pedantic_hinting; /* true if pedantic interpretation */
240 
241     /* latest interpreter additions */
242 
243     FT_Long            F_dot_P;    /* dot product of freedom and projection */
244                                    /* vectors                               */
245     TT_Round_Func      func_round; /* current rounding function             */
246 
247     TT_Project_Func    func_project,   /* current projection function */
248                        func_dualproj,  /* current dual proj. function */
249                        func_freeProj;  /* current freedom proj. func  */
250 
251     TT_Move_Func       func_move;      /* current point move function     */
252     TT_Move_Func       func_move_orig; /* move original position function */
253 
254     TT_Cur_Ppem_Func   func_cur_ppem;  /* get current proj. ppem value  */
255 
256     TT_Get_CVT_Func    func_read_cvt;  /* read a cvt entry              */
257     TT_Set_CVT_Func    func_write_cvt; /* write a cvt entry (in pixels) */
258     TT_Set_CVT_Func    func_move_cvt;  /* incr a cvt entry (in pixels)  */
259 
260     FT_Bool            grayscale;      /* bi-level hinting and */
261                                        /* grayscale rendering  */
262 
263 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
264     /*
265      * FreeType supports ClearType-like hinting of TrueType fonts through
266      * the version 40 interpreter.  This is achieved through several hacks
267      * in the base (v35) interpreter, as detailed below.
268      *
269      * ClearType is an umbrella term for several rendering techniques
270      * employed by Microsoft's various GUI and rendering toolkit
271      * implementations, most importantly: subpixel rendering for using the
272      * RGB subpixels of LCDs to approximately triple the perceived
273      * resolution on the x-axis and subpixel hinting for positioning stems
274      * on subpixel borders.  TrueType programming is explicit, i.e., fonts
275      * must be programmed to take advantage of ClearType's possibilities.
276      *
277      * When ClearType was introduced, it seemed unlikely that all fonts
278      * would be reprogrammed, so Microsoft decided to implement a backward
279      * compatibility mode.  It employs several simple to complicated
280      * assumptions and tricks, many of them font-dependent, that modify the
281      * interpretation of the bytecode contained in these fonts to retrofit
282      * them into a ClearType-y look.  The quality of the results varies.
283      * Most (web)fonts that were released since then have come to rely on
284      * these hacks to render correctly, even some of Microsoft's flagship
285      * fonts (e.g., Calibri, Cambria, Segoe UI).
286      *
287      * FreeType's minimal subpixel hinting code (interpreter version 40)
288      * employs a small list of font-agnostic hacks loosely based on the
289      * public information available on Microsoft's compatibility mode[2].
290      * The focus is on modern (web)fonts rather than legacy fonts that were
291      * made for monochrome rendering.  It will not match ClearType rendering
292      * exactly.  Unlike the `Infinality' code (interpreter version 38) that
293      * came before, it will not try to toggle hacks for specific fonts for
294      * performance and complexity reasons.  It will fall back to version 35
295      * behavior for tricky fonts[1] or when monochrome rendering is
296      * requested.
297      *
298      * Major hacks
299      *
300      * - Any point movement on the x axis is ignored (cf. `Direct_Move' and
301      *   `Direct_Move_X').  This has the smallest code footprint and single
302      *   biggest effect.  The ClearType way to increase resolution is
303      *   supersampling the x axis, the FreeType way is ignoring instructions
304      *   on the x axis, which gives the same result in the majority of
305      *   cases.
306      *
307      * - Points are not moved post-IUP (neither on the x nor on the y axis),
308      *   except the x component of diagonal moves post-IUP (cf.
309      *   `Direct_Move', `Direct_Move_Y', `Move_Zp2_Point').  Post-IUP
310      *   changes are commonly used to `fix' pixel patterns which has little
311      *   use outside monochrome rendering.
312      *
313      * - SHPIX and DELTAP don't execute unless moving a composite on the
314      *   y axis or moving a previously y touched point.  SHPIX additionally
315      *   denies movement on the x axis (cf. `Ins_SHPIX' and `Ins_DELTAP').
316      *   Both instructions are commonly used to `fix' pixel patterns for
317      *   monochrome or Windows's GDI rendering but make little sense for
318      *   FreeType rendering.  Both can distort the outline.  See [2] for
319      *   details.
320      *
321      * - The hdmx table and modifications to phantom points are ignored.
322      *   Bearings and advance widths remain unchanged (except rounding them
323      *   outside the interpreter!), cf. `compute_glyph_metrics' and
324      *   `TT_Hint_Glyph'.  Letting non-native-ClearType fonts modify spacing
325      *   might mess up spacing.
326      *
327      * Minor hacks
328      *
329      * - FLIPRGON, FLIPRGOFF, and FLIPPT don't execute post-IUP.  This
330      *   prevents dents in e.g. Arial-Regular's `D' and `G' glyphs at
331      *   various sizes.
332      *
333      * (Post-IUP is the state after both IUP[x] and IUP[y] have been
334      * executed.)
335      *
336      * The best results are achieved for fonts that were from the outset
337      * designed with ClearType in mind, meaning they leave the x axis mostly
338      * alone and don't mess with the `final' outline to produce more
339      * pleasing pixel patterns.  The harder the designer tried to produce
340      * very specific patterns (`superhinting') for pre-ClearType-displays,
341      * the worse the results.
342      *
343      * Microsoft defines a way to turn off backward compatibility and
344      * interpret instructions as before (called `native ClearType')[2][3].
345      * The font designer then regains full control and is responsible for
346      * making the font work correctly with ClearType without any
347      * hand-holding by the interpreter or rasterizer[4].  The v40
348      * interpreter assumes backward compatibility by default, which can be
349      * turned off the same way by executing the following in the control
350      * program (cf. `Ins_INSTCTRL').
351      *
352      *   #PUSH 4,3
353      *   INSTCTRL[]
354      *
355      * [1] Tricky fonts as FreeType defines them rely on the bytecode
356      *     interpreter to display correctly.  Hacks can interfere with them,
357      *     so they get treated like native ClearType fonts (v40 with
358      *     backward compatibility turned off).  Cf. `TT_RunIns'.
359      *
360      * [2] Proposed by Microsoft's Greg Hitchcock in
361      *     https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
362      *
363      * [3] Beat Stamm describes it in more detail:
364      *     http://rastertragedy.com/RTRCh4.htm#Sec12.
365      *
366      * [4] The list of `native ClearType' fonts is small at the time of this
367      *     writing; I found the following on a Windows 10 Update 1511
368      *     installation: Constantia, Corbel, Sitka, Malgun Gothic, Microsoft
369      *     JhengHei (Bold and UI Bold), Microsoft YaHei (Bold and UI Bold),
370      *     SimSun, NSimSun, and Yu Gothic.
371      *
372      */
373 
374     /* Using v40 implies subpixel hinting, unless FT_RENDER_MODE_MONO has been
375      * requested.  Used to detect interpreter */
376     /* version switches.  `_lean' to differentiate from the Infinality */
377     /* `subpixel_hinting', which is managed differently.               */
378     FT_Bool            subpixel_hinting_lean;
379 
380     /* Long side of a LCD subpixel is vertical (e.g., screen is rotated). */
381     /* `_lean' to differentiate from the Infinality `vertical_lcd', which */
382     /* is managed differently.                                            */
383     FT_Bool            vertical_lcd_lean;
384 
385     /* Default to backward compatibility mode in v40 interpreter.  If   */
386     /* this is false, it implies the interpreter is in v35 or in native */
387     /* ClearType mode.                                                  */
388     FT_Bool            backward_compatibility;
389 
390     /* Useful for detecting and denying post-IUP trickery that is usually */
391     /* used to fix pixel patterns (`superhinting').                       */
392     FT_Bool            iupx_called;
393     FT_Bool            iupy_called;
394 
395     /* ClearType hinting and grayscale rendering, as used by Universal */
396     /* Windows Platform apps (Windows 8 and above).  Like the standard */
397     /* colorful ClearType mode, it utilizes a vastly increased virtual */
398     /* resolution on the x axis.  Different from bi-level hinting and  */
399     /* grayscale rendering, the old mode from Win9x days that roughly  */
400     /* adheres to the physical pixel grid on both axes.                */
401     FT_Bool            grayscale_cleartype;
402 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
403 
404 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
405     TT_Round_Func      func_round_sphn;   /* subpixel rounding function */
406 
407     FT_Bool            subpixel_hinting;  /* Using subpixel hinting?       */
408     FT_Bool            ignore_x_mode;     /* Standard rendering mode for   */
409                                           /* subpixel hinting.  On if gray */
410                                           /* or subpixel hinting is on.    */
411 
412     /* The following 6 aren't fully implemented but here for MS rasterizer */
413     /* compatibility.                                                      */
414     FT_Bool            compatible_widths;     /* compatible widths?        */
415     FT_Bool            symmetrical_smoothing; /* symmetrical_smoothing?    */
416     FT_Bool            bgr;                   /* bgr instead of rgb?       */
417     FT_Bool            vertical_lcd;          /* long side of LCD subpixel */
418                                               /* rectangles is horizontal  */
419     FT_Bool            subpixel_positioned;   /* subpixel positioned       */
420                                               /* (DirectWrite ClearType)?  */
421     FT_Bool            gray_cleartype;        /* ClearType hinting but     */
422                                               /* grayscale rendering       */
423 
424     FT_Int             rasterizer_version;    /* MS rasterizer version     */
425 
426     FT_Bool            iup_called;            /* IUP called for glyph?     */
427 
428     FT_ULong           sph_tweak_flags;       /* flags to control          */
429                                               /* hint tweaks               */
430 
431     FT_ULong           sph_in_func_flags;     /* flags to indicate if in   */
432                                               /* special functions         */
433 
434 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
435 
436     /* We maintain two counters (in addition to the instruction counter) */
437     /* that act as loop detectors for LOOPCALL and jump opcodes with     */
438     /* negative arguments.                                               */
439     FT_ULong           loopcall_counter;
440     FT_ULong           loopcall_counter_max;
441     FT_ULong           neg_jump_counter;
442     FT_ULong           neg_jump_counter_max;
443 
444   } TT_ExecContextRec;
445 
446 
447   extern const TT_GraphicsState  tt_default_graphics_state;
448 
449 
450 #ifdef TT_USE_BYTECODE_INTERPRETER
451   FT_LOCAL( void )
452   TT_Goto_CodeRange( TT_ExecContext  exec,
453                      FT_Int          range,
454                      FT_Long         IP );
455 
456   FT_LOCAL( void )
457   TT_Set_CodeRange( TT_ExecContext  exec,
458                     FT_Int          range,
459                     void*           base,
460                     FT_Long         length );
461 
462   FT_LOCAL( void )
463   TT_Clear_CodeRange( TT_ExecContext  exec,
464                       FT_Int          range );
465 
466 
467   FT_LOCAL( FT_Error )
468   Update_Max( FT_Memory  memory,
469               FT_ULong*  size,
470               FT_ULong   multiplier,
471               void*      _pbuff,
472               FT_ULong   new_max );
473 #endif /* TT_USE_BYTECODE_INTERPRETER */
474 
475 
476   /**************************************************************************
477    *
478    * @Function:
479    *   TT_New_Context
480    *
481    * @Description:
482    *   Create a `TT_ExecContext`.  Note that there is now an execution
483    *   context per `TT_Size` that is not shared among faces.
484    *
485    * @Input:
486    *   driver ::
487    *     A handle to the driver, used for memory allocation.
488    *
489    * @Return:
490    *   A handle to a new empty execution context.
491    *
492    * @Note:
493    *   Only the glyph loader and debugger should call this function.
494    *   (And right now only the glyph loader uses it.)
495    */
496   FT_EXPORT( TT_ExecContext )
497   TT_New_Context( TT_Driver  driver );
498 
499 
500 #ifdef TT_USE_BYTECODE_INTERPRETER
501   FT_LOCAL( void )
502   TT_Done_Context( TT_ExecContext  exec );
503 
504   FT_LOCAL( FT_Error )
505   TT_Load_Context( TT_ExecContext  exec,
506                    TT_Face         face,
507                    TT_Size         size );
508 
509   FT_LOCAL( void )
510   TT_Save_Context( TT_ExecContext  exec,
511                    TT_Size         ins );
512 
513   FT_LOCAL( FT_Error )
514   TT_Run_Context( TT_ExecContext  exec );
515 #endif /* TT_USE_BYTECODE_INTERPRETER */
516 
517 
518   /**************************************************************************
519    *
520    * @Function:
521    *   TT_RunIns
522    *
523    * @Description:
524    *   Executes one or more instruction in the execution context.  This
525    *   is the main function of the TrueType opcode interpreter.
526    *
527    * @Input:
528    *   exec ::
529    *     A handle to the target execution context.
530    *
531    * @Return:
532    *   FreeType error code.  0 means success.
533    *
534    * @Note:
535    *   Only the object manager and debugger should call this function.
536    *
537    *   This function is publicly exported because it is directly
538    *   invoked by the TrueType debugger.
539    */
540   FT_EXPORT( FT_Error )
541   TT_RunIns( TT_ExecContext  exec );
542 
543 
544 FT_END_HEADER
545 
546 #endif /* TTINTERP_H_ */
547 
548 
549 /* END */
550