1 /****************************************************************************
   2  *
   3  * ttobjs.c
   4  *
   5  *   Objects manager (body).
   6  *
   7  * Copyright (C) 1996-2020 by
   8  * David Turner, Robert Wilhelm, and Werner Lemberg.
   9  *
  10  * This file is part of the FreeType project, and may only be used,
  11  * modified, and distributed under the terms of the FreeType project
  12  * license, LICENSE.TXT.  By continuing to use, modify, or distribute
  13  * this file you indicate that you have read the license and
  14  * understand and accept it fully.
  15  *
  16  */
  17 
  18 
  19 #include <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( const 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     FT_UInt         i;
 941 
 942     /* unscaled CVT values are already stored in 26.6 format */
 943     FT_Fixed  scale = size->ttmetrics.scale >> 6;
 944 
 945 
 946     /* Scale the cvt values to the new ppem.            */
 947     /* By default, we use the y ppem value for scaling. */
 948     FT_TRACE6(( "CVT values:\n" ));
 949     for ( i = 0; i < size->cvt_size; i++ )
 950     {
 951       size->cvt[i] = FT_MulFix( face->cvt[i], scale );
 952       FT_TRACE6(( "  %3d: %f (%f)\n",
 953                   i, face->cvt[i] / 64.0, size->cvt[i] / 64.0 ));
 954     }
 955     FT_TRACE6(( "\n" ));
 956 
 957     exec = size->context;
 958 
 959     error = TT_Load_Context( exec, face, size );
 960     if ( error )
 961       return error;
 962 
 963     exec->callTop = 0;
 964     exec->top     = 0;
 965 
 966     exec->instruction_trap = FALSE;
 967 
 968     exec->pedantic_hinting = pedantic;
 969 
 970     TT_Set_CodeRange( exec,
 971                       tt_coderange_cvt,
 972                       face->cvt_program,
 973                       (FT_Long)face->cvt_program_size );
 974 
 975     TT_Clear_CodeRange( exec, tt_coderange_glyph );
 976 
 977     if ( face->cvt_program_size > 0 )
 978     {
 979       TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
 980 
 981       FT_TRACE4(( "Executing `prep' table.\n" ));
 982       error = face->interpreter( exec );
 983 #ifdef FT_DEBUG_LEVEL_TRACE
 984       if ( error )
 985         FT_TRACE4(( "  interpretation failed with error code 0x%x\n",
 986                     error ));
 987 #endif
 988     }
 989     else
 990       error = FT_Err_Ok;
 991 
 992     size->cvt_ready = error;
 993 
 994     /* UNDOCUMENTED!  The MS rasterizer doesn't allow the following */
 995     /* graphics state variables to be modified by the CVT program.  */
 996 
 997     exec->GS.dualVector.x = 0x4000;
 998     exec->GS.dualVector.y = 0;
 999     exec->GS.projVector.x = 0x4000;
