1 /****************************************************************************
   2  *
   3  * sfobjs.c
   4  *
   5  *   SFNT object management (base).
   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 "sfobjs.h"
  21 #include "ttload.h"
  22 #include "ttcmap.h"
  23 #include "ttkern.h"
  24 #include "sfwoff.h"
  25 #include FT_INTERNAL_SFNT_H
  26 #include FT_INTERNAL_DEBUG_H
  27 #include FT_TRUETYPE_IDS_H
  28 #include FT_TRUETYPE_TAGS_H
  29 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
  30 #include FT_SFNT_NAMES_H
  31 
  32 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  33 #include FT_SERVICE_MULTIPLE_MASTERS_H
  34 #include FT_SERVICE_METRICS_VARIATIONS_H
  35 #endif
  36 
  37 #include "sferrors.h"
  38 
  39 #ifdef TT_CONFIG_OPTION_BDF
  40 #include "ttbdf.h"
  41 #endif
  42 
  43 
  44   /**************************************************************************
  45    *
  46    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
  47    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
  48    * messages during execution.
  49    */
  50 #undef  FT_COMPONENT
  51 #define FT_COMPONENT  sfobjs
  52 
  53 
  54 
  55   /* convert a UTF-16 name entry to ASCII */
  56   static FT_String*
  57   tt_name_ascii_from_utf16( TT_Name    entry,
  58                             FT_Memory  memory )
  59   {
  60     FT_String*  string = NULL;
  61     FT_UInt     len, code, n;
  62     FT_Byte*    read   = (FT_Byte*)entry->string;
  63     FT_Error    error;
  64 
  65 
  66     len = (FT_UInt)entry->stringLength / 2;
  67 
  68     if ( FT_NEW_ARRAY( string, len + 1 ) )
  69       return NULL;
  70 
  71     for ( n = 0; n < len; n++ )
  72     {
  73       code = FT_NEXT_USHORT( read );
  74 
  75       if ( code == 0 )
  76         break;
  77 
  78       if ( code < 32 || code > 127 )
  79         code = '?';
  80 
  81       string[n] = (char)code;
  82     }
  83 
  84     string[n] = 0;
  85 
  86     return string;
  87   }
  88 
  89 
  90   /* convert an Apple Roman or symbol name entry to ASCII */
  91   static FT_String*
  92   tt_name_ascii_from_other( TT_Name    entry,
  93                             FT_Memory  memory )
  94   {
  95     FT_String*  string = NULL;
  96     FT_UInt     len, code, n;
  97     FT_Byte*    read   = (FT_Byte*)entry->string;
  98     FT_Error    error;
  99 
 100 
 101     len = (FT_UInt)entry->stringLength;
 102 
 103     if ( FT_NEW_ARRAY( string, len + 1 ) )
 104       return NULL;
 105 
 106     for ( n = 0; n < len; n++ )
 107     {
 108       code = *read++;
 109 
 110       if ( code == 0 )
 111         break;
 112 
 113       if ( code < 32 || code > 127 )
 114         code = '?';
 115 
 116       string[n] = (char)code;
 117     }
 118 
 119     string[n] = 0;
 120 
 121     return string;
 122   }
 123 
 124 
 125   typedef FT_String*  (*TT_Name_ConvertFunc)( TT_Name    entry,
 126                                               FT_Memory  memory );
 127 
 128 
 129   /* documentation is in sfnt.h */
 130 
 131   FT_LOCAL_DEF( FT_Error )
 132   tt_face_get_name( TT_Face      face,
 133                     FT_UShort    nameid,
 134                     FT_String**  name )
 135   {
 136     FT_Memory   memory = face->root.memory;
 137     FT_Error    error  = FT_Err_Ok;
 138     FT_String*  result = NULL;
 139     FT_UShort   n;
 140     TT_Name     rec;
 141 
 142     FT_Int  found_apple         = -1;
 143     FT_Int  found_apple_roman   = -1;
 144     FT_Int  found_apple_english = -1;
 145     FT_Int  found_win           = -1;
 146     FT_Int  found_unicode       = -1;
 147 
 148     FT_Bool  is_english = 0;
 149 
 150     TT_Name_ConvertFunc  convert;
 151 
 152 
 153     FT_ASSERT( name );
 154 
 155     rec = face->name_table.names;
 156     for ( n = 0; n < face->num_names; n++, rec++ )
 157     {
 158       /* According to the OpenType 1.3 specification, only Microsoft or  */
 159       /* Apple platform IDs might be used in the `name' table.  The      */
 160       /* `Unicode' platform is reserved for the `cmap' table, and the    */
 161       /* `ISO' one is deprecated.                                        */
 162       /*                                                                 */
 163       /* However, the Apple TrueType specification doesn't say the same  */
 164       /* thing and goes to suggest that all Unicode `name' table entries */
 165       /* should be coded in UTF-16 (in big-endian format I suppose).     */
 166       /*                                                                 */
 167       if ( rec->nameID == nameid && rec->stringLength > 0 )
 168       {
 169         switch ( rec->platformID )
 170         {
 171         case TT_PLATFORM_APPLE_UNICODE:
 172         case TT_PLATFORM_ISO:
 173           /* there is `languageID' to check there.  We should use this */
 174           /* field only as a last solution when nothing else is        */
 175           /* available.                                                */
 176           /*                                                           */
 177           found_unicode = n;
 178           break;
 179 
 180         case TT_PLATFORM_MACINTOSH:
 181           /* This is a bit special because some fonts will use either    */
 182           /* an English language id, or a Roman encoding id, to indicate */
 183           /* the English version of its font name.                       */
 184           /*                                                             */
 185           if ( rec->languageID == TT_MAC_LANGID_ENGLISH )
 186             found_apple_english = n;
 187           else if ( rec->encodingID == TT_MAC_ID_ROMAN )
 188             found_apple_roman = n;
 189           break;
 190 
 191         case TT_PLATFORM_MICROSOFT:
 192           /* we only take a non-English name when there is nothing */
 193           /* else available in the font                            */
 194           /*                                                       */
 195           if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 )
 196           {
 197             switch ( rec->encodingID )
 198             {
 199             case TT_MS_ID_SYMBOL_CS:
 200             case TT_MS_ID_UNICODE_CS:
 201             case TT_MS_ID_UCS_4:
 202               is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 );
 203               found_win  = n;
 204               break;
 205 
 206             default:
 207               ;
 208             }
 209           }
 210           break;
 211 
 212         default:
 213           ;
 214         }
 215       }
 216     }
 217 
 218     found_apple = found_apple_roman;
 219     if ( found_apple_english >= 0 )
 220       found_apple = found_apple_english;
 221 
 222     /* some fonts contain invalid Unicode or Macintosh formatted entries; */
 223     /* we will thus favor names encoded in Windows formats if available   */
 224     /* (provided it is an English name)                                   */
 225     /*                                                                    */
 226     convert = NULL;
 227     if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) )
 228     {
 229       rec = face->name_table.names + found_win;
 230       switch ( rec->encodingID )
 231       {
 232         /* all Unicode strings are encoded using UTF-16BE */
 233       case TT_MS_ID_UNICODE_CS:
 234       case TT_MS_ID_SYMBOL_CS:
 235         convert = tt_name_ascii_from_utf16;
 236         break;
 237 
 238       case TT_MS_ID_UCS_4:
 239         /* Apparently, if this value is found in a name table entry, it is */
 240         /* documented as `full Unicode repertoire'.  Experience with the   */
 241         /* MsGothic font shipped with Windows Vista shows that this really */
 242         /* means UTF-16 encoded names (UCS-4 values are only used within   */
 243         /* charmaps).                                                      */
 244         convert = tt_name_ascii_from_utf16;
 245         break;
 246 
 247       default:
 248         ;
 249       }
 250     }
 251     else if ( found_apple >= 0 )
 252     {
 253       rec     = face->name_table.names + found_apple;
 254       convert = tt_name_ascii_from_other;
 255     }
 256     else if ( found_unicode >= 0 )
 257     {
 258       rec     = face->name_table.names + found_unicode;
 259       convert = tt_name_ascii_from_utf16;
 260     }
 261 
 262     if ( rec && convert )
 263     {
 264       if ( !rec->string )
 265       {
 266         FT_Stream  stream = face->name_table.stream;
 267 
 268 
 269         if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) ||
 270              FT_STREAM_SEEK( rec->stringOffset )              ||
 271              FT_STREAM_READ( rec->string, rec->stringLength ) )
 272         {
 273           FT_FREE( rec->string );
 274           rec->stringLength = 0;
 275           result            = NULL;
 276           goto Exit;
 277         }
 278       }
 279 
 280       result = convert( rec, memory );
 281     }
 282 
 283   Exit:
 284     *name = result;
 285     return error;
 286   }
 287 
 288 
 289   static FT_Encoding
 290   sfnt_find_encoding( int  platform_id,
 291                       int  encoding_id )
 292   {
 293     typedef struct  TEncoding_
 294     {
 295       int          platform_id;
 296       int          encoding_id;
 297       FT_Encoding  encoding;
 298 
 299     } TEncoding;
 300 
 301     static
 302     const TEncoding  tt_encodings[] =
 303     {
 304       { TT_PLATFORM_ISO,           -1,                  FT_ENCODING_UNICODE },
 305 
 306       { TT_PLATFORM_APPLE_UNICODE, -1,                  FT_ENCODING_UNICODE },
 307 
 308       { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     FT_ENCODING_APPLE_ROMAN },
 309 
 310       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SYMBOL_CS,  FT_ENCODING_MS_SYMBOL },
 311       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UCS_4,      FT_ENCODING_UNICODE },
 312       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE },
 313       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,       FT_ENCODING_SJIS },
 314       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_PRC,        FT_ENCODING_PRC },
 315       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,      FT_ENCODING_BIG5 },
 316       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,    FT_ENCODING_WANSUNG },
 317       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,      FT_ENCODING_JOHAB }
 318     };
 319 
 320     const TEncoding  *cur, *limit;
 321 
 322 
 323     cur   = tt_encodings;
 324     limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
 325 
 326     for ( ; cur < limit; cur++ )
 327     {
 328       if ( cur->platform_id == platform_id )
 329       {
 330         if ( cur->encoding_id == encoding_id ||
 331              cur->encoding_id == -1          )
 332           return cur->encoding;
 333       }
 334     }
 335 
 336     return FT_ENCODING_NONE;
 337   }
 338 
 339 
 340   /* Fill in face->ttc_header.  If the font is not a TTC, it is */
 341   /* synthesized into a TTC with one offset table.              */
 342   static FT_Error
 343   sfnt_open_font( FT_Stream  stream,
 344                   TT_Face    face )
 345   {
 346     FT_Memory  memory = stream->memory;
 347     FT_Error   error;
 348     FT_ULong   tag, offset;
 349 
 350     static const FT_Frame_Field  ttc_header_fields[] =
 351     {
 352 #undef  FT_STRUCTURE
 353 #define FT_STRUCTURE  TTC_HeaderRec
 354 
 355       FT_FRAME_START( 8 ),
 356         FT_FRAME_LONG( version ),
 357         FT_FRAME_LONG( count   ),  /* this is ULong in the specs */
 358       FT_FRAME_END
 359     };
 360 
 361 
 362     face->ttc_header.tag     = 0;
 363     face->ttc_header.version = 0;
 364     face->ttc_header.count   = 0;
 365 
 366   retry:
 367     offset = FT_STREAM_POS();
 368 
 369     if ( FT_READ_ULONG( tag ) )
 370       return error;
 371 
 372     if ( tag == TTAG_wOFF )
 373     {
 374       FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" ));
 375 
 376       if ( FT_STREAM_SEEK( offset ) )
 377         return error;
 378 
 379       error = woff_open_font( stream, face );
 380       if ( error )
 381         return error;
 382 
 383       /* Swap out stream and retry! */
 384       stream = face->root.stream;
 385       goto retry;
 386     }
 387 
 388     if ( tag != 0x00010000UL &&
 389          tag != TTAG_ttcf    &&
 390          tag != TTAG_OTTO    &&
 391          tag != TTAG_true    &&
 392          tag != TTAG_typ1    &&
 393          tag != TTAG_0xA5kbd &&
 394          tag != TTAG_0xA5lst &&
 395          tag != 0x00020000UL )
 396     {
 397       FT_TRACE2(( "  not a font using the SFNT container format\n" ));
 398       return FT_THROW( Unknown_File_Format );
 399     }
 400 
 401     face->ttc_header.tag = TTAG_ttcf;
 402 
 403     if ( tag == TTAG_ttcf )
 404     {
 405       FT_Int  n;
 406 
 407 
 408       FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));
 409 
 410       if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
 411         return error;
 412 
 413       FT_TRACE3(( "                with %ld subfonts\n",
 414                   face->ttc_header.count ));
 415 
 416       if ( face->ttc_header.count == 0 )
 417         return FT_THROW( Invalid_Table );
 418 
 419       /* a rough size estimate: let's conservatively assume that there   */
 420       /* is just a single table info in each subfont header (12 + 16*1 = */
 421       /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */
 422       /* size of the TTC header plus `28*count' bytes for all subfont    */
 423       /* headers                                                         */
 424       if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) )
 425         return FT_THROW( Array_Too_Large );
 426 
 427       /* now read the offsets of each font in the file */
 428       if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
 429         return error;
 430 
 431       if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
 432         return error;
 433 
 434       for ( n = 0; n < face->ttc_header.count; n++ )
 435         face->ttc_header.offsets[n] = FT_GET_ULONG();
 436 
 437       FT_FRAME_EXIT();
 438     }
 439     else
 440     {
 441       FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));
 442 
 443       face->ttc_header.version = 1 << 16;
 444       face->ttc_header.count   = 1;
 445 
 446       if ( FT_NEW( face->ttc_header.offsets ) )
 447         return error;
 448 
 449       face->ttc_header.offsets[0] = offset;
 450     }
 451 
 452     return error;
 453   }
 454 
 455 
 456   FT_LOCAL_DEF( FT_Error )
 457   sfnt_init_face( FT_Stream      stream,
 458                   TT_Face        face,
 459                   FT_Int         face_instance_index,
 460                   FT_Int         num_params,
 461                   FT_Parameter*  params )
 462   {
 463     FT_Error      error;
 464     FT_Library    library = face->root.driver->root.library;
 465     SFNT_Service  sfnt;
 466     FT_Int        face_index;
 467 
 468 
 469     /* for now, parameters are unused */
 470     FT_UNUSED( num_params );
 471     FT_UNUSED( params );
 472 
 473 
 474     sfnt = (SFNT_Service)face->sfnt;
 475     if ( !sfnt )
 476     {
 477       sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
 478       if ( !sfnt )
 479       {
 480         FT_ERROR(( "sfnt_init_face: cannot access `sfnt' module\n" ));
 481         return FT_THROW( Missing_Module );
 482       }
 483 
 484       face->sfnt       = sfnt;
 485       face->goto_table = sfnt->goto_table;
 486     }
 487 
 488     FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS );
 489 
 490 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 491     if ( !face->mm )
 492     {
 493       /* we want the MM interface from the `truetype' module only */
 494       FT_Module  tt_module = FT_Get_Module( library, "truetype" );
 495 
 496 
 497       face->mm = ft_module_get_service( tt_module,
 498                                         FT_SERVICE_ID_MULTI_MASTERS,
 499                                         0 );
 500     }
 501 
 502     if ( !face->var )
 503     {
 504       /* we want the metrics variations interface */
 505       /* from the `truetype' module only          */
 506       FT_Module  tt_module = FT_Get_Module( library, "truetype" );
 507 
 508 
 509       face->var = ft_module_get_service( tt_module,
 510                                          FT_SERVICE_ID_METRICS_VARIATIONS,
 511                                          0 );
 512     }
 513 #endif
 514 
 515     FT_TRACE2(( "SFNT driver\n" ));
 516 
 517     error = sfnt_open_font( stream, face );
 518     if ( error )
 519       return error;
 520 
 521     /* Stream may have changed in sfnt_open_font. */
 522     stream = face->root.stream;
 523 
 524     FT_TRACE2(( "sfnt_init_face: %08p (index %d)\n",
 525                 face,
 526                 face_instance_index ));
 527 
 528     face_index = FT_ABS( face_instance_index ) & 0xFFFF;
 529 
 530     /* value -(N+1) requests information on index N */
 531     if ( face_instance_index < 0 )
 532       face_index--;
 533 
 534     if ( face_index >= face->ttc_header.count )
 535     {
 536       if ( face_instance_index >= 0 )
 537         return FT_THROW( Invalid_Argument );
 538       else
 539         face_index = 0;
 540     }
 541 
 542     if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
 543       return error;
 544 
 545     /* check whether we have a valid TrueType file */
 546     error = sfnt->load_font_dir( face, stream );
 547     if ( error )
 548       return error;
 549 
 550 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 551     {
 552       FT_Memory  memory = face->root.memory;
 553 
 554       FT_ULong  fvar_len;
 555 
 556       FT_ULong  version;
 557       FT_ULong  offset;
 558 
 559       FT_UShort  num_axes;
 560       FT_UShort  axis_size;
 561       FT_UShort  num_instances;
 562       FT_UShort  instance_size;
 563 
 564       FT_Int  instance_index;
 565 
 566       FT_Byte*  default_values  = NULL;
 567       FT_Byte*  instance_values = NULL;
 568 
 569 
 570       instance_index = FT_ABS( face_instance_index ) >> 16;
 571 
 572       /* test whether current face is a GX font with named instances */
 573       if ( face->goto_table( face, TTAG_fvar, stream, &fvar_len ) ||
 574            fvar_len < 20                                          ||
 575            FT_READ_ULONG( version )                               ||
 576            FT_READ_USHORT( offset )                               ||
 577            FT_STREAM_SKIP( 2 ) /* reserved */                     ||
 578            FT_READ_USHORT( num_axes )                             ||
 579            FT_READ_USHORT( axis_size )                            ||
 580            FT_READ_USHORT( num_instances )                        ||
 581            FT_READ_USHORT( instance_size )                        )
 582       {
 583         version       = 0;
 584         offset        = 0;
 585         num_axes      = 0;
 586         axis_size     = 0;
 587         num_instances = 0;
 588         instance_size = 0;
 589       }
 590 
 591       /* check that the data is bound by the table length */
 592       if ( version != 0x00010000UL                    ||
 593            axis_size != 20                            ||
 594            num_axes == 0                              ||
 595            /* `num_axes' limit implied by 16-bit `instance_size' */
 596            num_axes > 0x3FFE                          ||
 597            !( instance_size == 4 + 4 * num_axes ||
 598               instance_size == 6 + 4 * num_axes )     ||
 599            /* `num_instances' limit implied by limited range of name IDs */
 600            num_instances > 0x7EFF                     ||
 601            offset                          +
 602              axis_size * num_axes          +
 603              instance_size * num_instances > fvar_len )
 604         num_instances = 0;
 605       else
 606         face->variation_support |= TT_FACE_FLAG_VAR_FVAR;
 607 
 608       /*
 609        * As documented in the OpenType specification, an entry for the
 610        * default instance may be omitted in the named instance table.  In
 611        * particular this means that even if there is no named instance
 612        * table in the font we actually do have a named instance, namely the
 613        * default instance.
 614        *
 615        * For consistency, we always want the default instance in our list
 616        * of named instances.  If it is missing, we try to synthesize it
 617        * later on.  Here, we have to adjust `num_instances' accordingly.
 618        */
 619 
 620       if ( ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) &&
 621            !( FT_ALLOC( default_values, num_axes * 4 )  ||
 622               FT_ALLOC( instance_values, num_axes * 4 ) )      )
 623       {
 624         /* the current stream position is 16 bytes after the table start */
 625         FT_ULong  array_start = FT_STREAM_POS() - 16 + offset;
 626         FT_ULong  default_value_offset, instance_offset;
 627 
 628         FT_Byte*  p;
 629         FT_UInt   i;
 630 
 631 
 632         default_value_offset = array_start + 8;
 633         p                    = default_values;
 634 
 635         for ( i = 0; i < num_axes; i++ )
 636         {
 637           (void)FT_STREAM_READ_AT( default_value_offset, p, 4 );
 638 
 639           default_value_offset += axis_size;
 640           p                    += 4;
 641         }
 642 
 643         instance_offset = array_start + axis_size * num_axes + 4;
 644 
 645         for ( i = 0; i < num_instances; i++ )
 646         {
 647           (void)FT_STREAM_READ_AT( instance_offset,
 648                                    instance_values,
 649                                    num_axes * 4 );
 650 
 651           if ( !ft_memcmp( default_values, instance_values, num_axes * 4 ) )
 652             break;
 653 
 654           instance_offset += instance_size;
 655         }
 656 
 657         if ( i == num_instances )
 658         {
 659           /* no default instance in named instance table; */
 660           /* we thus have to synthesize it                */
 661           num_instances++;
 662         }
 663       }
 664 
 665       FT_FREE( default_values );
 666       FT_FREE( instance_values );
 667 
 668       /* we don't support Multiple Master CFFs yet; */
 669       /* note that `glyf' or `CFF2' have precedence */
 670       if ( face->goto_table( face, TTAG_glyf, stream, 0 ) &&
 671            face->goto_table( face, TTAG_CFF2, stream, 0 ) &&
 672            !face->goto_table( face, TTAG_CFF, stream, 0 ) )
 673         num_instances = 0;
 674 
 675       /* instance indices in `face_instance_index' start with index 1, */
 676       /* thus `>' and not `>='                                         */
 677       if ( instance_index > num_instances )
 678       {
 679         if ( face_instance_index >= 0 )
 680           return FT_THROW( Invalid_Argument );
 681         else
 682           num_instances = 0;
 683       }
 684 
 685       face->root.style_flags = (FT_Long)num_instances << 16;
 686     }
 687 #endif
 688 
 689     face->root.num_faces  = face->ttc_header.count;
 690     face->root.face_index = face_instance_index;
 691 
 692     return error;
 693   }
 694 
 695 
 696 #define LOAD_( x )                                          \
 697   do                                                        \
 698   {                                                         \
 699     FT_TRACE2(( "`" #x "' " ));                             \
 700     FT_TRACE3(( "-->\n" ));                                 \
 701                                                             \
 702     error = sfnt->load_ ## x( face, stream );               \
 703                                                             \
 704     FT_TRACE2(( "%s\n", ( !error )                          \
 705                         ? "loaded"                          \
 706                         : FT_ERR_EQ( error, Table_Missing ) \
 707                           ? "missing"                       \
 708                           : "failed to load" ));            \
 709     FT_TRACE3(( "\n" ));                                    \
 710   } while ( 0 )
 711 
 712 #define LOADM_( x, vertical )                               \
 713   do                                                        \
 714   {                                                         \
 715     FT_TRACE2(( "`%s" #x "' ",                              \
 716                 vertical ? "vertical " : "" ));             \
 717     FT_TRACE3(( "-->\n" ));                                 \
 718                                                             \
 719     error = sfnt->load_ ## x( face, stream, vertical );     \
 720                                                             \
 721     FT_TRACE2(( "%s\n", ( !error )                          \
 722                         ? "loaded"                          \
 723                         : FT_ERR_EQ( error, Table_Missing ) \
 724                           ? "missing"                       \
 725                           : "failed to load" ));            \
 726     FT_TRACE3(( "\n" ));                                    \
 727   } while ( 0 )
 728 
 729 #define GET_NAME( id, field )                                   \
 730   do                                                            \
 731   {                                                             \
 732     error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \
 733     if ( error )                                                \
 734       goto Exit;                                                \
 735   } while ( 0 )
 736 
 737 
 738   FT_LOCAL_DEF( FT_Error )
 739   sfnt_load_face( FT_Stream      stream,
 740                   TT_Face        face,
 741                   FT_Int         face_instance_index,
 742                   FT_Int         num_params,
 743                   FT_Parameter*  params )
 744   {
 745     FT_Error      error;
 746 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
 747     FT_Error      psnames_error;
 748 #endif
 749     FT_Bool       has_outline;
 750     FT_Bool       is_apple_sbit;
 751     FT_Bool       is_apple_sbix;
 752     FT_Bool       has_CBLC;
 753     FT_Bool       has_CBDT;
 754     FT_Bool       ignore_typographic_family    = FALSE;
 755     FT_Bool       ignore_typographic_subfamily = FALSE;
 756 
 757     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
 758 
 759     FT_UNUSED( face_instance_index );
 760 
 761 
 762     /* Check parameters */
 763 
 764     {
 765       FT_Int  i;
 766 
 767 
 768       for ( i = 0; i < num_params; i++ )
 769       {
 770         if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY )
 771           ignore_typographic_family = TRUE;
 772         else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY )
 773           ignore_typographic_subfamily = TRUE;
 774       }
 775     }
 776 
 777     /* Load tables */
 778 
 779     /* We now support two SFNT-based bitmapped font formats.  They */
 780     /* are recognized easily as they do not include a `glyf'       */
 781     /* table.                                                      */
 782     /*                                                             */
 783     /* The first format comes from Apple, and uses a table named   */
 784     /* `bhed' instead of `head' to store the font header (using    */
 785     /* the same format).  It also doesn't include horizontal and   */
 786     /* vertical metrics tables (i.e. `hhea' and `vhea' tables are  */
 787     /* missing).                                                   */
 788     /*                                                             */
 789     /* The other format comes from Microsoft, and is used with     */
 790     /* WinCE/PocketPC.  It looks like a standard TTF, except that  */
 791     /* it doesn't contain outlines.                                */
 792     /*                                                             */
 793 
 794     FT_TRACE2(( "sfnt_load_face: %08p\n\n", face ));
 795 
 796     /* do we have outlines in there? */
 797 #ifdef FT_CONFIG_OPTION_INCREMENTAL
 798     has_outline = FT_BOOL( face->root.internal->incremental_interface ||
 799                            tt_face_lookup_table( face, TTAG_glyf )    ||
 800                            tt_face_lookup_table( face, TTAG_CFF )     ||
 801                            tt_face_lookup_table( face, TTAG_CFF2 )    );
 802 #else
 803     has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) ||
 804                            tt_face_lookup_table( face, TTAG_CFF )  ||
 805                            tt_face_lookup_table( face, TTAG_CFF2 ) );
 806 #endif
 807 
 808     is_apple_sbit = 0;
 809     is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 );
 810 
 811     /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf'
 812      * outline rendered on top.  We don't support that yet, so just ignore
 813      * the 'glyf' outline and advertise it as a bitmap-only font. */
 814     if ( is_apple_sbix )
 815       has_outline = FALSE;
 816 
 817     /* if this font doesn't contain outlines, we try to load */
 818     /* a `bhed' table                                        */
 819     if ( !has_outline && sfnt->load_bhed )
 820     {
 821       LOAD_( bhed );
 822       is_apple_sbit = FT_BOOL( !error );
 823     }
 824 
 825     /* load the font header (`head' table) if this isn't an Apple */
 826     /* sbit font file                                             */
 827     if ( !is_apple_sbit || is_apple_sbix )
 828     {
 829       LOAD_( head );
 830       if ( error )
 831         goto Exit;
 832     }
 833 
 834     has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 );
 835     has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 );
 836 
 837     /* Ignore outlines for CBLC/CBDT fonts. */
 838     if ( has_CBLC || has_CBDT )
 839       has_outline = FALSE;
 840 
 841     /* OpenType 1.8.2 introduced limits to this value;    */
 842     /* however, they make sense for older SFNT fonts also */
 843     if ( face->header.Units_Per_EM <    16 ||
 844          face->header.Units_Per_EM > 16384 )
 845     {
 846       error = FT_THROW( Invalid_Table );
 847 
 848       goto Exit;
 849     }
 850 
 851     /* the following tables are often not present in embedded TrueType */
 852     /* fonts within PDF documents, so don't check for them.            */
 853     LOAD_( maxp );
 854     LOAD_( cmap );
 855 
 856     /* the following tables are optional in PCL fonts -- */
 857     /* don't check for errors                            */
 858     LOAD_( name );
 859     LOAD_( post );
 860 
 861 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
 862     psnames_error = error;
 863 #endif
 864 
 865     /* do not load the metrics headers and tables if this is an Apple */
 866     /* sbit font file                                                 */
 867     if ( !is_apple_sbit )
 868     {
 869       /* load the `hhea' and `hmtx' tables */
 870       LOADM_( hhea, 0 );
 871       if ( !error )
 872       {
 873         LOADM_( hmtx, 0 );
 874         if ( FT_ERR_EQ( error, Table_Missing ) )
 875         {
 876           error = FT_THROW( Hmtx_Table_Missing );
 877 
 878 #ifdef FT_CONFIG_OPTION_INCREMENTAL
 879           /* If this is an incrementally loaded font and there are */
 880           /* overriding metrics, tolerate a missing `hmtx' table.  */
 881           if ( face->root.internal->incremental_interface          &&
 882                face->root.internal->incremental_interface->funcs->
 883                  get_glyph_metrics                                 )
 884           {
 885             face->horizontal.number_Of_HMetrics = 0;
 886             error                               = FT_Err_Ok;
 887           }
 888 #endif
 889         }
 890       }
 891       else if ( FT_ERR_EQ( error, Table_Missing ) )
 892       {
 893         /* No `hhea' table necessary for SFNT Mac fonts. */
 894         if ( face->format_tag == TTAG_true )
 895         {
 896           FT_TRACE2(( "This is an SFNT Mac font.\n" ));
 897 
 898           has_outline = 0;
 899           error       = FT_Err_Ok;
 900         }
 901         else
 902         {
 903           error = FT_THROW( Horiz_Header_Missing );
 904 
 905 #ifdef FT_CONFIG_OPTION_INCREMENTAL
 906           /* If this is an incrementally loaded font and there are */
 907           /* overriding metrics, tolerate a missing `hhea' table.  */
 908           if ( face->root.internal->incremental_interface          &&
 909                face->root.internal->incremental_interface->funcs->
 910                  get_glyph_metrics                                 )
 911           {
 912             face->horizontal.number_Of_HMetrics = 0;
 913             error                               = FT_Err_Ok;
 914           }
 915 #endif
 916 
 917         }
 918       }
 919 
 920       if ( error )
 921         goto Exit;
 922 
 923       /* try to load the `vhea' and `vmtx' tables */
 924       LOADM_( hhea, 1 );
 925       if ( !error )
 926       {
 927         LOADM_( hmtx, 1 );
 928         if ( !error )
 929           face->vertical_info = 1;
 930       }
 931 
 932       if ( error && FT_ERR_NEQ( error, Table_Missing ) )
 933         goto Exit;
 934 
 935       LOAD_( os2 );
 936       if ( error )
 937       {
 938         /* we treat the table as missing if there are any errors */
 939         face->os2.version = 0xFFFFU;
 940       }
 941     }
 942 
 943     /* the optional tables */
 944 
 945     /* embedded bitmap support */
 946     if ( sfnt->load_eblc )
 947       LOAD_( eblc );
 948 
 949     /* colored glyph support */
 950     if ( sfnt->load_cpal )
 951     {
 952       LOAD_( cpal );
 953       LOAD_( colr );
 954     }
 955 
 956     /* consider the pclt, kerning, and gasp tables as optional */
 957     LOAD_( pclt );
 958     LOAD_( gasp );
 959     LOAD_( kern );
 960 
 961     face->root.num_glyphs = face->max_profile.numGlyphs;
 962 
 963     /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes  */
 964     /* a WWS-only font face.  `WWS' stands for `weight', width', and */
 965     /* `slope', a term used by Microsoft's Windows Presentation      */
 966     /* Foundation (WPF).  This flag has been introduced in version   */
 967     /* 1.5 of the OpenType specification (May 2008).                 */
 968 
 969     face->root.family_name = NULL;
 970     face->root.style_name  = NULL;
 971     if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 )
 972     {
 973       if ( !ignore_typographic_family )
 974         GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name );
 975       if ( !face->root.family_name )
 976         GET_NAME( FONT_FAMILY, &face->root.family_name );
 977 
 978       if ( !ignore_typographic_subfamily )
 979         GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name );
 980       if ( !face->root.style_name )
 981         GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
 982     }
 983     else
 984     {
 985       GET_NAME( WWS_FAMILY, &face->root.family_name );
 986       if ( !face->root.family_name && !ignore_typographic_family )
 987         GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name );
 988       if ( !face->root.family_name )
 989         GET_NAME( FONT_FAMILY, &face->root.family_name );
 990 
 991       GET_NAME( WWS_SUBFAMILY, &face->root.style_name );
 992       if ( !face->root.style_name && !ignore_typographic_subfamily )
 993         GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name );
 994       if ( !face->root.style_name )
 995         GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
 996     }
 997 
 998     /* now set up root fields */
 999     {
1000       FT_Face  root  = &face->root;
1001       FT_Long  flags = root->face_flags;
1002 
1003 
1004       /**********************************************************************
1005        *
1006        * Compute face flags.
1007        */
1008       if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC ||
1009            face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX ||
1010            face->colr                                       )
1011         flags |= FT_FACE_FLAG_COLOR;      /* color glyphs */
1012 
1013       if ( has_outline == TRUE )
1014         flags |= FT_FACE_FLAG_SCALABLE;   /* scalable outlines */
1015 
1016       /* The sfnt driver only supports bitmap fonts natively, thus we */
1017       /* don't set FT_FACE_FLAG_HINTER.                               */
1018       flags |= FT_FACE_FLAG_SFNT       |  /* SFNT file format  */
1019                FT_FACE_FLAG_HORIZONTAL;   /* horizontal data   */
1020 
1021 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
1022       if ( !psnames_error                             &&
1023            face->postscript.FormatType != 0x00030000L )
1024         flags |= FT_FACE_FLAG_GLYPH_NAMES;
1025 #endif
1026 
1027       /* fixed width font? */
1028       if ( face->postscript.isFixedPitch )
1029         flags |= FT_FACE_FLAG_FIXED_WIDTH;
1030 
1031       /* vertical information? */
1032       if ( face->vertical_info )
1033         flags |= FT_FACE_FLAG_VERTICAL;
1034 
1035       /* kerning available ? */
1036       if ( TT_FACE_HAS_KERNING( face ) )
1037         flags |= FT_FACE_FLAG_KERNING;
1038 
1039 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1040       /* Don't bother to load the tables unless somebody asks for them. */
1041       /* No need to do work which will (probably) not be used.          */
1042       if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR )
1043       {
1044         if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
1045              tt_face_lookup_table( face, TTAG_gvar ) != 0 )
1046           flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
1047         if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 )
1048           flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
1049       }
1050 #endif
1051 
1052       root->face_flags = flags;
1053 
1054       /**********************************************************************
1055        *
1056        * Compute style flags.
1057        */
1058 
1059       flags = 0;
1060       if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
1061       {
1062         /* We have an OS/2 table; use the `fsSelection' field.  Bit 9 */
1063         /* indicates an oblique font face.  This flag has been        */
1064         /* introduced in version 1.5 of the OpenType specification.   */
1065 
1066         if ( face->os2.fsSelection & 512 )       /* bit 9 */
1067           flags |= FT_STYLE_FLAG_ITALIC;
1068         else if ( face->os2.fsSelection & 1 )    /* bit 0 */
1069           flags |= FT_STYLE_FLAG_ITALIC;
1070 
1071         if ( face->os2.fsSelection & 32 )        /* bit 5 */
1072           flags |= FT_STYLE_FLAG_BOLD;
1073       }
1074       else
1075       {
1076         /* this is an old Mac font, use the header field */
1077 
1078         if ( face->header.Mac_Style & 1 )
1079           flags |= FT_STYLE_FLAG_BOLD;
1080 
1081         if ( face->header.Mac_Style & 2 )
1082           flags |= FT_STYLE_FLAG_ITALIC;
1083       }
1084 
1085       root->style_flags |= flags;
1086 
1087       /**********************************************************************
1088        *
1089        * Polish the charmaps.
1090        *
1091        *   Try to set the charmap encoding according to the platform &
1092        *   encoding ID of each charmap.  Emulate Unicode charmap if one
1093        *   is missing.
1094        */
1095 
1096       tt_face_build_cmaps( face );  /* ignore errors */
1097 
1098 
1099       /* set the encoding fields */
1100       {
1101         FT_Int   m;
1102 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
1103         FT_Bool  has_unicode = FALSE;
1104 #endif
1105 
1106 
1107         for ( m = 0; m < root->num_charmaps; m++ )
1108         {
1109           FT_CharMap  charmap = root->charmaps[m];
1110 
1111 
1112           charmap->encoding = sfnt_find_encoding( charmap->platform_id,
1113                                                   charmap->encoding_id );
1114 
1115 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
1116 
1117           if ( charmap->encoding == FT_ENCODING_UNICODE   ||
1118                charmap->encoding == FT_ENCODING_MS_SYMBOL )  /* PUA */
1119             has_unicode = TRUE;
1120         }
1121 
1122         /* synthesize Unicode charmap if one is missing */
1123         if ( !has_unicode )
1124         {
1125           FT_CharMapRec cmaprec;
1126 
1127 
1128           cmaprec.face        = root;
1129           cmaprec.platform_id = TT_PLATFORM_MICROSOFT;
1130           cmaprec.encoding_id = TT_MS_ID_UNICODE_CS;
1131           cmaprec.encoding    = FT_ENCODING_UNICODE;
1132 
1133 
1134           error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec,
1135                                NULL, &cmaprec, NULL );
1136           if ( error                                      &&
1137                FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) &&
1138                FT_ERR_NEQ( error, Unimplemented_Feature ) )
1139             goto Exit;
1140           error = FT_Err_Ok;
1141 
1142 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
1143 
1144         }
1145       }
1146 
1147 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1148 
1149       /*
1150        * Now allocate the root array of FT_Bitmap_Size records and
1151        * populate them.  Unfortunately, it isn't possible to indicate bit
1152        * depths in the FT_Bitmap_Size record.  This is a design error.
1153        */
1154       {
1155         FT_UInt  count;
1156 
1157 
1158         count = face->sbit_num_strikes;
1159 
1160         if ( count > 0 )
1161         {
1162           FT_Memory        memory   = face->root.stream->memory;
1163           FT_UShort        em_size  = face->header.Units_Per_EM;
1164           FT_Short         avgwidth = face->os2.xAvgCharWidth;
1165           FT_Size_Metrics  metrics;
1166 
1167           FT_UInt*  sbit_strike_map = NULL;
1168           FT_UInt   strike_idx, bsize_idx;
1169 
1170 
1171           if ( em_size == 0 || face->os2.version == 0xFFFFU )
1172           {
1173             avgwidth = 1;
1174             em_size = 1;
1175           }
1176 
1177           /* to avoid invalid strike data in the `available_sizes' field */
1178           /* of `FT_Face', we map `available_sizes' indices to strike    */
1179           /* indices                                                     */
1180           if ( FT_NEW_ARRAY( root->available_sizes, count ) ||
1181                FT_NEW_ARRAY( sbit_strike_map, count ) )
1182             goto Exit;
1183 
1184           bsize_idx = 0;
1185           for ( strike_idx = 0; strike_idx < count; strike_idx++ )
1186           {
1187             FT_Bitmap_Size*  bsize = root->available_sizes + bsize_idx;
1188 
1189 
1190             error = sfnt->load_strike_metrics( face, strike_idx, &metrics );
1191             if ( error )
1192               continue;
1193 
1194             bsize->height = (FT_Short)( metrics.height >> 6 );
1195             bsize->width  = (FT_Short)(
1196               ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
1197 
1198             bsize->x_ppem = metrics.x_ppem << 6;
1199             bsize->y_ppem = metrics.y_ppem << 6;
1200 
1201             /* assume 72dpi */
1202             bsize->size   = metrics.y_ppem << 6;
1203 
1204             /* only use strikes with valid PPEM values */
1205             if ( bsize->x_ppem && bsize->y_ppem )
1206               sbit_strike_map[bsize_idx++] = strike_idx;
1207           }
1208 
1209           /* reduce array size to the actually used elements */
1210           (void)FT_RENEW_ARRAY( sbit_strike_map, count, bsize_idx );
1211 
1212           /* from now on, all strike indices are mapped */
1213           /* using `sbit_strike_map'                    */
1214           if ( bsize_idx )
1215           {
1216             face->sbit_strike_map = sbit_strike_map;
1217 
1218             root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
1219             root->num_fixed_sizes = (FT_Int)bsize_idx;
1220           }
1221         }
1222       }
1223 
1224 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1225 
1226       /* a font with no bitmaps and no outlines is scalable; */
1227       /* it has only empty glyphs then                       */
1228       if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) )
1229         root->face_flags |= FT_FACE_FLAG_SCALABLE;
1230 
1231 
1232       /**********************************************************************
1233        *
1234        * Set up metrics.
1235        */
1236       if ( FT_IS_SCALABLE( root ) )
1237       {
1238         /* XXX What about if outline header is missing */
1239         /*     (e.g. sfnt wrapped bitmap)?             */
1240         root->bbox.xMin    = face->header.xMin;
1241         root->bbox.yMin    = face->header.yMin;
1242         root->bbox.xMax    = face->header.xMax;
1243         root->bbox.yMax    = face->header.yMax;
1244         root->units_per_EM = face->header.Units_Per_EM;
1245 
1246 
1247         /*
1248          * Computing the ascender/descender/height is tricky.
1249          *
1250          * The OpenType specification v1.8.3 says:
1251          *
1252          *   [OS/2's] sTypoAscender, sTypoDescender and sTypoLineGap fields
1253          *   are intended to allow applications to lay out documents in a
1254          *   typographically-correct and portable fashion.
1255          *
1256          * This is somewhat at odds with the decades of backwards
1257          * compatibility, operating systems and applications doing whatever
1258          * they want, not to mention broken fonts.
1259          *
1260          * Not all fonts have an OS/2 table; in this case, we take the values
1261          * in the horizontal header, although there is nothing stopping the
1262          * values from being unreliable. Even with a OS/2 table, certain fonts
1263          * set the sTypoAscender, sTypoDescender and sTypoLineGap fields to 0
1264          * and instead correctly set usWinAscent and usWinDescent.
1265          *
1266          * As an example, Arial Narrow is shipped as four files ARIALN.TTF,
1267          * ARIALNI.TTF, ARIALNB.TTF and ARIALNBI.TTF. Strangely, all fonts have
1268          * the same values in their sTypo* fields, except ARIALNB.ttf which
1269          * sets them to 0. All of them have different usWinAscent/Descent
1270          * values. The OS/2 table therefore cannot be trusted for computing the
1271          * text height reliably.
1272          *
1273          * As a compromise, do the following:
1274          *
1275          * 1. If the OS/2 table exists and the fsSelection bit 7 is set
1276          *    (USE_TYPO_METRICS), trust the font and use the sTypo* metrics.
1277          * 2. Otherwise, use the `hhea' table's metrics.
1278          * 3. If they are zero and the OS/2 table exists,
1279          *    1. use the OS/2 table's sTypo* metrics if they are non-zero.
1280          *    2. Otherwise, use the OS/2 table's usWin* metrics.
1281          */
1282 
1283         if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 128 )
1284         {
1285           root->ascender  = face->os2.sTypoAscender;
1286           root->descender = face->os2.sTypoDescender;
1287           root->height    = root->ascender - root->descender +
1288                             face->os2.sTypoLineGap;
1289         }
1290         else
1291         {
1292           root->ascender  = face->horizontal.Ascender;
1293           root->descender = face->horizontal.Descender;
1294           root->height    = root->ascender - root->descender +
1295                             face->horizontal.Line_Gap;
1296 
1297           if ( !( root->ascender || root->descender ) )
1298           {
1299             if ( face->os2.version != 0xFFFFU )
1300             {
1301               if ( face->os2.sTypoAscender || face->os2.sTypoDescender )
1302               {
1303                 root->ascender  = face->os2.sTypoAscender;
1304                 root->descender = face->os2.sTypoDescender;
1305                 root->height    = root->ascender - root->descender +
1306                                   face->os2.sTypoLineGap;
1307               }
1308               else
1309               {
1310                 root->ascender  =  (FT_Short)face->os2.usWinAscent;
1311                 root->descender = -(FT_Short)face->os2.usWinDescent;
1312                 root->height    =  root->ascender - root->descender;
1313               }
1314             }
1315           }
1316         }
1317 
1318         root->max_advance_width  =
1319           (FT_Short)face->horizontal.advance_Width_Max;
1320         root->max_advance_height =
1321           (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max
1322                                           : root->height );
1323 
1324         /* See https://www.microsoft.com/typography/otspec/post.htm -- */
1325         /* Adjust underline position from top edge to centre of        */
1326         /* stroke to convert TrueType meaning to FreeType meaning.     */
1327         root->underline_position  = face->postscript.underlinePosition -
1328                                     face->postscript.underlineThickness / 2;
1329         root->underline_thickness = face->postscript.underlineThickness;
1330       }
1331 
1332     }
1333 
1334   Exit:
1335     FT_TRACE2(( "sfnt_load_face: done\n" ));
1336 
1337     return error;
1338   }
1339 
1340 
1341 #undef LOAD_
1342 #undef LOADM_
1343 #undef GET_NAME
1344 
1345 
1346   FT_LOCAL_DEF( void )
1347   sfnt_done_face( TT_Face  face )
1348   {
1349     FT_Memory     memory;
1350     SFNT_Service  sfnt;
1351 
1352 
1353     if ( !face )
1354       return;
1355 
1356     memory = face->root.memory;
1357     sfnt   = (SFNT_Service)face->sfnt;
1358 
1359     if ( sfnt )
1360     {
1361       /* destroy the postscript names table if it is loaded */
1362       if ( sfnt->free_psnames )
1363         sfnt->free_psnames( face );
1364 
1365       /* destroy the embedded bitmaps table if it is loaded */
1366       if ( sfnt->free_eblc )
1367         sfnt->free_eblc( face );
1368 
1369       /* destroy color table data if it is loaded */
1370       if ( sfnt->free_cpal )
1371       {
1372         sfnt->free_cpal( face );
1373         sfnt->free_colr( face );
1374       }
1375     }
1376 
1377 #ifdef TT_CONFIG_OPTION_BDF
1378     /* freeing the embedded BDF properties */
1379     tt_face_free_bdf_props( face );
1380 #endif
1381 
1382     /* freeing the kerning table */
1383     tt_face_done_kern( face );
1384 
1385     /* freeing the collection table */
1386     FT_FREE( face->ttc_header.offsets );
1387     face->ttc_header.count = 0;
1388 
1389     /* freeing table directory */
1390     FT_FREE( face->dir_tables );
1391     face->num_tables = 0;
1392 
1393     {
1394       FT_Stream  stream = FT_FACE_STREAM( face );
1395 
1396 
1397       /* simply release the 'cmap' table frame */
1398       FT_FRAME_RELEASE( face->cmap_table );
1399       face->cmap_size = 0;
1400     }
1401 
1402     face->horz_metrics_size = 0;
1403     face->vert_metrics_size = 0;
1404 
1405     /* freeing vertical metrics, if any */
1406     if ( face->vertical_info )
1407     {
1408       FT_FREE( face->vertical.long_metrics  );
1409       FT_FREE( face->vertical.short_metrics );
1410       face->vertical_info = 0;
1411     }
1412 
1413     /* freeing the gasp table */
1414     FT_FREE( face->gasp.gaspRanges );
1415     face->gasp.numRanges = 0;
1416 
1417     /* freeing the name table */
1418     if ( sfnt )
1419       sfnt->free_name( face );
1420 
1421     /* freeing family and style name */
1422     FT_FREE( face->root.family_name );
1423     FT_FREE( face->root.style_name );
1424 
1425     /* freeing sbit size table */
1426     FT_FREE( face->root.available_sizes );
1427     FT_FREE( face->sbit_strike_map );
1428     face->root.num_fixed_sizes = 0;
1429 
1430     FT_FREE( face->postscript_name );
1431 
1432 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1433     FT_FREE( face->var_postscript_prefix );
1434 #endif
1435 
1436     /* freeing glyph color palette data */
1437     FT_FREE( face->palette_data.palette_name_ids );
1438     FT_FREE( face->palette_data.palette_flags );
1439     FT_FREE( face->palette_data.palette_entry_name_ids );
1440     FT_FREE( face->palette );
1441 
1442     face->sfnt = NULL;
1443   }
1444 
1445 
1446 /* END */