tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ttobjs.c (39580B)


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