1000     exec->GS.projVector.y = 0x0;
1001     exec->GS.freeVector.x = 0x4000;
1002     exec->GS.freeVector.y = 0x0;
1003 
1004     exec->GS.rp0 = 0;
1005     exec->GS.rp1 = 0;
1006     exec->GS.rp2 = 0;
1007 
1008     exec->GS.gep0 = 1;
1009     exec->GS.gep1 = 1;
1010     exec->GS.gep2 = 1;
1011 
1012     exec->GS.loop = 1;
1013 
1014     /* save as default graphics state */
1015     size->GS = exec->GS;
1016 
1017     TT_Save_Context( exec, size );
1018 
1019     return error;
1020   }
1021 
1022 
1023   static void
1024   tt_size_done_bytecode( FT_Size  ftsize )
1025   {
1026     TT_Size    size   = (TT_Size)ftsize;
1027     TT_Face    face   = (TT_Face)ftsize->face;
1028     FT_Memory  memory = face->root.memory;
1029 
1030     if ( size->context )
1031     {
1032       TT_Done_Context( size->context );
1033       size->context = NULL;
1034     }
1035 
1036     FT_FREE( size->cvt );
1037     size->cvt_size = 0;
1038 
1039     /* free storage area */
1040     FT_FREE( size->storage );
1041     size->storage_size = 0;
1042 
1043     /* twilight zone */
1044     tt_glyphzone_done( &size->twilight );
1045 
1046     FT_FREE( size->function_defs );
1047     FT_FREE( size->instruction_defs );
1048 
1049     size->num_function_defs    = 0;
1050     size->max_function_defs    = 0;
1051     size->num_instruction_defs = 0;
1052     size->max_instruction_defs = 0;
1053 
1054     size->max_func = 0;
1055     size->max_ins  = 0;
1056 
1057     size->bytecode_ready = -1;
1058     size->cvt_ready      = -1;
1059   }
1060 
1061 
1062   /* Initialize bytecode-related fields in the size object.       */
1063   /* We do this only if bytecode interpretation is really needed. */
1064   static FT_Error
1065   tt_size_init_bytecode( FT_Size  ftsize,
1066                          FT_Bool  pedantic )
1067   {
1068     FT_Error   error;
1069     TT_Size    size = (TT_Size)ftsize;
1070     TT_Face    face = (TT_Face)ftsize->face;
1071     FT_Memory  memory = face->root.memory;
1072 
1073     FT_UShort       n_twilight;
1074     TT_MaxProfile*  maxp = &face->max_profile;
1075 
1076 
1077     /* clean up bytecode related data */
1078     FT_FREE( size->function_defs );
1079     FT_FREE( size->instruction_defs );
1080     FT_FREE( size->cvt );
1081     FT_FREE( size->storage );
1082 
1083     if ( size->context )
1084       TT_Done_Context( size->context );
1085     tt_glyphzone_done( &size->twilight );
1086 
1087     size->bytecode_ready = -1;
1088     size->cvt_ready      = -1;
1089 
1090     size->context = TT_New_Context( (TT_Driver)face->root.driver );
1091 
1092     size->max_function_defs    = maxp->maxFunctionDefs;
1093     size->max_instruction_defs = maxp->maxInstructionDefs;
1094 
1095     size->num_function_defs    = 0;
1096     size->num_instruction_defs = 0;
1097 
1098     size->max_func = 0;
1099     size->max_ins  = 0;
1100 
1101     size->cvt_size     = face->cvt_size;
1102     size->storage_size = maxp->maxStorage;
1103 
1104     /* Set default metrics */
1105     {
1106       TT_Size_Metrics*  tt_metrics = &size->ttmetrics;
1107 
1108 
1109       tt_metrics->rotated   = FALSE;
1110       tt_metrics->stretched = FALSE;
1111 
1112       /* Set default engine compensation.  Value 3 is not described */
1113       /* in the OpenType specification (as of Mai 2019), but Greg   */
1114       /* says that MS handles it the same as `gray'.                */
1115       /*                                                            */
1116       /* The Apple specification says that the compensation for     */
1117       /* `gray' is always zero.  FreeType doesn't do any            */
1118       /* compensation at all.                                       */
1119       tt_metrics->compensations[0] = 0;   /* gray             */
1120       tt_metrics->compensations[1] = 0;   /* black            */
1121       tt_metrics->compensations[2] = 0;   /* white            */
1122       tt_metrics->compensations[3] = 0;   /* the same as gray */
1123     }
1124 
1125     /* allocate function defs, instruction defs, cvt, and storage area */
1126     if ( FT_NEW_ARRAY( size->function_defs,    size->max_function_defs    ) ||
1127          FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) ||
1128          FT_NEW_ARRAY( size->cvt,              size->cvt_size             ) ||
1129          FT_NEW_ARRAY( size->storage,          size->storage_size         ) )
1130       goto Exit;
1131 
1132     /* reserve twilight zone */
1133     n_twilight = maxp->maxTwilightPoints;
1134 
1135     /* there are 4 phantom points (do we need this?) */
1136     n_twilight += 4;
1137 
1138     error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight );
1139     if ( error )
1140       goto Exit;
1141 
1142     size->twilight.n_points = n_twilight;
1143 
1144     size->GS = tt_default_graphics_state;
1145 
1146     /* set `face->interpreter' according to the debug hook present */
1147     {
1148       FT_Library  library = face->root.driver->root.library;
1149 
1150 
1151       face->interpreter = (TT_Interpreter)
1152                             library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
1153       if ( !face->interpreter )
1154         face->interpreter = (TT_Interpreter)TT_RunIns;
1155     }
1156 
1157     /* Fine, now run the font program! */
1158 
1159     /* In case of an error while executing `fpgm', we intentionally don't */
1160     /* clean up immediately – bugs in the `fpgm' are so fundamental that  */
1161     /* all following hinting calls should fail.  Additionally, `fpgm' is  */
1162     /* to be executed just once; calling it again is completely useless   */
1163     /* and might even lead to extremely slow behaviour if it is malformed */
1164     /* (containing an infinite loop, for example).                        */
1165     error = tt_size_run_fpgm( size, pedantic );
1166     return error;
1167 
1168   Exit:
1169     if ( error )
1170       tt_size_done_bytecode( ftsize );
1171 
1172     return error;
1173   }
1174 
1175 
1176   FT_LOCAL_DEF( FT_Error )
1177   tt_size_ready_bytecode( TT_Size  size,
1178                           FT_Bool  pedantic )
1179   {
1180     FT_Error  error = FT_Err_Ok;
1181 
1182 
1183     if ( size->bytecode_ready < 0 )
1184       error = tt_size_init_bytecode( (FT_Size)size, pedantic );
1185     else
1186       error = size->bytecode_ready;
1187 
1188     if ( error )
1189       goto Exit;
1190 
1191     /* rescale CVT when needed */
1192     if ( size->cvt_ready < 0 )
1193     {
1194       FT_UInt  i;
1195 
1196 
1197       /* all twilight points are originally zero */
1198       for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ )
1199       {
1200         size->twilight.org[i].x = 0;
1201         size->twilight.org[i].y = 0;
1202         size->twilight.cur[i].x = 0;
1203         size->twilight.cur[i].y = 0;
1204       }
1205 
1206       /* clear storage area */
1207       for ( i = 0; i < (FT_UInt)size->storage_size; i++ )
1208         size->storage[i] = 0;
1209 
1210       size->GS = tt_default_graphics_state;
1211 
1212       error = tt_size_run_prep( size, pedantic );
1213     }
1214     else
1215       error = size->cvt_ready;
1216 
1217   Exit:
1218     return error;
1219   }
1220 
1221 #endif /* TT_USE_BYTECODE_INTERPRETER */
1222 
1223 
1224   /**************************************************************************
1225    *
1226    * @Function:
1227    *   tt_size_init
1228    *
1229    * @Description:
1230    *   Initialize a new TrueType size object.
1231    *
1232    * @InOut:
1233    *   size ::
1234    *     A handle to the size object.
1235    *
1236    * @Return:
1237    *   FreeType error code.  0 means success.
1238    */
1239   FT_LOCAL_DEF( FT_Error )
1240   tt_size_init( FT_Size  ttsize )           /* TT_Size */
1241   {
1242     TT_Size   size  = (TT_Size)ttsize;
1243     FT_Error  error = FT_Err_Ok;
1244 
1245 
1246 #ifdef TT_USE_BYTECODE_INTERPRETER
1247     size->bytecode_ready = -1;
1248     size->cvt_ready      = -1;
1249 #endif
1250 
1251     size->ttmetrics.valid = FALSE;
1252     size->strike_index    = 0xFFFFFFFFUL;
1253 
1254     return error;
1255   }
1256 
1257 
1258   /**************************************************************************
1259    *
1260    * @Function:
1261    *   tt_size_done
1262    *
1263    * @Description:
1264    *   The TrueType size object finalizer.
1265    *
1266    * @Input:
1267    *   size ::
1268    *     A handle to the target size object.
1269    */
1270   FT_LOCAL_DEF( void )
1271   tt_size_done( FT_Size  ttsize )           /* TT_Size */
1272   {
1273     TT_Size  size = (TT_Size)ttsize;
1274 
1275 
1276 #ifdef TT_USE_BYTECODE_INTERPRETER
1277     tt_size_done_bytecode( ttsize );
1278 #endif
1279 
1280     size->ttmetrics.valid = FALSE;
1281   }
1282 
1283 
1284   /**************************************************************************
1285    *
1286    * @Function:
1287    *   tt_size_reset
1288    *
1289    * @Description:
1290    *   Reset a TrueType size when resolutions and character dimensions
1291    *   have been changed.
1292    *
1293    * @Input:
1294    *   size ::
1295    *     A handle to the target size object.
1296    *
1297    *   only_height ::
1298    *     Only recompute ascender, descender, and height;
1299    *     this flag is used for variation fonts where
1300    *     `tt_size_reset' is used as an iterator function.
1301    */
1302   FT_LOCAL_DEF( FT_Error )
1303   tt_size_reset( TT_Size  size,
1304                  FT_Bool  only_height )
1305   {
1306     TT_Face           face;
1307     FT_Size_Metrics*  size_metrics;
1308 
1309 
1310     face = (TT_Face)size->root.face;
1311 
1312     /* nothing to do for CFF2 */
1313     if ( face->is_cff2 )
1314       return FT_Err_Ok;
1315 
1316     size->ttmetrics.valid = FALSE;
1317 
1318     size_metrics = &size->hinted_metrics;
1319 
1320     /* copy the result from base layer */
1321     *size_metrics = size->root.metrics;
1322 
1323     if ( size_metrics->x_ppem < 1 || size_metrics->y_ppem < 1 )
1324       return FT_THROW( Invalid_PPem );
1325 
1326     /* This bit flag, if set, indicates that the ppems must be       */
1327     /* rounded to integers.  Nearly all TrueType fonts have this bit */
1328     /* set, as hinting won't work really well otherwise.             */
1329     /*                                                               */
1330     if ( face->header.Flags & 8 )
1331     {
1332       /* the TT spec always asks for ROUND, not FLOOR or CEIL */
1333       size_metrics->ascender = FT_PIX_ROUND(
1334                                  FT_MulFix( face->root.ascender,
1335                                             size_metrics->y_scale ) );
1336       size_metrics->descender = FT_PIX_ROUND(
1337                                  FT_MulFix( face->root.descender,
1338                                             size_metrics->y_scale ) );
1339       size_metrics->height = FT_PIX_ROUND(
1340                                FT_MulFix( face->root.height,
1341                                           size_metrics->y_scale ) );
1342     }
1343 
1344     size->ttmetrics.valid = TRUE;
1345 
1346     if ( only_height )
1347     {
1348       /* we must not recompute the scaling values here since       */
1349       /* `tt_size_reset' was already called (with only_height = 0) */
1350       return FT_Err_Ok;
1351     }
1352 
1353     if ( face->header.Flags & 8 )
1354     {
1355       /* base scaling values on integer ppem values, */
1356       /* as mandated by the TrueType specification   */
1357       size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6,
1358                                          face->root.units_per_EM );
1359       size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6,
1360                                          face->root.units_per_EM );
1361 
1362       size_metrics->max_advance = FT_PIX_ROUND(
1363                                     FT_MulFix( face->root.max_advance_width,
1364                                                size_metrics->x_scale ) );
1365     }
1366 
1367     /* compute new transformation */
1368     if ( size_metrics->x_ppem >= size_metrics->y_ppem )
1369     {
1370       size->ttmetrics.scale   = size_metrics->x_scale;
1371       size->ttmetrics.ppem    = size_metrics->x_ppem;
1372       size->ttmetrics.x_ratio = 0x10000L;
1373       size->ttmetrics.y_ratio = FT_DivFix( size_metrics->y_ppem,
1374                                            size_metrics->x_ppem );
1375     }
1376     else
1377     {
1378       size->ttmetrics.scale   = size_metrics->y_scale;
1379       size->ttmetrics.ppem    = size_metrics->y_ppem;
1380       size->ttmetrics.x_ratio = FT_DivFix( size_metrics->x_ppem,
1381                                            size_metrics->y_ppem );
1382       size->ttmetrics.y_ratio = 0x10000L;
1383     }
1384 
1385     size->metrics = size_metrics;
1386 
1387 #ifdef TT_USE_BYTECODE_INTERPRETER
1388     size->cvt_ready = -1;
1389 #endif /* TT_USE_BYTECODE_INTERPRETER */
1390 
1391     return FT_Err_Ok;
1392   }
1393 
1394 
1395   /**************************************************************************
1396    *
1397    * @Function:
1398    *   tt_driver_init
1399    *
1400    * @Description:
1401    *   Initialize a given TrueType driver object.
1402    *
1403    * @Input:
1404    *   driver ::
1405    *     A handle to the target driver object.
1406    *
1407    * @Return:
1408    *   FreeType error code.  0 means success.
1409    */
1410   FT_LOCAL_DEF( FT_Error )
1411   tt_driver_init( FT_Module  ttdriver )     /* TT_Driver */
1412   {
1413 
1414 #ifdef TT_USE_BYTECODE_INTERPRETER
1415 
1416     TT_Driver  driver = (TT_Driver)ttdriver;
1417 
1418     driver->interpreter_version = TT_INTERPRETER_VERSION_35;
1419 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1420     driver->interpreter_version = TT_INTERPRETER_VERSION_38;
1421 #endif
1422 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1423     driver->interpreter_version = TT_INTERPRETER_VERSION_40;
1424 #endif
1425 
1426 #else /* !TT_USE_BYTECODE_INTERPRETER */
1427 
1428     FT_UNUSED( ttdriver );
1429 
1430 #endif /* !TT_USE_BYTECODE_INTERPRETER */
1431 
1432     return FT_Err_Ok;
1433   }
1434 
1435 
1436   /**************************************************************************
1437    *
1438    * @Function:
1439    *   tt_driver_done
1440    *
1441    * @Description:
1442    *   Finalize a given TrueType driver.
1443    *
1444    * @Input:
1445    *   driver ::
1446    *     A handle to the target TrueType driver.
1447    */
1448   FT_LOCAL_DEF( void )
1449   tt_driver_done( FT_Module  ttdriver )     /* TT_Driver */
1450   {
1451     FT_UNUSED( ttdriver );
1452   }
1453 
1454 
1455   /**************************************************************************
1456    *
1457    * @Function:
1458    *   tt_slot_init
1459    *
1460    * @Description:
1461    *   Initialize a new slot object.
1462    *
1463    * @InOut:
1464    *   slot ::
1465    *     A handle to the slot object.
1466    *
1467    * @Return:
1468    *   FreeType error code.  0 means success.
1469    */
1470   FT_LOCAL_DEF( FT_Error )
1471   tt_slot_init( FT_GlyphSlot  slot )
1472   {
1473     return FT_GlyphLoader_CreateExtra( slot->internal->loader );
1474   }
1475 
1476 
1477 /* END */