misc/libfreetype/src/sfnt/sfobjs.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
equal deleted inserted replaced
9371:f3840de881bd 9372:915436ff64ab
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  sfobjs.c                                                               */
       
     4 /*                                                                         */
       
     5 /*    SFNT object management (base).                                       */
       
     6 /*                                                                         */
       
     7 /*  Copyright 1996-2008, 2010-2011 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 "sferrors.h"
       
    31 
       
    32 #ifdef TT_CONFIG_OPTION_BDF
       
    33 #include "ttbdf.h"
       
    34 #endif
       
    35 
       
    36 
       
    37   /*************************************************************************/
       
    38   /*                                                                       */
       
    39   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
       
    40   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
       
    41   /* messages during execution.                                            */
       
    42   /*                                                                       */
       
    43 #undef  FT_COMPONENT
       
    44 #define FT_COMPONENT  trace_sfobjs
       
    45 
       
    46 
       
    47 
       
    48   /* convert a UTF-16 name entry to ASCII */
       
    49   static FT_String*
       
    50   tt_name_entry_ascii_from_utf16( TT_NameEntry  entry,
       
    51                                   FT_Memory     memory )
       
    52   {
       
    53     FT_String*  string = NULL;
       
    54     FT_UInt     len, code, n;
       
    55     FT_Byte*    read   = (FT_Byte*)entry->string;
       
    56     FT_Error    error;
       
    57 
       
    58 
       
    59     len = (FT_UInt)entry->stringLength / 2;
       
    60 
       
    61     if ( FT_NEW_ARRAY( string, len + 1 ) )
       
    62       return NULL;
       
    63 
       
    64     for ( n = 0; n < len; n++ )
       
    65     {
       
    66       code = FT_NEXT_USHORT( read );
       
    67       if ( code < 32 || code > 127 )
       
    68         code = '?';
       
    69 
       
    70       string[n] = (char)code;
       
    71     }
       
    72 
       
    73     string[len] = 0;
       
    74 
       
    75     return string;
       
    76   }
       
    77 
       
    78 
       
    79   /* convert an Apple Roman or symbol name entry to ASCII */
       
    80   static FT_String*
       
    81   tt_name_entry_ascii_from_other( TT_NameEntry  entry,
       
    82                                   FT_Memory     memory )
       
    83   {
       
    84     FT_String*  string = NULL;
       
    85     FT_UInt     len, code, n;
       
    86     FT_Byte*    read   = (FT_Byte*)entry->string;
       
    87     FT_Error    error;
       
    88 
       
    89 
       
    90     len = (FT_UInt)entry->stringLength;
       
    91 
       
    92     if ( FT_NEW_ARRAY( string, len + 1 ) )
       
    93       return NULL;
       
    94 
       
    95     for ( n = 0; n < len; n++ )
       
    96     {
       
    97       code = *read++;
       
    98       if ( code < 32 || code > 127 )
       
    99         code = '?';
       
   100 
       
   101       string[n] = (char)code;
       
   102     }
       
   103 
       
   104     string[len] = 0;
       
   105 
       
   106     return string;
       
   107   }
       
   108 
       
   109 
       
   110   typedef FT_String*  (*TT_NameEntry_ConvertFunc)( TT_NameEntry  entry,
       
   111                                                    FT_Memory     memory );
       
   112 
       
   113 
       
   114   /*************************************************************************/
       
   115   /*                                                                       */
       
   116   /* <Function>                                                            */
       
   117   /*    tt_face_get_name                                                   */
       
   118   /*                                                                       */
       
   119   /* <Description>                                                         */
       
   120   /*    Returns a given ENGLISH name record in ASCII.                      */
       
   121   /*                                                                       */
       
   122   /* <Input>                                                               */
       
   123   /*    face   :: A handle to the source face object.                      */
       
   124   /*                                                                       */
       
   125   /*    nameid :: The name id of the name record to return.                */
       
   126   /*                                                                       */
       
   127   /* <InOut>                                                               */
       
   128   /*    name   :: The address of a string pointer.  NULL if no name is     */
       
   129   /*              present.                                                 */
       
   130   /*                                                                       */
       
   131   /* <Return>                                                              */
       
   132   /*    FreeType error code.  0 means success.                             */
       
   133   /*                                                                       */
       
   134   static FT_Error
       
   135   tt_face_get_name( TT_Face      face,
       
   136                     FT_UShort    nameid,
       
   137                     FT_String**  name )
       
   138   {
       
   139     FT_Memory         memory = face->root.memory;
       
   140     FT_Error          error  = SFNT_Err_Ok;
       
   141     FT_String*        result = NULL;
       
   142     FT_UShort         n;
       
   143     TT_NameEntryRec*  rec;
       
   144     FT_Int            found_apple         = -1;
       
   145     FT_Int            found_apple_roman   = -1;
       
   146     FT_Int            found_apple_english = -1;
       
   147     FT_Int            found_win           = -1;
       
   148     FT_Int            found_unicode       = -1;
       
   149 
       
   150     FT_Bool           is_english = 0;
       
   151 
       
   152     TT_NameEntry_ConvertFunc  convert;
       
   153 
       
   154 
       
   155     FT_ASSERT( name );
       
   156 
       
   157     rec = face->name_table.names;
       
   158     for ( n = 0; n < face->num_names; n++, rec++ )
       
   159     {
       
   160       /* According to the OpenType 1.3 specification, only Microsoft or  */
       
   161       /* Apple platform IDs might be used in the `name' table.  The      */
       
   162       /* `Unicode' platform is reserved for the `cmap' table, and the    */
       
   163       /* `ISO' one is deprecated.                                        */
       
   164       /*                                                                 */
       
   165       /* However, the Apple TrueType specification doesn't say the same  */
       
   166       /* thing and goes to suggest that all Unicode `name' table entries */
       
   167       /* should be coded in UTF-16 (in big-endian format I suppose).     */
       
   168       /*                                                                 */
       
   169       if ( rec->nameID == nameid && rec->stringLength > 0 )
       
   170       {
       
   171         switch ( rec->platformID )
       
   172         {
       
   173         case TT_PLATFORM_APPLE_UNICODE:
       
   174         case TT_PLATFORM_ISO:
       
   175           /* there is `languageID' to check there.  We should use this */
       
   176           /* field only as a last solution when nothing else is        */
       
   177           /* available.                                                */
       
   178           /*                                                           */
       
   179           found_unicode = n;
       
   180           break;
       
   181 
       
   182         case TT_PLATFORM_MACINTOSH:
       
   183           /* This is a bit special because some fonts will use either    */
       
   184           /* an English language id, or a Roman encoding id, to indicate */
       
   185           /* the English version of its font name.                       */
       
   186           /*                                                             */
       
   187           if ( rec->languageID == TT_MAC_LANGID_ENGLISH )
       
   188             found_apple_english = n;
       
   189           else if ( rec->encodingID == TT_MAC_ID_ROMAN )
       
   190             found_apple_roman = n;
       
   191           break;
       
   192 
       
   193         case TT_PLATFORM_MICROSOFT:
       
   194           /* we only take a non-English name when there is nothing */
       
   195           /* else available in the font                            */
       
   196           /*                                                       */
       
   197           if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 )
       
   198           {
       
   199             switch ( rec->encodingID )
       
   200             {
       
   201             case TT_MS_ID_SYMBOL_CS:
       
   202             case TT_MS_ID_UNICODE_CS:
       
   203             case TT_MS_ID_UCS_4:
       
   204               is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 );
       
   205               found_win  = n;
       
   206               break;
       
   207 
       
   208             default:
       
   209               ;
       
   210             }
       
   211           }
       
   212           break;
       
   213 
       
   214         default:
       
   215           ;
       
   216         }
       
   217       }
       
   218     }
       
   219 
       
   220     found_apple = found_apple_roman;
       
   221     if ( found_apple_english >= 0 )
       
   222       found_apple = found_apple_english;
       
   223 
       
   224     /* some fonts contain invalid Unicode or Macintosh formatted entries; */
       
   225     /* we will thus favor names encoded in Windows formats if available   */
       
   226     /* (provided it is an English name)                                   */
       
   227     /*                                                                    */
       
   228     convert = NULL;
       
   229     if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) )
       
   230     {
       
   231       rec = face->name_table.names + found_win;
       
   232       switch ( rec->encodingID )
       
   233       {
       
   234         /* all Unicode strings are encoded using UTF-16BE */
       
   235       case TT_MS_ID_UNICODE_CS:
       
   236       case TT_MS_ID_SYMBOL_CS:
       
   237         convert = tt_name_entry_ascii_from_utf16;
       
   238         break;
       
   239 
       
   240       case TT_MS_ID_UCS_4:
       
   241         /* Apparently, if this value is found in a name table entry, it is */
       
   242         /* documented as `full Unicode repertoire'.  Experience with the   */
       
   243         /* MsGothic font shipped with Windows Vista shows that this really */
       
   244         /* means UTF-16 encoded names (UCS-4 values are only used within   */
       
   245         /* charmaps).                                                      */
       
   246         convert = tt_name_entry_ascii_from_utf16;
       
   247         break;
       
   248 
       
   249       default:
       
   250         ;
       
   251       }
       
   252     }
       
   253     else if ( found_apple >= 0 )
       
   254     {
       
   255       rec     = face->name_table.names + found_apple;
       
   256       convert = tt_name_entry_ascii_from_other;
       
   257     }
       
   258     else if ( found_unicode >= 0 )
       
   259     {
       
   260       rec     = face->name_table.names + found_unicode;
       
   261       convert = tt_name_entry_ascii_from_utf16;
       
   262     }
       
   263 
       
   264     if ( rec && convert )
       
   265     {
       
   266       if ( rec->string == NULL )
       
   267       {
       
   268         FT_Stream  stream = face->name_table.stream;
       
   269 
       
   270 
       
   271         if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) ||
       
   272              FT_STREAM_SEEK( rec->stringOffset )              ||
       
   273              FT_STREAM_READ( rec->string, rec->stringLength ) )
       
   274         {
       
   275           FT_FREE( rec->string );
       
   276           rec->stringLength = 0;
       
   277           result            = NULL;
       
   278           goto Exit;
       
   279         }
       
   280       }
       
   281 
       
   282       result = convert( rec, memory );
       
   283     }
       
   284 
       
   285   Exit:
       
   286     *name = result;
       
   287     return error;
       
   288   }
       
   289 
       
   290 
       
   291   static FT_Encoding
       
   292   sfnt_find_encoding( int  platform_id,
       
   293                       int  encoding_id )
       
   294   {
       
   295     typedef struct  TEncoding_
       
   296     {
       
   297       int          platform_id;
       
   298       int          encoding_id;
       
   299       FT_Encoding  encoding;
       
   300 
       
   301     } TEncoding;
       
   302 
       
   303     static
       
   304     const TEncoding  tt_encodings[] =
       
   305     {
       
   306       { TT_PLATFORM_ISO,           -1,                  FT_ENCODING_UNICODE },
       
   307 
       
   308       { TT_PLATFORM_APPLE_UNICODE, -1,                  FT_ENCODING_UNICODE },
       
   309 
       
   310       { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     FT_ENCODING_APPLE_ROMAN },
       
   311 
       
   312       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SYMBOL_CS,  FT_ENCODING_MS_SYMBOL },
       
   313       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UCS_4,      FT_ENCODING_UNICODE },
       
   314       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE },
       
   315       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,       FT_ENCODING_SJIS },
       
   316       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_GB2312,     FT_ENCODING_GB2312 },
       
   317       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,      FT_ENCODING_BIG5 },
       
   318       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,    FT_ENCODING_WANSUNG },
       
   319       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,      FT_ENCODING_JOHAB }
       
   320     };
       
   321 
       
   322     const TEncoding  *cur, *limit;
       
   323 
       
   324 
       
   325     cur   = tt_encodings;
       
   326     limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
       
   327 
       
   328     for ( ; cur < limit; cur++ )
       
   329     {
       
   330       if ( cur->platform_id == platform_id )
       
   331       {
       
   332         if ( cur->encoding_id == encoding_id ||
       
   333              cur->encoding_id == -1          )
       
   334           return cur->encoding;
       
   335       }
       
   336     }
       
   337 
       
   338     return FT_ENCODING_NONE;
       
   339   }
       
   340 
       
   341 
       
   342   /* Fill in face->ttc_header.  If the font is not a TTC, it is */
       
   343   /* synthesized into a TTC with one offset table.              */
       
   344   static FT_Error
       
   345   sfnt_open_font( FT_Stream  stream,
       
   346                   TT_Face    face )
       
   347   {
       
   348     FT_Memory  memory = stream->memory;
       
   349     FT_Error   error;
       
   350     FT_ULong   tag, offset;
       
   351 
       
   352     static const FT_Frame_Field  ttc_header_fields[] =
       
   353     {
       
   354 #undef  FT_STRUCTURE
       
   355 #define FT_STRUCTURE  TTC_HeaderRec
       
   356 
       
   357       FT_FRAME_START( 8 ),
       
   358         FT_FRAME_LONG( version ),
       
   359         FT_FRAME_LONG( count   ),  /* this is ULong in the specs */
       
   360       FT_FRAME_END
       
   361     };
       
   362 
       
   363 
       
   364     face->ttc_header.tag     = 0;
       
   365     face->ttc_header.version = 0;
       
   366     face->ttc_header.count   = 0;
       
   367 
       
   368     offset = FT_STREAM_POS();
       
   369 
       
   370     if ( FT_READ_ULONG( tag ) )
       
   371       return error;
       
   372 
       
   373     if ( tag != 0x00010000UL &&
       
   374          tag != TTAG_ttcf    &&
       
   375          tag != TTAG_OTTO    &&
       
   376          tag != TTAG_true    &&
       
   377          tag != TTAG_typ1    &&
       
   378          tag != 0x00020000UL )
       
   379       return SFNT_Err_Unknown_File_Format;
       
   380 
       
   381     face->ttc_header.tag = TTAG_ttcf;
       
   382 
       
   383     if ( tag == TTAG_ttcf )
       
   384     {
       
   385       FT_Int  n;
       
   386 
       
   387 
       
   388       FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));
       
   389 
       
   390       if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
       
   391         return error;
       
   392 
       
   393       if ( face->ttc_header.count == 0 )
       
   394         return SFNT_Err_Invalid_Table;
       
   395 
       
   396       /* a rough size estimate: let's conservatively assume that there   */
       
   397       /* is just a single table info in each subfont header (12 + 16*1 = */
       
   398       /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */
       
   399       /* size of the TTC header plus `28*count' bytes for all subfont    */
       
   400       /* headers                                                         */
       
   401       if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) )
       
   402         return SFNT_Err_Array_Too_Large;
       
   403 
       
   404       /* now read the offsets of each font in the file */
       
   405       if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
       
   406         return error;
       
   407 
       
   408       if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
       
   409         return error;
       
   410 
       
   411       for ( n = 0; n < face->ttc_header.count; n++ )
       
   412         face->ttc_header.offsets[n] = FT_GET_ULONG();
       
   413 
       
   414       FT_FRAME_EXIT();
       
   415     }
       
   416     else
       
   417     {
       
   418       FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));
       
   419 
       
   420       face->ttc_header.version = 1 << 16;
       
   421       face->ttc_header.count   = 1;
       
   422 
       
   423       if ( FT_NEW( face->ttc_header.offsets ) )
       
   424         return error;
       
   425 
       
   426       face->ttc_header.offsets[0] = offset;
       
   427     }
       
   428 
       
   429     return error;
       
   430   }
       
   431 
       
   432 
       
   433   FT_LOCAL_DEF( FT_Error )
       
   434   sfnt_init_face( FT_Stream      stream,
       
   435                   TT_Face        face,
       
   436                   FT_Int         face_index,
       
   437                   FT_Int         num_params,
       
   438                   FT_Parameter*  params )
       
   439   {
       
   440     FT_Error        error;
       
   441     FT_Library      library = face->root.driver->root.library;
       
   442     SFNT_Service    sfnt;
       
   443 
       
   444 
       
   445     /* for now, parameters are unused */
       
   446     FT_UNUSED( num_params );
       
   447     FT_UNUSED( params );
       
   448 
       
   449 
       
   450     sfnt = (SFNT_Service)face->sfnt;
       
   451     if ( !sfnt )
       
   452     {
       
   453       sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
       
   454       if ( !sfnt )
       
   455         return SFNT_Err_Invalid_File_Format;
       
   456 
       
   457       face->sfnt       = sfnt;
       
   458       face->goto_table = sfnt->goto_table;
       
   459     }
       
   460 
       
   461     FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS );
       
   462 
       
   463     error = sfnt_open_font( stream, face );
       
   464     if ( error )
       
   465       return error;
       
   466 
       
   467     FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index ));
       
   468 
       
   469     if ( face_index < 0 )
       
   470       face_index = 0;
       
   471 
       
   472     if ( face_index >= face->ttc_header.count )
       
   473       return SFNT_Err_Invalid_Argument;
       
   474 
       
   475     if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
       
   476       return error;
       
   477 
       
   478     /* check that we have a valid TrueType file */
       
   479     error = sfnt->load_font_dir( face, stream );
       
   480     if ( error )
       
   481       return error;
       
   482 
       
   483     face->root.num_faces  = face->ttc_header.count;
       
   484     face->root.face_index = face_index;
       
   485 
       
   486     return error;
       
   487   }
       
   488 
       
   489 
       
   490 #define LOAD_( x )                                            \
       
   491   do {                                                        \
       
   492     FT_TRACE2(( "`" #x "' " ));                               \
       
   493     FT_TRACE3(( "-->\n" ));                                   \
       
   494                                                               \
       
   495     error = sfnt->load_##x( face, stream );                   \
       
   496                                                               \
       
   497     FT_TRACE2(( "%s\n", ( !error )                            \
       
   498                         ? "loaded"                            \
       
   499                         : ( error == SFNT_Err_Table_Missing ) \
       
   500                           ? "missing"                         \
       
   501                           : "failed to load" ));              \
       
   502     FT_TRACE3(( "\n" ));                                      \
       
   503   } while ( 0 )
       
   504 
       
   505 #define LOADM_( x, vertical )                                 \
       
   506   do {                                                        \
       
   507     FT_TRACE2(( "`%s" #x "' ",                                \
       
   508                 vertical ? "vertical " : "" ));               \
       
   509     FT_TRACE3(( "-->\n" ));                                   \
       
   510                                                               \
       
   511     error = sfnt->load_##x( face, stream, vertical );         \
       
   512                                                               \
       
   513     FT_TRACE2(( "%s\n", ( !error )                            \
       
   514                         ? "loaded"                            \
       
   515                         : ( error == SFNT_Err_Table_Missing ) \
       
   516                           ? "missing"                         \
       
   517                           : "failed to load" ));              \
       
   518     FT_TRACE3(( "\n" ));                                      \
       
   519   } while ( 0 )
       
   520 
       
   521 #define GET_NAME( id, field )                                 \
       
   522   do {                                                        \
       
   523     error = tt_face_get_name( face, TT_NAME_ID_##id, field ); \
       
   524     if ( error )                                              \
       
   525       goto Exit;                                              \
       
   526   } while ( 0 )
       
   527 
       
   528 
       
   529   FT_LOCAL_DEF( FT_Error )
       
   530   sfnt_load_face( FT_Stream      stream,
       
   531                   TT_Face        face,
       
   532                   FT_Int         face_index,
       
   533                   FT_Int         num_params,
       
   534                   FT_Parameter*  params )
       
   535   {
       
   536     FT_Error      error;
       
   537 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
       
   538     FT_Error      psnames_error;
       
   539 #endif
       
   540     FT_Bool       has_outline;
       
   541     FT_Bool       is_apple_sbit;
       
   542     FT_Bool       ignore_preferred_family = FALSE;
       
   543     FT_Bool       ignore_preferred_subfamily = FALSE;
       
   544 
       
   545     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
       
   546 
       
   547     FT_UNUSED( face_index );
       
   548 
       
   549     /* Check parameters */
       
   550 
       
   551     {
       
   552       FT_Int  i;
       
   553 
       
   554 
       
   555       for ( i = 0; i < num_params; i++ )
       
   556       {
       
   557         if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY )
       
   558           ignore_preferred_family = TRUE;
       
   559         else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY )
       
   560           ignore_preferred_subfamily = TRUE;
       
   561       }
       
   562     }
       
   563 
       
   564     /* Load tables */
       
   565 
       
   566     /* We now support two SFNT-based bitmapped font formats.  They */
       
   567     /* are recognized easily as they do not include a `glyf'       */
       
   568     /* table.                                                      */
       
   569     /*                                                             */
       
   570     /* The first format comes from Apple, and uses a table named   */
       
   571     /* `bhed' instead of `head' to store the font header (using    */
       
   572     /* the same format).  It also doesn't include horizontal and   */
       
   573     /* vertical metrics tables (i.e. `hhea' and `vhea' tables are  */
       
   574     /* missing).                                                   */
       
   575     /*                                                             */
       
   576     /* The other format comes from Microsoft, and is used with     */
       
   577     /* WinCE/PocketPC.  It looks like a standard TTF, except that  */
       
   578     /* it doesn't contain outlines.                                */
       
   579     /*                                                             */
       
   580 
       
   581     FT_TRACE2(( "sfnt_load_face: %08p\n\n", face ));
       
   582 
       
   583     /* do we have outlines in there? */
       
   584 #ifdef FT_CONFIG_OPTION_INCREMENTAL
       
   585     has_outline   = FT_BOOL( face->root.internal->incremental_interface != 0 ||
       
   586                              tt_face_lookup_table( face, TTAG_glyf )    != 0 ||
       
   587                              tt_face_lookup_table( face, TTAG_CFF )     != 0 );
       
   588 #else
       
   589     has_outline   = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
       
   590                              tt_face_lookup_table( face, TTAG_CFF )  != 0 );
       
   591 #endif
       
   592 
       
   593     is_apple_sbit = 0;
       
   594 
       
   595     /* if this font doesn't contain outlines, we try to load */
       
   596     /* a `bhed' table                                        */
       
   597     if ( !has_outline && sfnt->load_bhed )
       
   598     {
       
   599       LOAD_( bhed );
       
   600       is_apple_sbit = FT_BOOL( !error );
       
   601     }
       
   602 
       
   603     /* load the font header (`head' table) if this isn't an Apple */
       
   604     /* sbit font file                                             */
       
   605     if ( !is_apple_sbit )
       
   606     {
       
   607       LOAD_( head );
       
   608       if ( error )
       
   609         goto Exit;
       
   610     }
       
   611 
       
   612     if ( face->header.Units_Per_EM == 0 )
       
   613     {
       
   614       error = SFNT_Err_Invalid_Table;
       
   615 
       
   616       goto Exit;
       
   617     }
       
   618 
       
   619     /* the following tables are often not present in embedded TrueType */
       
   620     /* fonts within PDF documents, so don't check for them.            */
       
   621     LOAD_( maxp );
       
   622     LOAD_( cmap );
       
   623 
       
   624     /* the following tables are optional in PCL fonts -- */
       
   625     /* don't check for errors                            */
       
   626     LOAD_( name );
       
   627     LOAD_( post );
       
   628 
       
   629 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
       
   630     psnames_error = error;
       
   631 #endif
       
   632 
       
   633     /* do not load the metrics headers and tables if this is an Apple */
       
   634     /* sbit font file                                                 */
       
   635     if ( !is_apple_sbit )
       
   636     {
       
   637       /* load the `hhea' and `hmtx' tables */
       
   638       LOADM_( hhea, 0 );
       
   639       if ( !error )
       
   640       {
       
   641         LOADM_( hmtx, 0 );
       
   642         if ( error == SFNT_Err_Table_Missing )
       
   643         {
       
   644           error = SFNT_Err_Hmtx_Table_Missing;
       
   645 
       
   646 #ifdef FT_CONFIG_OPTION_INCREMENTAL
       
   647           /* If this is an incrementally loaded font and there are */
       
   648           /* overriding metrics, tolerate a missing `hmtx' table.  */
       
   649           if ( face->root.internal->incremental_interface          &&
       
   650                face->root.internal->incremental_interface->funcs->
       
   651                  get_glyph_metrics                                 )
       
   652           {
       
   653             face->horizontal.number_Of_HMetrics = 0;
       
   654             error = SFNT_Err_Ok;
       
   655           }
       
   656 #endif
       
   657         }
       
   658       }
       
   659       else if ( error == SFNT_Err_Table_Missing )
       
   660       {
       
   661         /* No `hhea' table necessary for SFNT Mac fonts. */
       
   662         if ( face->format_tag == TTAG_true )
       
   663         {
       
   664           FT_TRACE2(( "This is an SFNT Mac font.\n" ));
       
   665           has_outline = 0;
       
   666           error = SFNT_Err_Ok;
       
   667         }
       
   668         else
       
   669         {
       
   670           error = SFNT_Err_Horiz_Header_Missing;
       
   671 
       
   672 #ifdef FT_CONFIG_OPTION_INCREMENTAL
       
   673           /* If this is an incrementally loaded font and there are */
       
   674           /* overriding metrics, tolerate a missing `hhea' table.  */
       
   675           if ( face->root.internal->incremental_interface          &&
       
   676                face->root.internal->incremental_interface->funcs->
       
   677                  get_glyph_metrics                                 )
       
   678           {
       
   679             face->horizontal.number_Of_HMetrics = 0;
       
   680             error = SFNT_Err_Ok;
       
   681           }
       
   682 #endif
       
   683 
       
   684         }
       
   685       }
       
   686 
       
   687       if ( error )
       
   688         goto Exit;
       
   689 
       
   690       /* try to load the `vhea' and `vmtx' tables */
       
   691       LOADM_( hhea, 1 );
       
   692       if ( !error )
       
   693       {
       
   694         LOADM_( hmtx, 1 );
       
   695         if ( !error )
       
   696           face->vertical_info = 1;
       
   697       }
       
   698 
       
   699       if ( error && error != SFNT_Err_Table_Missing )
       
   700         goto Exit;
       
   701 
       
   702       LOAD_( os2 );
       
   703       if ( error )
       
   704       {
       
   705         /* we treat the table as missing if there are any errors */
       
   706         face->os2.version = 0xFFFFU;
       
   707       }
       
   708     }
       
   709 
       
   710     /* the optional tables */
       
   711 
       
   712     /* embedded bitmap support */
       
   713     if ( sfnt->load_eblc )
       
   714     {
       
   715       LOAD_( eblc );
       
   716       if ( error )
       
   717       {
       
   718         /* a font which contains neither bitmaps nor outlines is */
       
   719         /* still valid (although rather useless in most cases);  */
       
   720         /* however, you can find such stripped fonts in PDFs     */
       
   721         if ( error == SFNT_Err_Table_Missing )
       
   722           error = SFNT_Err_Ok;
       
   723         else
       
   724           goto Exit;
       
   725       }
       
   726     }
       
   727 
       
   728     LOAD_( pclt );
       
   729     if ( error )
       
   730     {
       
   731       if ( error != SFNT_Err_Table_Missing )
       
   732         goto Exit;
       
   733 
       
   734       face->pclt.Version = 0;
       
   735     }
       
   736 
       
   737     /* consider the kerning and gasp tables as optional */
       
   738     LOAD_( gasp );
       
   739     LOAD_( kern );
       
   740 
       
   741     face->root.num_glyphs = face->max_profile.numGlyphs;
       
   742 
       
   743     /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes  */
       
   744     /* a WWS-only font face.  `WWS' stands for `weight', width', and */
       
   745     /* `slope', a term used by Microsoft's Windows Presentation      */
       
   746     /* Foundation (WPF).  This flag has been introduced in version   */
       
   747     /* 1.5 of the OpenType specification (May 2008).                 */
       
   748 
       
   749     face->root.family_name = NULL;
       
   750     face->root.style_name  = NULL;
       
   751     if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 )
       
   752     {
       
   753       if ( !ignore_preferred_family )
       
   754         GET_NAME( PREFERRED_FAMILY, &face->root.family_name );
       
   755       if ( !face->root.family_name )
       
   756         GET_NAME( FONT_FAMILY, &face->root.family_name );
       
   757 
       
   758       if ( !ignore_preferred_subfamily )
       
   759         GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );
       
   760       if ( !face->root.style_name )
       
   761         GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
       
   762     }
       
   763     else
       
   764     {
       
   765       GET_NAME( WWS_FAMILY, &face->root.family_name );
       
   766       if ( !face->root.family_name && !ignore_preferred_family )
       
   767         GET_NAME( PREFERRED_FAMILY, &face->root.family_name );
       
   768       if ( !face->root.family_name )
       
   769         GET_NAME( FONT_FAMILY, &face->root.family_name );
       
   770 
       
   771       GET_NAME( WWS_SUBFAMILY, &face->root.style_name );
       
   772       if ( !face->root.style_name && !ignore_preferred_subfamily )
       
   773         GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );
       
   774       if ( !face->root.style_name )
       
   775         GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
       
   776     }
       
   777 
       
   778     /* now set up root fields */
       
   779     {
       
   780       FT_Face  root  = &face->root;
       
   781       FT_Long  flags = root->face_flags;
       
   782 
       
   783 
       
   784       /*********************************************************************/
       
   785       /*                                                                   */
       
   786       /* Compute face flags.                                               */
       
   787       /*                                                                   */
       
   788       if ( has_outline == TRUE )
       
   789         flags |= FT_FACE_FLAG_SCALABLE;   /* scalable outlines */
       
   790 
       
   791       /* The sfnt driver only supports bitmap fonts natively, thus we */
       
   792       /* don't set FT_FACE_FLAG_HINTER.                               */
       
   793       flags |= FT_FACE_FLAG_SFNT       |  /* SFNT file format  */
       
   794                FT_FACE_FLAG_HORIZONTAL;   /* horizontal data   */
       
   795 
       
   796 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
       
   797       if ( psnames_error == SFNT_Err_Ok               &&
       
   798            face->postscript.FormatType != 0x00030000L )
       
   799         flags |= FT_FACE_FLAG_GLYPH_NAMES;
       
   800 #endif
       
   801 
       
   802       /* fixed width font? */
       
   803       if ( face->postscript.isFixedPitch )
       
   804         flags |= FT_FACE_FLAG_FIXED_WIDTH;
       
   805 
       
   806       /* vertical information? */
       
   807       if ( face->vertical_info )
       
   808         flags |= FT_FACE_FLAG_VERTICAL;
       
   809 
       
   810       /* kerning available ? */
       
   811       if ( TT_FACE_HAS_KERNING( face ) )
       
   812         flags |= FT_FACE_FLAG_KERNING;
       
   813 
       
   814 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
       
   815       /* Don't bother to load the tables unless somebody asks for them. */
       
   816       /* No need to do work which will (probably) not be used.          */
       
   817       if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
       
   818            tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
       
   819            tt_face_lookup_table( face, TTAG_gvar ) != 0 )
       
   820         flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
       
   821 #endif
       
   822 
       
   823       root->face_flags = flags;
       
   824 
       
   825       /*********************************************************************/
       
   826       /*                                                                   */
       
   827       /* Compute style flags.                                              */
       
   828       /*                                                                   */
       
   829 
       
   830       flags = 0;
       
   831       if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
       
   832       {
       
   833         /* We have an OS/2 table; use the `fsSelection' field.  Bit 9 */
       
   834         /* indicates an oblique font face.  This flag has been        */
       
   835         /* introduced in version 1.5 of the OpenType specification.   */
       
   836 
       
   837         if ( face->os2.fsSelection & 512 )       /* bit 9 */
       
   838           flags |= FT_STYLE_FLAG_ITALIC;
       
   839         else if ( face->os2.fsSelection & 1 )    /* bit 0 */
       
   840           flags |= FT_STYLE_FLAG_ITALIC;
       
   841 
       
   842         if ( face->os2.fsSelection & 32 )        /* bit 5 */
       
   843           flags |= FT_STYLE_FLAG_BOLD;
       
   844       }
       
   845       else
       
   846       {
       
   847         /* this is an old Mac font, use the header field */
       
   848 
       
   849         if ( face->header.Mac_Style & 1 )
       
   850           flags |= FT_STYLE_FLAG_BOLD;
       
   851 
       
   852         if ( face->header.Mac_Style & 2 )
       
   853           flags |= FT_STYLE_FLAG_ITALIC;
       
   854       }
       
   855 
       
   856       root->style_flags = flags;
       
   857 
       
   858       /*********************************************************************/
       
   859       /*                                                                   */
       
   860       /* Polish the charmaps.                                              */
       
   861       /*                                                                   */
       
   862       /*   Try to set the charmap encoding according to the platform &     */
       
   863       /*   encoding ID of each charmap.                                    */
       
   864       /*                                                                   */
       
   865 
       
   866       tt_face_build_cmaps( face );  /* ignore errors */
       
   867 
       
   868 
       
   869       /* set the encoding fields */
       
   870       {
       
   871         FT_Int  m;
       
   872 
       
   873 
       
   874         for ( m = 0; m < root->num_charmaps; m++ )
       
   875         {
       
   876           FT_CharMap  charmap = root->charmaps[m];
       
   877 
       
   878 
       
   879           charmap->encoding = sfnt_find_encoding( charmap->platform_id,
       
   880                                                   charmap->encoding_id );
       
   881 
       
   882 #if 0
       
   883           if ( root->charmap     == NULL &&
       
   884                charmap->encoding == FT_ENCODING_UNICODE )
       
   885           {
       
   886             /* set 'root->charmap' to the first Unicode encoding we find */
       
   887             root->charmap = charmap;
       
   888           }
       
   889 #endif
       
   890         }
       
   891       }
       
   892 
       
   893 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
       
   894 
       
   895       /*
       
   896        *  Now allocate the root array of FT_Bitmap_Size records and
       
   897        *  populate them.  Unfortunately, it isn't possible to indicate bit
       
   898        *  depths in the FT_Bitmap_Size record.  This is a design error.
       
   899        */
       
   900       {
       
   901         FT_UInt  i, count;
       
   902 
       
   903 
       
   904 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
       
   905         count = face->sbit_num_strikes;
       
   906 #else
       
   907         count = (FT_UInt)face->num_sbit_strikes;
       
   908 #endif
       
   909 
       
   910         if ( count > 0 )
       
   911         {
       
   912           FT_Memory        memory   = face->root.stream->memory;
       
   913           FT_UShort        em_size  = face->header.Units_Per_EM;
       
   914           FT_Short         avgwidth = face->os2.xAvgCharWidth;
       
   915           FT_Size_Metrics  metrics;
       
   916 
       
   917 
       
   918           if ( em_size == 0 || face->os2.version == 0xFFFFU )
       
   919           {
       
   920             avgwidth = 0;
       
   921             em_size = 1;
       
   922           }
       
   923 
       
   924           if ( FT_NEW_ARRAY( root->available_sizes, count ) )
       
   925             goto Exit;
       
   926 
       
   927           for ( i = 0; i < count; i++ )
       
   928           {
       
   929             FT_Bitmap_Size*  bsize = root->available_sizes + i;
       
   930 
       
   931 
       
   932             error = sfnt->load_strike_metrics( face, i, &metrics );
       
   933             if ( error )
       
   934               goto Exit;
       
   935 
       
   936             bsize->height = (FT_Short)( metrics.height >> 6 );
       
   937             bsize->width = (FT_Short)(
       
   938                 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
       
   939 
       
   940             bsize->x_ppem = metrics.x_ppem << 6;
       
   941             bsize->y_ppem = metrics.y_ppem << 6;
       
   942 
       
   943             /* assume 72dpi */
       
   944             bsize->size   = metrics.y_ppem << 6;
       
   945           }
       
   946 
       
   947           root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
       
   948           root->num_fixed_sizes = (FT_Int)count;
       
   949         }
       
   950       }
       
   951 
       
   952 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
       
   953 
       
   954       /* a font with no bitmaps and no outlines is scalable; */
       
   955       /* it has only empty glyphs then                       */
       
   956       if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) )
       
   957         root->face_flags |= FT_FACE_FLAG_SCALABLE;
       
   958 
       
   959 
       
   960       /*********************************************************************/
       
   961       /*                                                                   */
       
   962       /*  Set up metrics.                                                  */
       
   963       /*                                                                   */
       
   964       if ( FT_IS_SCALABLE( root ) )
       
   965       {
       
   966         /* XXX What about if outline header is missing */
       
   967         /*     (e.g. sfnt wrapped bitmap)?             */
       
   968         root->bbox.xMin    = face->header.xMin;
       
   969         root->bbox.yMin    = face->header.yMin;
       
   970         root->bbox.xMax    = face->header.xMax;
       
   971         root->bbox.yMax    = face->header.yMax;
       
   972         root->units_per_EM = face->header.Units_Per_EM;
       
   973 
       
   974 
       
   975         /* XXX: Computing the ascender/descender/height is very different */
       
   976         /*      from what the specification tells you.  Apparently, we    */
       
   977         /*      must be careful because                                   */
       
   978         /*                                                                */
       
   979         /*      - not all fonts have an OS/2 table; in this case, we take */
       
   980         /*        the values in the horizontal header.  However, these    */
       
   981         /*        values very often are not reliable.                     */
       
   982         /*                                                                */
       
   983         /*      - otherwise, the correct typographic values are in the    */
       
   984         /*        sTypoAscender, sTypoDescender & sTypoLineGap fields.    */
       
   985         /*                                                                */
       
   986         /*        However, certain fonts have these fields set to 0.      */
       
   987         /*        Rather, they have usWinAscent & usWinDescent correctly  */
       
   988         /*        set (but with different values).                        */
       
   989         /*                                                                */
       
   990         /*      As an example, Arial Narrow is implemented through four   */
       
   991         /*      files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
       
   992         /*                                                                */
       
   993         /*      Strangely, all fonts have the same values in their        */
       
   994         /*      sTypoXXX fields, except ARIALNB which sets them to 0.     */
       
   995         /*                                                                */
       
   996         /*      On the other hand, they all have different                */
       
   997         /*      usWinAscent/Descent values -- as a conclusion, the OS/2   */
       
   998         /*      table cannot be used to compute the text height reliably! */
       
   999         /*                                                                */
       
  1000 
       
  1001         /* The ascender/descender/height are computed from the OS/2 table */
       
  1002         /* when found.  Otherwise, they're taken from the horizontal      */
       
  1003         /* header.                                                        */
       
  1004         /*                                                                */
       
  1005 
       
  1006         root->ascender  = face->horizontal.Ascender;
       
  1007         root->descender = face->horizontal.Descender;
       
  1008 
       
  1009         root->height    = (FT_Short)( root->ascender - root->descender +
       
  1010                                       face->horizontal.Line_Gap );
       
  1011 
       
  1012 #if 0
       
  1013         /* if the line_gap is 0, we add an extra 15% to the text height --  */
       
  1014         /* this computation is based on various versions of Times New Roman */
       
  1015         if ( face->horizontal.Line_Gap == 0 )
       
  1016           root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
       
  1017 #endif /* 0 */
       
  1018 
       
  1019 #if 0
       
  1020         /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
       
  1021         /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF             */
       
  1022         if ( face->os2.version != 0xFFFFU && root->ascender )
       
  1023         {
       
  1024           FT_Int  height;
       
  1025 
       
  1026 
       
  1027           root->ascender  =  face->os2.sTypoAscender;
       
  1028           root->descender = -face->os2.sTypoDescender;
       
  1029 
       
  1030           height = root->ascender + root->descender + face->os2.sTypoLineGap;
       
  1031           if ( height > root->height )
       
  1032             root->height = height;
       
  1033         }
       
  1034 #endif /* 0 */
       
  1035 
       
  1036         root->max_advance_width  = face->horizontal.advance_Width_Max;
       
  1037         root->max_advance_height = (FT_Short)( face->vertical_info
       
  1038                                      ? face->vertical.advance_Height_Max
       
  1039                                      : root->height );
       
  1040 
       
  1041         /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */
       
  1042         /* Adjust underline position from top edge to centre of     */
       
  1043         /* stroke to convert TrueType meaning to FreeType meaning.  */
       
  1044         root->underline_position  = face->postscript.underlinePosition -
       
  1045                                     face->postscript.underlineThickness / 2;
       
  1046         root->underline_thickness = face->postscript.underlineThickness;
       
  1047       }
       
  1048 
       
  1049     }
       
  1050 
       
  1051   Exit:
       
  1052     FT_TRACE2(( "sfnt_load_face: done\n" ));
       
  1053 
       
  1054     return error;
       
  1055   }
       
  1056 
       
  1057 
       
  1058 #undef LOAD_
       
  1059 #undef LOADM_
       
  1060 #undef GET_NAME
       
  1061 
       
  1062 
       
  1063   FT_LOCAL_DEF( void )
       
  1064   sfnt_done_face( TT_Face  face )
       
  1065   {
       
  1066     FT_Memory     memory;
       
  1067     SFNT_Service  sfnt;
       
  1068 
       
  1069 
       
  1070     if ( !face )
       
  1071       return;
       
  1072 
       
  1073     memory = face->root.memory;
       
  1074     sfnt   = (SFNT_Service)face->sfnt;
       
  1075 
       
  1076     if ( sfnt )
       
  1077     {
       
  1078       /* destroy the postscript names table if it is loaded */
       
  1079       if ( sfnt->free_psnames )
       
  1080         sfnt->free_psnames( face );
       
  1081 
       
  1082       /* destroy the embedded bitmaps table if it is loaded */
       
  1083       if ( sfnt->free_eblc )
       
  1084         sfnt->free_eblc( face );
       
  1085     }
       
  1086 
       
  1087 #ifdef TT_CONFIG_OPTION_BDF
       
  1088     /* freeing the embedded BDF properties */
       
  1089     tt_face_free_bdf_props( face );
       
  1090 #endif
       
  1091 
       
  1092     /* freeing the kerning table */
       
  1093     tt_face_done_kern( face );
       
  1094 
       
  1095     /* freeing the collection table */
       
  1096     FT_FREE( face->ttc_header.offsets );
       
  1097     face->ttc_header.count = 0;
       
  1098 
       
  1099     /* freeing table directory */
       
  1100     FT_FREE( face->dir_tables );
       
  1101     face->num_tables = 0;
       
  1102 
       
  1103     {
       
  1104       FT_Stream  stream = FT_FACE_STREAM( face );
       
  1105 
       
  1106 
       
  1107       /* simply release the 'cmap' table frame */
       
  1108       FT_FRAME_RELEASE( face->cmap_table );
       
  1109       face->cmap_size = 0;
       
  1110     }
       
  1111 
       
  1112     /* freeing the horizontal metrics */
       
  1113 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
       
  1114     {
       
  1115       FT_Stream  stream = FT_FACE_STREAM( face );
       
  1116 
       
  1117 
       
  1118       FT_FRAME_RELEASE( face->horz_metrics );
       
  1119       FT_FRAME_RELEASE( face->vert_metrics );
       
  1120       face->horz_metrics_size = 0;
       
  1121       face->vert_metrics_size = 0;
       
  1122     }
       
  1123 #else
       
  1124     FT_FREE( face->horizontal.long_metrics );
       
  1125     FT_FREE( face->horizontal.short_metrics );
       
  1126 #endif
       
  1127 
       
  1128     /* freeing the vertical ones, if any */
       
  1129     if ( face->vertical_info )
       
  1130     {
       
  1131       FT_FREE( face->vertical.long_metrics  );
       
  1132       FT_FREE( face->vertical.short_metrics );
       
  1133       face->vertical_info = 0;
       
  1134     }
       
  1135 
       
  1136     /* freeing the gasp table */
       
  1137     FT_FREE( face->gasp.gaspRanges );
       
  1138     face->gasp.numRanges = 0;
       
  1139 
       
  1140     /* freeing the name table */
       
  1141     if ( sfnt )
       
  1142       sfnt->free_name( face );
       
  1143 
       
  1144     /* freeing family and style name */
       
  1145     FT_FREE( face->root.family_name );
       
  1146     FT_FREE( face->root.style_name );
       
  1147 
       
  1148     /* freeing sbit size table */
       
  1149     FT_FREE( face->root.available_sizes );
       
  1150     face->root.num_fixed_sizes = 0;
       
  1151 
       
  1152     FT_FREE( face->postscript_name );
       
  1153 
       
  1154     face->sfnt = 0;
       
  1155   }
       
  1156 
       
  1157 
       
  1158 /* END */