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