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