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