Home | History | Annotate | Line # | Download | only in truetype
      1 /****************************************************************************
      2  *
      3  * ttobjs.c
      4  *
      5  *   Objects manager (body).
      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 #include <freetype/internal/ftdebug.h>
     20 #include <freetype/internal/ftstream.h>
     21 #include <freetype/tttags.h>
     22 #include <freetype/internal/sfnt.h>
     23 #include <freetype/ftdriver.h>
     24 
     25 #include "ttgload.h"
     26 #include "ttpload.h"
     27 
     28 #include "tterrors.h"
     29 
     30 #ifdef TT_USE_BYTECODE_INTERPRETER
     31 #include "ttinterp.h"
     32 #endif
     33 
     34 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     35 #include "ttgxvar.h"
     36 #endif
     37 
     38   /**************************************************************************
     39    *
     40    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     41    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     42    * messages during execution.
     43    */
     44 #undef  FT_COMPONENT
     45 #define FT_COMPONENT  ttobjs
     46 
     47 
     48 #ifdef TT_USE_BYTECODE_INTERPRETER
     49 
     50   /**************************************************************************
     51    *
     52    *                      GLYPH ZONE FUNCTIONS
     53    *
     54    */
     55 
     56 
     57   /**************************************************************************
     58    *
     59    * @Function:
     60    *   tt_glyphzone_done
     61    *
     62    * @Description:
     63    *   Deallocate a glyph zone.
     64    *
     65    * @Input:
     66    *   zone ::
     67    *     A pointer to the target glyph zone.
     68    */
     69   FT_LOCAL_DEF( void )
     70   tt_glyphzone_done( TT_GlyphZone  zone )
     71   {
     72     FT_Memory  memory = zone->memory;
     73 
     74 
     75     if ( memory )
     76     {
     77       FT_FREE( zone->contours );
     78       FT_FREE( zone->tags );
     79       FT_FREE( zone->cur );
     80       FT_FREE( zone->org );
     81       FT_FREE( zone->orus );
     82 
     83       zone->max_points   = zone->n_points   = 0;
     84       zone->max_contours = zone->n_contours = 0;
     85       zone->memory       = NULL;
     86     }
     87   }
     88 
     89 
     90   /**************************************************************************
     91    *
     92    * @Function:
     93    *   tt_glyphzone_new
     94    *
     95    * @Description:
     96    *   Allocate a new glyph zone.
     97    *
     98    * @Input:
     99    *   memory ::
    100    *     A handle to the current memory object.
    101    *
    102    *   maxPoints ::
    103    *     The capacity of glyph zone in points.
    104    *
    105    *   maxContours ::
    106    *     The capacity of glyph zone in contours.
    107    *
    108    * @Output:
    109    *   zone ::
    110    *     A pointer to the target glyph zone record.
    111    *
    112    * @Return:
    113    *   FreeType error code.  0 means success.
    114    */
    115   FT_LOCAL_DEF( FT_Error )
    116   tt_glyphzone_new( FT_Memory     memory,
    117                     FT_UShort     maxPoints,
    118                     FT_Short      maxContours,
    119                     TT_GlyphZone  zone )
    120   {
    121     FT_Error  error;
    122 
    123 
    124     FT_ZERO( zone );
    125     zone->memory = memory;
    126 
    127     if ( FT_NEW_ARRAY( zone->org,      maxPoints   ) ||
    128          FT_NEW_ARRAY( zone->cur,      maxPoints   ) ||
    129          FT_NEW_ARRAY( zone->orus,     maxPoints   ) ||
    130          FT_NEW_ARRAY( zone->tags,     maxPoints   ) ||
    131          FT_NEW_ARRAY( zone->contours, maxContours ) )
    132     {
    133       tt_glyphzone_done( zone );
    134     }
    135     else
    136     {
    137       zone->max_points   = maxPoints;
    138       zone->max_contours = maxContours;
    139     }
    140 
    141     return error;
    142   }
    143 #endif /* TT_USE_BYTECODE_INTERPRETER */
    144 
    145 
    146   /* Compare the face with a list of well-known `tricky' fonts. */
    147   /* This list shall be expanded as we find more of them.       */
    148 
    149   static FT_Bool
    150   tt_check_trickyness_family( const FT_String*  name )
    151   {
    152 
    153 #define TRICK_NAMES_MAX_CHARACTERS  19
    154 #define TRICK_NAMES_COUNT           26
    155 
    156     static const char trick_names[TRICK_NAMES_COUNT]
    157                                  [TRICK_NAMES_MAX_CHARACTERS + 1] =
    158     {
    159       /*
    160          PostScript names are given in brackets if they differ from the
    161          family name.  The version numbers, together with the copyright or
    162          release year data, are taken from fonts available to the
    163          developers.
    164 
    165          Note that later versions of the fonts might be no longer tricky;
    166          for example, `MingLiU' version 7.00 (file `mingliu.ttc' from
    167          Windows 7) is an ordinary TTC with non-tricky subfonts.
    168        */
    169 
    170       "cpop",               /* dftt-p7.ttf; version 1.00, 1992 [DLJGyShoMedium] */
    171       "DFGirl-W6-WIN-BF",   /* dftt-h6.ttf; version 1.00, 1993 */
    172       "DFGothic-EB",        /* DynaLab Inc. 1992-1995 */
    173       "DFGyoSho-Lt",        /* DynaLab Inc. 1992-1995 */
    174       "DFHei-Md-HK-BF",     /* maybe DynaLab Inc. */
    175       "DFHSGothic-W5",      /* DynaLab Inc. 1992-1995 */
    176       "DFHSMincho-W3",      /* DynaLab Inc. 1992-1995 */
    177       "DFHSMincho-W7",      /* DynaLab Inc. 1992-1995 */
    178       "DFKaiSho-SB",        /* dfkaisb.ttf */
    179       "DFKaiShu",
    180       "DFKaiShu-Md-HK-BF",  /* maybe DynaLab Inc. */
    181       "DFKai-SB",           /* kaiu.ttf; version 3.00, 1998 [DFKaiShu-SB-Estd-BF] */
    182       "DFMing-Bd-HK-BF",    /* maybe DynaLab Inc. */
    183       "DLC",                /* dftt-m7.ttf; version 1.00, 1993 [DLCMingBold] */
    184                             /* dftt-f5.ttf; version 1.00, 1993 [DLCFongSung] */
    185       "DLCHayMedium",       /* dftt-b5.ttf; version 1.00, 1993 */
    186       "DLCHayBold",         /* dftt-b7.ttf; version 1.00, 1993 */
    187       "DLCKaiMedium",       /* dftt-k5.ttf; version 1.00, 1992 */
    188       "DLCLiShu",           /* dftt-l5.ttf; version 1.00, 1992 */
    189       "DLCRoundBold",       /* dftt-r7.ttf; version 1.00, 1993 */
    190       "HuaTianKaiTi?",      /* htkt2.ttf */
    191       "HuaTianSongTi?",     /* htst3.ttf */
    192       "Ming(for ISO10646)", /* hkscsiic.ttf; version 0.12, 2007 [Ming] */
    193                             /* iicore.ttf; version 0.07, 2007 [Ming] */
    194       "MingLiU",            /* mingliu.ttf */
    195                             /* mingliu.ttc; version 3.21, 2001 */
    196       "MingMedium",         /* dftt-m5.ttf; version 1.00, 1993 [DLCMingMedium] */
    197       "PMingLiU",           /* mingliu.ttc; version 3.21, 2001 */
    198       "MingLi43",           /* mingli.ttf; version 1.00, 1992 */
    199     };
    200 
    201     int  nn;
    202 
    203 
    204     for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ )
    205       if ( ft_strstr( name, trick_names[nn] ) )
    206         return TRUE;
    207 
    208     return FALSE;
    209   }
    210 
    211 
    212   /* XXX: This function should be in the `sfnt' module. */
    213 
    214   /* Some PDF generators clear the checksums in the TrueType header table. */
    215   /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF     */
    216   /* Printer clears the entries for subsetted subtables.  We thus have to  */
    217   /* recalculate the checksums  where necessary.                           */
    218 
    219   static FT_UInt32
    220   tt_synth_sfnt_checksum( FT_Stream  stream,
    221                           FT_ULong   length )
    222   {
    223     FT_Error   error;
    224     FT_UInt32  checksum = 0;
    225     FT_UInt    i;
    226 
    227 
    228     if ( FT_FRAME_ENTER( length ) )
    229       return 0;
    230 
    231     for ( ; length > 3; length -= 4 )
    232       checksum += (FT_UInt32)FT_GET_ULONG();
    233 
    234     for ( i = 3; length > 0; length--, i-- )
    235       checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 );
    236 
    237     FT_FRAME_EXIT();
    238 
    239     return checksum;
    240   }
    241 
    242 
    243   /* XXX: This function should be in the `sfnt' module. */
    244 
    245   static FT_ULong
    246   tt_get_sfnt_checksum( TT_Face    face,
    247                         FT_UShort  i )
    248   {
    249 #if 0 /* if we believe the written value, use following part. */
    250     if ( face->dir_tables[i].CheckSum )
    251       return face->dir_tables[i].CheckSum;
    252 #endif
    253 
    254     if ( !face->goto_table )
    255       return 0;
    256 
    257     if ( face->goto_table( face,
    258                            face->dir_tables[i].Tag,
    259                            face->root.stream,
    260                            NULL ) )
    261       return 0;
    262 
    263     return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream,
    264                                              face->dir_tables[i].Length );
    265   }
    266 
    267 
    268   typedef struct tt_sfnt_id_rec_
    269   {
    270     FT_ULong  CheckSum;
    271     FT_ULong  Length;
    272 
    273   } tt_sfnt_id_rec;
    274 
    275 
    276   static FT_Bool
    277   tt_check_trickyness_sfnt_ids( TT_Face  face )
    278   {
    279 #define TRICK_SFNT_IDS_PER_FACE   3
    280 #define TRICK_SFNT_IDS_NUM_FACES  29
    281 
    282     static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
    283                                        [TRICK_SFNT_IDS_PER_FACE] = {
    284 
    285 #define TRICK_SFNT_ID_cvt   0
    286 #define TRICK_SFNT_ID_fpgm  1
    287 #define TRICK_SFNT_ID_prep  2
    288 
    289       { /* MingLiU 1995 */
    290         { 0x05BCF058UL, 0x000002E4UL }, /* cvt  */
    291         { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
    292         { 0xA344A1EAUL, 0x000001E1UL }  /* prep */
    293       },
    294       { /* MingLiU 1996- */
    295         { 0x05BCF058UL, 0x000002E4UL }, /* cvt  */
    296         { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
    297         { 0xA344A1EBUL, 0x000001E1UL }  /* prep */
    298       },
    299       { /* DFGothic-EB */
    300         { 0x12C3EBB2UL, 0x00000350UL }, /* cvt  */
    301         { 0xB680EE64UL, 0x000087A7UL }, /* fpgm */
    302         { 0xCE939563UL, 0x00000758UL }  /* prep */
    303       },
    304       { /* DFGyoSho-Lt */
    305         { 0x11E5EAD4UL, 0x00000350UL }, /* cvt  */
    306         { 0xCE5956E9UL, 0x0000BC85UL }, /* fpgm */
    307         { 0x8272F416UL, 0x00000045UL }  /* prep */
    308       },
    309       { /* DFHei-Md-HK-BF */
    310         { 0x1257EB46UL, 0x00000350UL }, /* cvt  */
    311         { 0xF699D160UL, 0x0000715FUL }, /* fpgm */
    312         { 0xD222F568UL, 0x000003BCUL }  /* prep */
    313       },
    314       { /* DFHSGothic-W5 */
    315         { 0x1262EB4EUL, 0x00000350UL }, /* cvt  */
    316         { 0xE86A5D64UL, 0x00007940UL }, /* fpgm */
    317         { 0x7850F729UL, 0x000005FFUL }  /* prep */
    318       },
    319       { /* DFHSMincho-W3 */
    320         { 0x122DEB0AUL, 0x00000350UL }, /* cvt  */
    321         { 0x3D16328AUL, 0x0000859BUL }, /* fpgm */
    322         { 0xA93FC33BUL, 0x000002CBUL }  /* prep */
    323       },
    324       { /* DFHSMincho-W7 */
    325         { 0x125FEB26UL, 0x00000350UL }, /* cvt  */
    326         { 0xA5ACC982UL, 0x00007EE1UL }, /* fpgm */
    327         { 0x90999196UL, 0x0000041FUL }  /* prep */
    328       },
    329       { /* DFKaiShu */
    330         { 0x11E5EAD4UL, 0x00000350UL }, /* cvt  */
    331         { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */
    332         { 0x13A42602UL, 0x0000007EUL }  /* prep */
    333       },
    334       { /* DFKaiShu, variant */
    335         { 0x11E5EAD4UL, 0x00000350UL }, /* cvt  */
    336         { 0xA6E78C01UL, 0x00008998UL }, /* fpgm */
    337         { 0x13A42602UL, 0x0000007EUL }  /* prep */
    338       },
    339       { /* DFKaiShu-Md-HK-BF */
    340         { 0x11E5EAD4UL, 0x00000360UL }, /* cvt  */
    341         { 0x9DB282B2UL, 0x0000C06EUL }, /* fpgm */
    342         { 0x53E6D7CAUL, 0x00000082UL }  /* prep */
    343       },
    344       { /* DFMing-Bd-HK-BF */
    345         { 0x1243EB18UL, 0x00000350UL }, /* cvt  */
    346         { 0xBA0A8C30UL, 0x000074ADUL }, /* fpgm */
    347         { 0xF3D83409UL, 0x0000037BUL }  /* prep */
    348       },
    349       { /* DLCLiShu */
    350         { 0x07DCF546UL, 0x00000308UL }, /* cvt  */
    351         { 0x40FE7C90UL, 0x00008E2AUL }, /* fpgm */
    352         { 0x608174B5UL, 0x0000007AUL }  /* prep */
    353       },
    354       { /* DLCHayBold */
    355         { 0xEB891238UL, 0x00000308UL }, /* cvt  */
    356         { 0xD2E4DCD4UL, 0x0000676FUL }, /* fpgm */
    357         { 0x8EA5F293UL, 0x000003B8UL }  /* prep */
    358       },
    359       { /* HuaTianKaiTi */
    360         { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt  */
    361         { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */
    362         { 0x70020112UL, 0x00000008UL }  /* prep */
    363       },
    364       { /* HuaTianSongTi */
    365         { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt  */
    366         { 0x0A5A0483UL, 0x00017C39UL }, /* fpgm */
    367         { 0x70020112UL, 0x00000008UL }  /* prep */
    368       },
    369       { /* NEC fadpop7.ttf */
    370         { 0x00000000UL, 0x00000000UL }, /* cvt  */
    371         { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
    372         { 0xA39B58E3UL, 0x0000117CUL }  /* prep */
    373       },
    374       { /* NEC fadrei5.ttf */
    375         { 0x00000000UL, 0x00000000UL }, /* cvt  */
    376         { 0x33C41652UL, 0x000000E5UL }, /* fpgm */
    377         { 0x26D6C52AUL, 0x00000F6AUL }  /* prep */
    378       },
    379       { /* NEC fangot7.ttf */
    380         { 0x00000000UL, 0x00000000UL }, /* cvt  */
    381         { 0x6DB1651DUL, 0x0000019DUL }, /* fpgm */
    382         { 0x6C6E4B03UL, 0x00002492UL }  /* prep */
    383       },
    384       { /* NEC fangyo5.ttf */
    385         { 0x00000000UL, 0x00000000UL }, /* cvt  */
    386         { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
    387         { 0xDE51FAD0UL, 0x0000117CUL }  /* prep */
    388       },
    389       { /* NEC fankyo5.ttf */
    390         { 0x00000000UL, 0x00000000UL }, /* cvt  */
    391         { 0x85E47664UL, 0x000000E5UL }, /* fpgm */
    392         { 0xA6C62831UL, 0x00001CAAUL }  /* prep */
    393       },
    394       { /* NEC fanrgo5.ttf */
    395         { 0x00000000UL, 0x00000000UL }, /* cvt  */
    396         { 0x2D891CFDUL, 0x0000019DUL }, /* fpgm */
    397         { 0xA0604633UL, 0x00001DE8UL }  /* prep */
    398       },
    399       { /* NEC fangot5.ttc */
    400         { 0x00000000UL, 0x00000000UL }, /* cvt  */
    401         { 0x40AA774CUL, 0x000001CBUL }, /* fpgm */
    402         { 0x9B5CAA96UL, 0x00001F9AUL }  /* prep */
    403       },
    404       { /* NEC fanmin3.ttc */
    405         { 0x00000000UL, 0x00000000UL }, /* cvt  */
    406         { 0x0D3DE9CBUL, 0x00000141UL }, /* fpgm */
    407         { 0xD4127766UL, 0x00002280UL }  /* prep */
    408       },
    409       { /* NEC FA-Gothic, 1996 */
    410         { 0x00000000UL, 0x00000000UL }, /* cvt  */
    411         { 0x4A692698UL, 0x000001F0UL }, /* fpgm */
    412         { 0x340D4346UL, 0x00001FCAUL }  /* prep */
    413       },
    414       { /* NEC FA-Minchou, 1996 */
    415         { 0x00000000UL, 0x00000000UL }, /* cvt  */
    416         { 0xCD34C604UL, 0x00000166UL }, /* fpgm */
    417         { 0x6CF31046UL, 0x000022B0UL }  /* prep */
    418       },
    419       { /* NEC FA-RoundGothicB, 1996 */
    420         { 0x00000000UL, 0x00000000UL }, /* cvt  */
    421         { 0x5DA75315UL, 0x0000019DUL }, /* fpgm */
    422         { 0x40745A5FUL, 0x000022E0UL }  /* prep */
    423       },
    424       { /* NEC FA-RoundGothicM, 1996 */
    425         { 0x00000000UL, 0x00000000UL }, /* cvt  */
    426         { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */
    427         { 0x3900DED3UL, 0x00001E18UL }  /* prep */
    428       },
    429         { /* MINGLI.TTF, 1992 */
    430         { 0x00170003UL, 0x00000060UL }, /* cvt  */
    431         { 0xDBB4306EUL, 0x000058AAUL }, /* fpgm */
    432         { 0xD643482AUL, 0x00000035UL }  /* prep */
    433       }
    434     };
    435 
    436     FT_ULong   checksum;
    437     int        num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
    438     FT_Bool    has_cvt, has_fpgm, has_prep;
    439     FT_UShort  i;
    440     int        j, k;
    441 
    442 
    443     FT_MEM_SET( num_matched_ids, 0,
    444                 sizeof ( int ) * TRICK_SFNT_IDS_NUM_FACES );
    445     has_cvt  = FALSE;
    446     has_fpgm = FALSE;
    447     has_prep = FALSE;
    448 
    449     for ( i = 0; i < face->num_tables; i++ )
    450     {
    451       checksum = 0;
    452 
    453       switch( face->dir_tables[i].Tag )
    454       {
    455       case TTAG_cvt:
    456         k = TRICK_SFNT_ID_cvt;
    457         has_cvt  = TRUE;
    458         break;
    459 
    460       case TTAG_fpgm:
    461         k = TRICK_SFNT_ID_fpgm;
    462         has_fpgm = TRUE;
    463         break;
    464 
    465       case TTAG_prep:
    466         k = TRICK_SFNT_ID_prep;
    467         has_prep = TRUE;
    468         break;
    469 
    470       default:
    471         continue;
    472       }
    473 
    474       for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
    475         if ( face->dir_tables[i].Length == sfnt_id[j][k].Length )
    476         {
    477           if ( !checksum )
    478             checksum = tt_get_sfnt_checksum( face, i );
    479 
    480           if ( sfnt_id[j][k].CheckSum == checksum )
    481             num_matched_ids[j]++;
    482 
    483           if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
    484             return TRUE;
    485         }
    486     }
    487 
    488     for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
    489     {
    490       if ( !has_cvt  && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length )
    491         num_matched_ids[j]++;
    492       if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length )
    493         num_matched_ids[j]++;
    494       if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length )
    495         num_matched_ids[j]++;
    496       if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
    497         return TRUE;
    498     }
    499 
    500     return FALSE;
    501   }
    502 
    503 
    504   static FT_Bool
    505   tt_check_trickyness( FT_Face  face )
    506   {
    507     if ( !face )
    508       return FALSE;
    509 
    510     /* For first, check the face name for quick check. */
    511     if ( face->family_name                               &&
    512          tt_check_trickyness_family( face->family_name ) )
    513       return TRUE;
    514 
    515     /* Type42 fonts may lack `name' tables, we thus try to identify */
    516     /* tricky fonts by checking the checksums of Type42-persistent  */
    517     /* sfnt tables (`cvt', `fpgm', and `prep').                     */
    518     if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) )
    519       return TRUE;
    520 
    521     return FALSE;
    522   }
    523 
    524 
    525   /* Check whether `.notdef' is the only glyph in the `loca' table. */
    526   static FT_Bool
    527   tt_check_single_notdef( FT_Face  ttface )
    528   {
    529     FT_Bool   result = FALSE;
    530 
    531     TT_Face   face = (TT_Face)ttface;
    532     FT_UInt   asize;
    533     FT_ULong  i;
    534     FT_ULong  glyph_index = 0;
    535     FT_UInt   count       = 0;
    536 
    537 
    538     for( i = 0; i < face->num_locations; i++ )
    539     {
    540       tt_face_get_location( face, i, &asize );
    541       if ( asize > 0 )
    542       {
    543         count += 1;
    544         if ( count > 1 )
    545           break;
    546         glyph_index = i;
    547       }
    548     }
    549 
    550     /* Only have a single outline. */
    551     if ( count == 1 )
    552     {
    553       if ( glyph_index == 0 )
    554         result = TRUE;
    555       else
    556       {
    557         /* FIXME: Need to test glyphname == .notdef ? */
    558         FT_Error error;
    559         char buf[8];
    560 
    561 
    562         error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 );
    563         if ( !error                                            &&
    564              buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) )
    565           result = TRUE;
    566       }
    567     }
    568 
    569     return result;
    570   }
    571 
    572 
    573   /**************************************************************************
    574    *
    575    * @Function:
    576    *   tt_face_init
    577    *
    578    * @Description:
    579    *   Initialize a given TrueType face object.
    580    *
    581    * @Input:
    582    *   stream ::
    583    *     The source font stream.
    584    *
    585    *   face_index ::
    586    *     The index of the TrueType font, if we are opening a
    587    *     collection, in bits 0-15.  The numbered instance
    588    *     index~+~1 of a GX (sub)font, if applicable, in bits
    589    *     16-30.
    590    *
    591    *   num_params ::
    592    *     Number of additional generic parameters.  Ignored.
    593    *
    594    *   params ::
    595    *     Additional generic parameters.  Ignored.
    596    *
    597    * @InOut:
    598    *   face ::
    599    *     The newly built face object.
    600    *
    601    * @Return:
    602    *   FreeType error code.  0 means success.
    603    */
    604   FT_LOCAL_DEF( FT_Error )
    605   tt_face_init( FT_Stream      stream,
    606                 FT_Face        ttface,      /* TT_Face */
    607                 FT_Int         face_index,
    608                 FT_Int         num_params,
    609                 FT_Parameter*  params )
    610   {
    611     FT_Error      error;
    612     FT_Library    library;
    613     SFNT_Service  sfnt;
    614     TT_Face       face = (TT_Face)ttface;
    615 
    616 
    617     FT_TRACE2(( "TTF driver\n" ));
    618 
    619     library = ttface->driver->root.library;
    620 
    621     sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
    622     if ( !sfnt )
    623     {
    624       FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" ));
    625       error = FT_THROW( Missing_Module );
    626       goto Exit;
    627     }
    628 
    629     /* create input stream from resource */
    630     if ( FT_STREAM_SEEK( 0 ) )
    631       goto Exit;
    632 
    633     /* check that we have a valid TrueType file */
    634     FT_TRACE2(( "  " ));
    635     error = sfnt->init_face( stream, face, face_index, num_params, params );
    636 
    637     /* Stream may have changed. */
    638     stream = face->root.stream;
    639 
    640     if ( error )
    641       goto Exit;
    642 
    643     /* We must also be able to accept Mac/GX fonts, as well as OT ones. */
    644     /* The 0x00020000 tag is completely undocumented; some fonts from   */
    645     /* Arphic made for Chinese Windows 3.1 have this.                   */
    646     if ( face->format_tag != 0x00010000L  && /* MS fonts                             */
    647          face->format_tag != 0x00020000L  && /* CJK fonts for Win 3.1                */
    648          face->format_tag != TTAG_true    && /* Mac fonts                            */
    649          face->format_tag != TTAG_0xA5kbd && /* `Keyboard.dfont' (legacy Mac OS X)   */
    650          face->format_tag != TTAG_0xA5lst )  /* `LastResort.dfont' (legacy Mac OS X) */
    651     {
    652       FT_TRACE2(( "  not a TTF font\n" ));
    653       goto Bad_Format;
    654     }
    655 
    656 #ifdef TT_USE_BYTECODE_INTERPRETER
    657     ttface->face_flags |= FT_FACE_FLAG_HINTER;
    658 #endif
    659 
    660     /* If we are performing a simple font format check, exit immediately. */
    661     if ( face_index < 0 )
    662       return FT_Err_Ok;
    663 
    664     /* Load font directory */
    665     error = sfnt->load_face( stream, face, face_index, num_params, params );
    666     if ( error )
    667       goto Exit;
    668 
    669     if ( tt_check_trickyness( ttface ) )
    670       ttface->face_flags |= FT_FACE_FLAG_TRICKY;
    671 
    672     error = tt_face_load_hdmx( face, stream );
    673     if ( error )
    674       goto Exit;
    675 
    676     if ( FT_IS_SCALABLE( ttface ) )
    677     {
    678 #ifdef FT_CONFIG_OPTION_INCREMENTAL
    679       if ( !ttface->internal->incremental_interface )
    680 #endif
    681       {
    682         error = tt_face_load_loca( face, stream );
    683 
    684         /* having a (non-zero) `glyf' table without */
    685         /* a `loca' table is not valid              */
    686         if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) )
    687           goto Exit;
    688         if ( error )
    689           goto Exit;
    690       }
    691 
    692       /* `fpgm', `cvt', and `prep' are optional */
    693       error = tt_face_load_cvt( face, stream );
    694       if ( error && FT_ERR_NEQ( error, Table_Missing ) )
    695         goto Exit;
    696 
    697       error = tt_face_load_fpgm( face, stream );
    698       if ( error && FT_ERR_NEQ( error, Table_Missing ) )
    699         goto Exit;
    700 
    701       error = tt_face_load_prep( face, stream );
    702       if ( error && FT_ERR_NEQ( error, Table_Missing ) )
    703         goto Exit;
    704 
    705       /* Check the scalable flag based on `loca'. */
    706 #ifdef FT_CONFIG_OPTION_INCREMENTAL
    707       if ( !ttface->internal->incremental_interface )
    708 #endif
    709       {
    710         if ( ttface->num_fixed_sizes          &&
    711              face->glyph_locations            &&
    712              tt_check_single_notdef( ttface ) )
    713         {
    714           FT_TRACE5(( "tt_face_init:"
    715                       " Only the `.notdef' glyph has an outline.\n"
    716                       "             "
    717                       " Resetting scalable flag to FALSE.\n" ));
    718 
    719           ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
    720         }
    721       }
    722     }
    723 
    724 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    725 
    726     {
    727       FT_UInt  instance_index = (FT_UInt)face_index >> 16;
    728 
    729 
    730       if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
    731            instance_index > 0                )
    732       {
    733         error = TT_Set_Named_Instance( face, instance_index );
    734         if ( error )
    735           goto Exit;
    736 
    737         tt_apply_mvar( face );
    738       }
    739     }
    740 
    741 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
    742 
    743     /* initialize standard glyph loading routines */
    744     TT_Init_Glyph_Loading( face );
    745 
    746   Exit:
    747     return error;
    748 
    749   Bad_Format:
    750     error = FT_THROW( Unknown_File_Format );
    751     goto Exit;
    752   }
    753 
    754 
    755   /**************************************************************************
    756    *
    757    * @Function:
    758    *   tt_face_done
    759    *
    760    * @Description:
    761    *   Finalize a given face object.
    762    *
    763    * @Input:
    764    *   face ::
    765    *     A pointer to the face object to destroy.
    766    */
    767   FT_LOCAL_DEF( void )
    768   tt_face_done( FT_Face  ttface )           /* TT_Face */
    769   {
    770     TT_Face       face = (TT_Face)ttface;
    771     FT_Memory     memory;
    772     FT_Stream     stream;
    773     SFNT_Service  sfnt;
    774 
    775 
    776     if ( !face )
    777       return;
    778 
    779     memory = ttface->memory;
    780     stream = ttface->stream;
    781     sfnt   = (SFNT_Service)face->sfnt;
    782 
    783     /* for `extended TrueType formats' (i.e. compressed versions) */
    784     if ( face->extra.finalizer )
    785       face->extra.finalizer( face->extra.data );
    786 
    787     if ( sfnt )
    788       sfnt->done_face( face );
    789 
    790     /* freeing the locations table */
    791     tt_face_done_loca( face );
    792 
    793     tt_face_free_hdmx( face );
    794 
    795     /* freeing the CVT */
    796     FT_FREE( face->cvt );
    797     face->cvt_size = 0;
    798 
    799     /* freeing the programs */
    800     FT_FRAME_RELEASE( face->font_program );
    801     FT_FRAME_RELEASE( face->cvt_program );
    802     face->font_program_size = 0;
    803     face->cvt_program_size  = 0;
    804 
    805 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    806     tt_done_blend( face );
    807     face->blend = NULL;
    808 #endif
    809   }
    810 
    811 
    812   /**************************************************************************
    813    *
    814    *                          SIZE  FUNCTIONS
    815    *
    816    */
    817 
    818 #ifdef TT_USE_BYTECODE_INTERPRETER
    819 
    820   /**************************************************************************
    821    *
    822    * @Function:
    823    *   tt_size_run_fpgm
    824    *
    825    * @Description:
    826    *   Run the font program.
    827    *
    828    * @Input:
    829    *   size ::
    830    *     A handle to the size object.
    831    *
    832    *   pedantic ::
    833    *     Set if bytecode execution should be pedantic.
    834    *
    835    * @Return:
    836    *   FreeType error code.  0 means success.
    837    */
    838   FT_LOCAL_DEF( FT_Error )
    839   tt_size_run_fpgm( TT_Size  size,
    840                     FT_Bool  pedantic )
    841   {
    842     TT_Face         face = (TT_Face)size->root.face;
    843     TT_ExecContext  exec;
    844     FT_Error        error;
    845 
    846 
    847     exec = size->context;
    848 
    849     error = TT_Load_Context( exec, face, size );
    850     if ( error )
    851       return error;
    852 
    853     exec->callTop = 0;
    854     exec->top     = 0;
    855 
    856     exec->period    = 64;
    857     exec->phase     = 0;
    858     exec->threshold = 0;
    859 
    860     exec->instruction_trap = FALSE;
    861     exec->F_dot_P          = 0x4000L;
    862 
    863     exec->pedantic_hinting = pedantic;
    864 
    865     {
    866       FT_Size_Metrics*  size_metrics = &exec->metrics;
    867       TT_Size_Metrics*  tt_metrics   = &exec->tt_metrics;
    868 
    869 
    870       size_metrics->x_ppem   = 0;
    871       size_metrics->y_ppem   = 0;
    872       size_metrics->x_scale  = 0;
    873       size_metrics->y_scale  = 0;
    874 
    875       tt_metrics->ppem  = 0;
    876       tt_metrics->scale = 0;
    877       tt_metrics->ratio = 0x10000L;
    878     }
    879 
    880     /* allow font program execution */
    881     TT_Set_CodeRange( exec,
    882                       tt_coderange_font,
    883                       face->font_program,
    884                       (FT_Long)face->font_program_size );
    885 
    886     /* disable CVT and glyph programs coderange */
    887     TT_Clear_CodeRange( exec, tt_coderange_cvt );
    888     TT_Clear_CodeRange( exec, tt_coderange_glyph );
    889 
    890     if ( face->font_program_size > 0 )
    891     {
    892       TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
    893 
    894       FT_TRACE4(( "Executing `fpgm' table.\n" ));
    895       error = face->interpreter( exec );
    896 #ifdef FT_DEBUG_LEVEL_TRACE
    897       if ( error )
    898         FT_TRACE4(( "  interpretation failed with error code 0x%x\n",
    899                     error ));
    900 #endif
    901     }
    902     else
    903       error = FT_Err_Ok;
    904 
    905     size->bytecode_ready = error;
    906 
    907     if ( !error )
    908       TT_Save_Context( exec, size );
    909 
    910     return error;
    911   }
    912 
    913 
    914   /**************************************************************************
    915    *
    916    * @Function:
    917    *   tt_size_run_prep
    918    *
    919    * @Description:
    920    *   Run the control value program.
    921    *
    922    * @Input:
    923    *   size ::
    924    *     A handle to the size object.
    925    *
    926    *   pedantic ::
    927    *     Set if bytecode execution should be pedantic.
    928    *
    929    * @Return:
    930    *   FreeType error code.  0 means success.
    931    */
    932   FT_LOCAL_DEF( FT_Error )
    933   tt_size_run_prep( TT_Size  size,
    934                     FT_Bool  pedantic )
    935   {
    936     TT_Face         face = (TT_Face)size->root.face;
    937     TT_ExecContext  exec;
    938     FT_Error        error;
    939     FT_UInt         i;
    940 
    941     /* unscaled CVT values are already stored in 26.6 format */
    942     FT_Fixed  scale = size->ttmetrics.scale >> 6;
    943 
    944 
    945     /* Scale the cvt values to the new ppem.            */
    946     /* By default, we use the y ppem value for scaling. */
    947     FT_TRACE6(( "CVT values:\n" ));
    948     for ( i = 0; i < size->cvt_size; i++ )
    949     {
    950       size->cvt[i] = FT_MulFix( face->cvt[i], scale );
    951       FT_TRACE6(( "  %3d: %f (%f)\n",
    952                   i, face->cvt[i] / 64.0, size->cvt[i] / 64.0 ));
    953     }
    954     FT_TRACE6(( "\n" ));
    955 
    956     exec = size->context;
    957 
    958     error = TT_Load_Context( exec, face, size );
    959     if ( error )
    960       return error;
    961 
    962     exec->callTop = 0;
    963     exec->top     = 0;
    964 
    965     exec->instruction_trap = FALSE;
    966 
    967     exec->pedantic_hinting = pedantic;
    968 
    969     TT_Set_CodeRange( exec,
    970                       tt_coderange_cvt,
    971                       face->cvt_program,
    972                       (FT_Long)face->cvt_program_size );
    973 
    974     TT_Clear_CodeRange( exec, tt_coderange_glyph );
    975 
    976     if ( face->cvt_program_size > 0 )
    977     {
    978       TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
    979 
    980       FT_TRACE4(( "Executing `prep' table.\n" ));
    981       error = face->interpreter( exec );
    982 #ifdef FT_DEBUG_LEVEL_TRACE
    983       if ( error )
    984         FT_TRACE4(( "  interpretation failed with error code 0x%x\n",
    985                     error ));
    986 #endif
    987     }
    988     else
    989       error = FT_Err_Ok;
    990 
    991     size->cvt_ready = error;
    992 
    993     /* UNDOCUMENTED!  The MS rasterizer doesn't allow the following */
    994     /* graphics state variables to be modified by the CVT program.  */
    995 
    996     exec->GS.dualVector.x = 0x4000;
    997     exec->GS.dualVector.y = 0;
    998     exec->GS.projVector.x = 0x4000;
    999     exec->GS.projVector.y = 0x0;
   1000     exec->GS.freeVector.x = 0x4000;
   1001     exec->GS.freeVector.y = 0x0;
   1002 
   1003     exec->GS.rp0 = 0;
   1004     exec->GS.rp1 = 0;
   1005     exec->GS.rp2 = 0;
   1006 
   1007     exec->GS.gep0 = 1;
   1008     exec->GS.gep1 = 1;
   1009     exec->GS.gep2 = 1;
   1010 
   1011     exec->GS.loop = 1;
   1012 
   1013     /* save as default graphics state */
   1014     size->GS = exec->GS;
   1015 
   1016     TT_Save_Context( exec, size );
   1017 
   1018     return error;
   1019   }
   1020 
   1021 
   1022   static void
   1023   tt_size_done_bytecode( FT_Size  ftsize )
   1024   {
   1025     TT_Size    size   = (TT_Size)ftsize;
   1026     TT_Face    face   = (TT_Face)ftsize->face;
   1027     FT_Memory  memory = face->root.memory;
   1028 
   1029     if ( size->context )
   1030     {
   1031       TT_Done_Context( size->context );
   1032       size->context = NULL;
   1033     }
   1034 
   1035     FT_FREE( size->cvt );
   1036     size->cvt_size = 0;
   1037 
   1038     /* free storage area */
   1039     FT_FREE( size->storage );
   1040     size->storage_size = 0;
   1041 
   1042     /* twilight zone */
   1043     tt_glyphzone_done( &size->twilight );
   1044 
   1045     FT_FREE( size->function_defs );
   1046     FT_FREE( size->instruction_defs );
   1047 
   1048     size->num_function_defs    = 0;
   1049     size->max_function_defs    = 0;
   1050     size->num_instruction_defs = 0;
   1051     size->max_instruction_defs = 0;
   1052 
   1053     size->max_func = 0;
   1054     size->max_ins  = 0;
   1055 
   1056     size->bytecode_ready = -1;
   1057     size->cvt_ready      = -1;
   1058   }
   1059 
   1060 
   1061   /* Initialize bytecode-related fields in the size object.       */
   1062   /* We do this only if bytecode interpretation is really needed. */
   1063   static FT_Error
   1064   tt_size_init_bytecode( FT_Size  ftsize,
   1065                          FT_Bool  pedantic )
   1066   {
   1067     FT_Error   error;
   1068     TT_Size    size = (TT_Size)ftsize;
   1069     TT_Face    face = (TT_Face)ftsize->face;
   1070     FT_Memory  memory = face->root.memory;
   1071 
   1072     FT_UShort       n_twilight;
   1073     TT_MaxProfile*  maxp = &face->max_profile;
   1074 
   1075 
   1076     /* clean up bytecode related data */
   1077     FT_FREE( size->function_defs );
   1078     FT_FREE( size->instruction_defs );
   1079     FT_FREE( size->cvt );
   1080     FT_FREE( size->storage );
   1081 
   1082     if ( size->context )
   1083       TT_Done_Context( size->context );
   1084     tt_glyphzone_done( &size->twilight );
   1085 
   1086     size->bytecode_ready = -1;
   1087     size->cvt_ready      = -1;
   1088 
   1089     size->context = TT_New_Context( (TT_Driver)face->root.driver );
   1090 
   1091     size->max_function_defs    = maxp->maxFunctionDefs;
   1092     size->max_instruction_defs = maxp->maxInstructionDefs;
   1093 
   1094     size->num_function_defs    = 0;
   1095     size->num_instruction_defs = 0;
   1096 
   1097     size->max_func = 0;
   1098     size->max_ins  = 0;
   1099 
   1100     size->cvt_size     = face->cvt_size;
   1101     size->storage_size = maxp->maxStorage;
   1102 
   1103     /* Set default metrics */
   1104     {
   1105       TT_Size_Metrics*  tt_metrics = &size->ttmetrics;
   1106 
   1107 
   1108       tt_metrics->rotated   = FALSE;
   1109       tt_metrics->stretched = FALSE;
   1110 
   1111       /* Set default engine compensation.  Value 3 is not described */
   1112       /* in the OpenType specification (as of Mai 2019), but Greg   */
   1113       /* says that MS handles it the same as `gray'.                */
   1114       /*                                                            */
   1115       /* The Apple specification says that the compensation for     */
   1116       /* `gray' is always zero.  FreeType doesn't do any            */
   1117       /* compensation at all.                                       */
   1118       tt_metrics->compensations[0] = 0;   /* gray  */
   1119       tt_metrics->compensations[1] = 0;   /* black */
   1120       tt_metrics->compensations[2] = 0;   /* white */
   1121       tt_metrics->compensations[3] = 0;   /* zero  */
   1122     }
   1123 
   1124     /* allocate function defs, instruction defs, cvt, and storage area */
   1125     if ( FT_NEW_ARRAY( size->function_defs,    size->max_function_defs    ) ||
   1126          FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) ||
   1127          FT_NEW_ARRAY( size->cvt,              size->cvt_size             ) ||
   1128          FT_NEW_ARRAY( size->storage,          size->storage_size         ) )
   1129       goto Exit;
   1130 
   1131     /* reserve twilight zone */
   1132     n_twilight = maxp->maxTwilightPoints;
   1133 
   1134     /* there are 4 phantom points (do we need this?) */
   1135     n_twilight += 4;
   1136 
   1137     error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight );
   1138     if ( error )
   1139       goto Exit;
   1140 
   1141     size->twilight.n_points = n_twilight;
   1142 
   1143     size->GS = tt_default_graphics_state;
   1144 
   1145     /* set `face->interpreter' according to the debug hook present */
   1146     {
   1147       FT_Library  library = face->root.driver->root.library;
   1148 
   1149 
   1150       face->interpreter = (TT_Interpreter)
   1151                             library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
   1152       if ( !face->interpreter )
   1153         face->interpreter = (TT_Interpreter)TT_RunIns;
   1154     }
   1155 
   1156     /* Fine, now run the font program! */
   1157 
   1158     /* In case of an error while executing `fpgm', we intentionally don't */
   1159     /* clean up immediately  bugs in the `fpgm' are so fundamental that  */
   1160     /* all following hinting calls should fail.  Additionally, `fpgm' is  */
   1161     /* to be executed just once; calling it again is completely useless   */
   1162     /* and might even lead to extremely slow behaviour if it is malformed */
   1163     /* (containing an infinite loop, for example).                        */
   1164     error = tt_size_run_fpgm( size, pedantic );
   1165     return error;
   1166 
   1167   Exit:
   1168     if ( error )
   1169       tt_size_done_bytecode( ftsize );
   1170 
   1171     return error;
   1172   }
   1173 
   1174 
   1175   FT_LOCAL_DEF( FT_Error )
   1176   tt_size_ready_bytecode( TT_Size  size,
   1177                           FT_Bool  pedantic )
   1178   {
   1179     FT_Error  error = FT_Err_Ok;
   1180 
   1181 
   1182     if ( size->bytecode_ready < 0 )
   1183       error = tt_size_init_bytecode( (FT_Size)size, pedantic );
   1184     else
   1185       error = size->bytecode_ready;
   1186 
   1187     if ( error )
   1188       goto Exit;
   1189 
   1190     /* rescale CVT when needed */
   1191     if ( size->cvt_ready < 0 )
   1192     {
   1193       FT_UInt  i;
   1194 
   1195 
   1196       /* all twilight points are originally zero */
   1197       for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ )
   1198       {
   1199         size->twilight.org[i].x = 0;
   1200         size->twilight.org[i].y = 0;
   1201         size->twilight.cur[i].x = 0;
   1202         size->twilight.cur[i].y = 0;
   1203       }
   1204 
   1205       /* clear storage area */
   1206       for ( i = 0; i < (FT_UInt)size->storage_size; i++ )
   1207         size->storage[i] = 0;
   1208 
   1209       size->GS = tt_default_graphics_state;
   1210 
   1211       error = tt_size_run_prep( size, pedantic );
   1212     }
   1213     else
   1214       error = size->cvt_ready;
   1215 
   1216   Exit:
   1217     return error;
   1218   }
   1219 
   1220 #endif /* TT_USE_BYTECODE_INTERPRETER */
   1221 
   1222 
   1223   /**************************************************************************
   1224    *
   1225    * @Function:
   1226    *   tt_size_init
   1227    *
   1228    * @Description:
   1229    *   Initialize a new TrueType size object.
   1230    *
   1231    * @InOut:
   1232    *   size ::
   1233    *     A handle to the size object.
   1234    *
   1235    * @Return:
   1236    *   FreeType error code.  0 means success.
   1237    */
   1238   FT_LOCAL_DEF( FT_Error )
   1239   tt_size_init( FT_Size  ttsize )           /* TT_Size */
   1240   {
   1241     TT_Size   size  = (TT_Size)ttsize;
   1242     FT_Error  error = FT_Err_Ok;
   1243 
   1244 
   1245 #ifdef TT_USE_BYTECODE_INTERPRETER
   1246     size->bytecode_ready = -1;
   1247     size->cvt_ready      = -1;
   1248 #endif
   1249 
   1250     size->ttmetrics.valid = FALSE;
   1251     size->strike_index    = 0xFFFFFFFFUL;
   1252 
   1253     return error;
   1254   }
   1255 
   1256 
   1257   /**************************************************************************
   1258    *
   1259    * @Function:
   1260    *   tt_size_done
   1261    *
   1262    * @Description:
   1263    *   The TrueType size object finalizer.
   1264    *
   1265    * @Input:
   1266    *   size ::
   1267    *     A handle to the target size object.
   1268    */
   1269   FT_LOCAL_DEF( void )
   1270   tt_size_done( FT_Size  ttsize )           /* TT_Size */
   1271   {
   1272     TT_Size  size = (TT_Size)ttsize;
   1273 
   1274 
   1275 #ifdef TT_USE_BYTECODE_INTERPRETER
   1276     tt_size_done_bytecode( ttsize );
   1277 #endif
   1278 
   1279     size->ttmetrics.valid = FALSE;
   1280   }
   1281 
   1282 
   1283   /**************************************************************************
   1284    *
   1285    * @Function:
   1286    *   tt_size_reset
   1287    *
   1288    * @Description:
   1289    *   Reset a TrueType size when resolutions and character dimensions
   1290    *   have been changed.
   1291    *
   1292    * @Input:
   1293    *   size ::
   1294    *     A handle to the target size object.
   1295    *
   1296    *   only_height ::
   1297    *     Only recompute ascender, descender, and height;
   1298    *     this flag is used for variation fonts where
   1299    *     `tt_size_reset' is used as an iterator function.
   1300    */
   1301   FT_LOCAL_DEF( FT_Error )
   1302   tt_size_reset( TT_Size  size,
   1303                  FT_Bool  only_height )
   1304   {
   1305     TT_Face           face;
   1306     FT_Size_Metrics*  size_metrics;
   1307 
   1308 
   1309     face = (TT_Face)size->root.face;
   1310 
   1311     /* nothing to do for CFF2 */
   1312     if ( face->is_cff2 )
   1313       return FT_Err_Ok;
   1314 
   1315     size->ttmetrics.valid = FALSE;
   1316 
   1317     size_metrics = &size->hinted_metrics;
   1318 
   1319     /* copy the result from base layer */
   1320     *size_metrics = size->root.metrics;
   1321 
   1322     if ( size_metrics->x_ppem < 1 || size_metrics->y_ppem < 1 )
   1323       return FT_THROW( Invalid_PPem );
   1324 
   1325     /* This bit flag, if set, indicates that the ppems must be       */
   1326     /* rounded to integers.  Nearly all TrueType fonts have this bit */
   1327     /* set, as hinting won't work really well otherwise.             */
   1328     /*                                                               */
   1329     if ( face->header.Flags & 8 )
   1330     {
   1331       /* the TT spec always asks for ROUND, not FLOOR or CEIL */
   1332       size_metrics->ascender = FT_PIX_ROUND(
   1333                                  FT_MulFix( face->root.ascender,
   1334                                             size_metrics->y_scale ) );
   1335       size_metrics->descender = FT_PIX_ROUND(
   1336                                  FT_MulFix( face->root.descender,
   1337                                             size_metrics->y_scale ) );
   1338       size_metrics->height = FT_PIX_ROUND(
   1339                                FT_MulFix( face->root.height,
   1340                                           size_metrics->y_scale ) );
   1341     }
   1342 
   1343     size->ttmetrics.valid = TRUE;
   1344 
   1345     if ( only_height )
   1346     {
   1347       /* we must not recompute the scaling values here since       */
   1348       /* `tt_size_reset' was already called (with only_height = 0) */
   1349       return FT_Err_Ok;
   1350     }
   1351 
   1352     if ( face->header.Flags & 8 )
   1353     {
   1354       /* base scaling values on integer ppem values, */
   1355       /* as mandated by the TrueType specification   */
   1356       size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6,
   1357                                          face->root.units_per_EM );
   1358       size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6,
   1359                                          face->root.units_per_EM );
   1360 
   1361       size_metrics->max_advance = FT_PIX_ROUND(
   1362                                     FT_MulFix( face->root.max_advance_width,
   1363                                                size_metrics->x_scale ) );
   1364     }
   1365 
   1366     /* compute new transformation */
   1367     if ( size_metrics->x_ppem >= size_metrics->y_ppem )
   1368     {
   1369       size->ttmetrics.scale   = size_metrics->x_scale;
   1370       size->ttmetrics.ppem    = size_metrics->x_ppem;
   1371       size->ttmetrics.x_ratio = 0x10000L;
   1372       size->ttmetrics.y_ratio = FT_DivFix( size_metrics->y_ppem,
   1373                                            size_metrics->x_ppem );
   1374     }
   1375     else
   1376     {
   1377       size->ttmetrics.scale   = size_metrics->y_scale;
   1378       size->ttmetrics.ppem    = size_metrics->y_ppem;
   1379       size->ttmetrics.x_ratio = FT_DivFix( size_metrics->x_ppem,
   1380                                            size_metrics->y_ppem );
   1381       size->ttmetrics.y_ratio = 0x10000L;
   1382     }
   1383 
   1384     size->metrics = size_metrics;
   1385 
   1386 #ifdef TT_USE_BYTECODE_INTERPRETER
   1387     size->cvt_ready = -1;
   1388 #endif /* TT_USE_BYTECODE_INTERPRETER */
   1389 
   1390     return FT_Err_Ok;
   1391   }
   1392 
   1393 
   1394   /**************************************************************************
   1395    *
   1396    * @Function:
   1397    *   tt_driver_init
   1398    *
   1399    * @Description:
   1400    *   Initialize a given TrueType driver object.
   1401    *
   1402    * @Input:
   1403    *   driver ::
   1404    *     A handle to the target driver object.
   1405    *
   1406    * @Return:
   1407    *   FreeType error code.  0 means success.
   1408    */
   1409   FT_LOCAL_DEF( FT_Error )
   1410   tt_driver_init( FT_Module  ttdriver )     /* TT_Driver */
   1411   {
   1412 
   1413 #ifdef TT_USE_BYTECODE_INTERPRETER
   1414 
   1415     TT_Driver  driver = (TT_Driver)ttdriver;
   1416 
   1417     driver->interpreter_version = TT_INTERPRETER_VERSION_35;
   1418 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
   1419     driver->interpreter_version = TT_INTERPRETER_VERSION_38;
   1420 #endif
   1421 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
   1422     driver->interpreter_version = TT_INTERPRETER_VERSION_40;
   1423 #endif
   1424 
   1425 #else /* !TT_USE_BYTECODE_INTERPRETER */
   1426 
   1427     FT_UNUSED( ttdriver );
   1428 
   1429 #endif /* !TT_USE_BYTECODE_INTERPRETER */
   1430 
   1431     return FT_Err_Ok;
   1432   }
   1433 
   1434 
   1435   /**************************************************************************
   1436    *
   1437    * @Function:
   1438    *   tt_driver_done
   1439    *
   1440    * @Description:
   1441    *   Finalize a given TrueType driver.
   1442    *
   1443    * @Input:
   1444    *   driver ::
   1445    *     A handle to the target TrueType driver.
   1446    */
   1447   FT_LOCAL_DEF( void )
   1448   tt_driver_done( FT_Module  ttdriver )     /* TT_Driver */
   1449   {
   1450     FT_UNUSED( ttdriver );
   1451   }
   1452 
   1453 
   1454   /**************************************************************************
   1455    *
   1456    * @Function:
   1457    *   tt_slot_init
   1458    *
   1459    * @Description:
   1460    *   Initialize a new slot object.
   1461    *
   1462    * @InOut:
   1463    *   slot ::
   1464    *     A handle to the slot object.
   1465    *
   1466    * @Return:
   1467    *   FreeType error code.  0 means success.
   1468    */
   1469   FT_LOCAL_DEF( FT_Error )
   1470   tt_slot_init( FT_GlyphSlot  slot )
   1471   {
   1472     return FT_GlyphLoader_CreateExtra( slot->internal->loader );
   1473   }
   1474 
   1475 
   1476 /* END */
   1477