Home | History | Annotate | Download | only in sfnt
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  sfobjs.c                                                               */
      4 /*                                                                         */
      5 /*    SFNT object management (base).                                       */
      6 /*                                                                         */
      7 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 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   ),
    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       /* now read the offsets of each font in the file */
    394       if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
    395         return error;
    396 
    397       if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
    398         return error;
    399 
    400       for ( n = 0; n < face->ttc_header.count; n++ )
    401         face->ttc_header.offsets[n] = FT_GET_ULONG();
    402 
    403       FT_FRAME_EXIT();
    404     }
    405     else
    406     {
    407       FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));
    408 
    409       face->ttc_header.version = 1 << 16;
    410       face->ttc_header.count   = 1;
    411 
    412       if ( FT_NEW( face->ttc_header.offsets ) )
    413         return error;
    414 
    415       face->ttc_header.offsets[0] = offset;
    416     }
    417 
    418     return error;
    419   }
    420 
    421 
    422   FT_LOCAL_DEF( FT_Error )
    423   sfnt_init_face( FT_Stream      stream,
    424                   TT_Face        face,
    425                   FT_Int         face_index,
    426                   FT_Int         num_params,
    427                   FT_Parameter*  params )
    428   {
    429     FT_Error        error;
    430     FT_Library      library = face->root.driver->root.library;
    431     SFNT_Service    sfnt;
    432 
    433 
    434     /* for now, parameters are unused */
    435     FT_UNUSED( num_params );
    436     FT_UNUSED( params );
    437 
    438 
    439     sfnt = (SFNT_Service)face->sfnt;
    440     if ( !sfnt )
    441     {
    442       sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
    443       if ( !sfnt )
    444         return SFNT_Err_Invalid_File_Format;
    445 
    446       face->sfnt       = sfnt;
    447       face->goto_table = sfnt->goto_table;
    448     }
    449 
    450     FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS );
    451 
    452     error = sfnt_open_font( stream, face );
    453     if ( error )
    454       return error;
    455 
    456     FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index ));
    457 
    458     if ( face_index < 0 )
    459       face_index = 0;
    460 
    461     if ( face_index >= face->ttc_header.count )
    462       return SFNT_Err_Invalid_Argument;
    463 
    464     if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
    465       return error;
    466 
    467     /* check that we have a valid TrueType file */
    468     error = sfnt->load_font_dir( face, stream );
    469     if ( error )
    470       return error;
    471 
    472     face->root.num_faces  = face->ttc_header.count;
    473     face->root.face_index = face_index;
    474 
    475     return error;
    476   }
    477 
    478 
    479 #define LOAD_( x )                                            \
    480   do {                                                        \
    481     FT_TRACE2(( "`" #x "' " ));                               \
    482     FT_TRACE3(( "-->\n" ));                                   \
    483                                                               \
    484     error = sfnt->load_##x( face, stream );                   \
    485                                                               \
    486     FT_TRACE2(( "%s\n", ( !error )                            \
    487                         ? "loaded"                            \
    488                         : ( error == SFNT_Err_Table_Missing ) \
    489                           ? "missing"                         \
    490                           : "failed to load" ));              \
    491     FT_TRACE3(( "\n" ));                                      \
    492   } while ( 0 )
    493 
    494 #define LOADM_( x, vertical )                                 \
    495   do {                                                        \
    496     FT_TRACE2(( "`%s" #x "' ",                                \
    497                 vertical ? "vertical " : "" ));               \
    498     FT_TRACE3(( "-->\n" ));                                   \
    499                                                               \
    500     error = sfnt->load_##x( face, stream, vertical );         \
    501                                                               \
    502     FT_TRACE2(( "%s\n", ( !error )                            \
    503                         ? "loaded"                            \
    504                         : ( error == SFNT_Err_Table_Missing ) \
    505                           ? "missing"                         \
    506                           : "failed to load" ));              \
    507     FT_TRACE3(( "\n" ));                                      \
    508   } while ( 0 )
    509 
    510 #define GET_NAME( id, field )                                 \
    511   do {                                                        \
    512     error = tt_face_get_name( face, TT_NAME_ID_##id, field ); \
    513     if ( error )                                              \
    514       goto Exit;                                              \
    515   } while ( 0 )
    516 
    517 
    518   FT_LOCAL_DEF( FT_Error )
    519   sfnt_load_face( FT_Stream      stream,
    520                   TT_Face        face,
    521                   FT_Int         face_index,
    522                   FT_Int         num_params,
    523                   FT_Parameter*  params )
    524   {
    525     FT_Error      error;
    526 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    527     FT_Error      psnames_error;
    528 #endif
    529     FT_Bool       has_outline;
    530     FT_Bool       is_apple_sbit;
    531     FT_Bool       ignore_preferred_family = FALSE;
    532     FT_Bool       ignore_preferred_subfamily = FALSE;
    533 
    534     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
    535 
    536     FT_UNUSED( face_index );
    537 
    538     /* Check parameters */
    539 
    540     {
    541       FT_Int  i;
    542 
    543 
    544       for ( i = 0; i < num_params; i++ )
    545       {
    546         if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY )
    547           ignore_preferred_family = TRUE;
    548         else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY )
    549           ignore_preferred_subfamily = TRUE;
    550       }
    551     }
    552 
    553     /* Load tables */
    554 
    555     /* We now support two SFNT-based bitmapped font formats.  They */
    556     /* are recognized easily as they do not include a `glyf'       */
    557     /* table.                                                      */
    558     /*                                                             */
    559     /* The first format comes from Apple, and uses a table named   */
    560     /* `bhed' instead of `head' to store the font header (using    */
    561     /* the same format).  It also doesn't include horizontal and   */
    562     /* vertical metrics tables (i.e. `hhea' and `vhea' tables are  */
    563     /* missing).                                                   */
    564     /*                                                             */
    565     /* The other format comes from Microsoft, and is used with     */
    566     /* WinCE/PocketPC.  It looks like a standard TTF, except that  */
    567     /* it doesn't contain outlines.                                */
    568     /*                                                             */
    569 
    570     FT_TRACE2(( "sfnt_load_face: %08p\n\n", face ));
    571 
    572     /* do we have outlines in there? */
    573 #ifdef FT_CONFIG_OPTION_INCREMENTAL
    574     has_outline   = FT_BOOL( face->root.internal->incremental_interface != 0 ||
    575                              tt_face_lookup_table( face, TTAG_glyf )    != 0 ||
    576                              tt_face_lookup_table( face, TTAG_CFF )     != 0 );
    577 #else
    578     has_outline   = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
    579                              tt_face_lookup_table( face, TTAG_CFF )  != 0 );
    580 #endif
    581 
    582     is_apple_sbit = 0;
    583 
    584     /* if this font doesn't contain outlines, we try to load */
    585     /* a `bhed' table                                        */
    586     if ( !has_outline && sfnt->load_bhed )
    587     {
    588       LOAD_( bhed );
    589       is_apple_sbit = FT_BOOL( !error );
    590     }
    591 
    592     /* load the font header (`head' table) if this isn't an Apple */
    593     /* sbit font file                                             */
    594     if ( !is_apple_sbit )
    595     {
    596       LOAD_( head );
    597       if ( error )
    598         goto Exit;
    599     }
    600 
    601     if ( face->header.Units_Per_EM == 0 )
    602     {
    603       error = SFNT_Err_Invalid_Table;
    604 
    605       goto Exit;
    606     }
    607 
    608     /* the following tables are often not present in embedded TrueType */
    609     /* fonts within PDF documents, so don't check for them.            */
    610     LOAD_( maxp );
    611     LOAD_( cmap );
    612 
    613     /* the following tables are optional in PCL fonts -- */
    614     /* don't check for errors                            */
    615     LOAD_( name );
    616     LOAD_( post );
    617 
    618 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    619     psnames_error = error;
    620 #endif
    621 
    622     /* do not load the metrics headers and tables if this is an Apple */
    623     /* sbit font file                                                 */
    624     if ( !is_apple_sbit )
    625     {
    626       /* load the `hhea' and `hmtx' tables */
    627       LOADM_( hhea, 0 );
    628       if ( !error )
    629       {
    630         LOADM_( hmtx, 0 );
    631         if ( error == SFNT_Err_Table_Missing )
    632         {
    633           error = SFNT_Err_Hmtx_Table_Missing;
    634 
    635 #ifdef FT_CONFIG_OPTION_INCREMENTAL
    636           /* If this is an incrementally loaded font and there are */
    637           /* overriding metrics, tolerate a missing `hmtx' table.  */
    638           if ( face->root.internal->incremental_interface          &&
    639                face->root.internal->incremental_interface->funcs->
    640                  get_glyph_metrics                                 )
    641           {
    642             face->horizontal.number_Of_HMetrics = 0;
    643             error = SFNT_Err_Ok;
    644           }
    645 #endif
    646         }
    647       }
    648       else if ( error == SFNT_Err_Table_Missing )
    649       {
    650         /* No `hhea' table necessary for SFNT Mac fonts. */
    651         if ( face->format_tag == TTAG_true )
    652         {
    653           FT_TRACE2(( "This is an SFNT Mac font.\n" ));
    654           has_outline = 0;
    655           error = SFNT_Err_Ok;
    656         }
    657         else
    658         {
    659           error = SFNT_Err_Horiz_Header_Missing;
    660 
    661 #ifdef FT_CONFIG_OPTION_INCREMENTAL
    662           /* If this is an incrementally loaded font and there are */
    663           /* overriding metrics, tolerate a missing `hhea' table.  */
    664           if ( face->root.internal->incremental_interface          &&
    665                face->root.internal->incremental_interface->funcs->
    666                  get_glyph_metrics                                 )
    667           {
    668             face->horizontal.number_Of_HMetrics = 0;
    669             error = SFNT_Err_Ok;
    670           }
    671 #endif
    672 
    673         }
    674       }
    675 
    676       if ( error )
    677         goto Exit;
    678 
    679       /* try to load the `vhea' and `vmtx' tables */
    680       LOADM_( hhea, 1 );
    681       if ( !error )
    682       {
    683         LOADM_( hmtx, 1 );
    684         if ( !error )
    685           face->vertical_info = 1;
    686       }
    687 
    688       if ( error && error != SFNT_Err_Table_Missing )
    689         goto Exit;
    690 
    691       LOAD_( os2 );
    692       if ( error )
    693       {
    694         if ( error != SFNT_Err_Table_Missing )
    695           goto Exit;
    696 
    697         face->os2.version = 0xFFFFU;
    698       }
    699     }
    700 
    701     /* the optional tables */
    702 
    703     /* embedded bitmap support */
    704     if ( sfnt->load_eblc )
    705     {
    706       LOAD_( eblc );
    707       if ( error )
    708       {
    709         /* a font which contains neither bitmaps nor outlines is */
    710         /* still valid (although rather useless in most cases);  */
    711         /* however, you can find such stripped fonts in PDFs     */
    712         if ( error == SFNT_Err_Table_Missing )
    713           error = SFNT_Err_Ok;
    714         else
    715           goto Exit;
    716       }
    717     }
    718 
    719     LOAD_( pclt );
    720     if ( error )
    721     {
    722       if ( error != SFNT_Err_Table_Missing )
    723         goto Exit;
    724 
    725       face->pclt.Version = 0;
    726     }
    727 
    728     /* consider the kerning and gasp tables as optional */
    729     LOAD_( gasp );
    730     LOAD_( kern );
    731 
    732     face->root.num_glyphs = face->max_profile.numGlyphs;
    733 
    734     /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes  */
    735     /* a WWS-only font face.  `WWS' stands for `weight', width', and */
    736     /* `slope', a term used by Microsoft's Windows Presentation      */
    737     /* Foundation (WPF).  This flag has been introduced in version   */
    738     /* 1.5 of the OpenType specification (May 2008).                 */
    739 
    740     face->root.family_name = NULL;
    741     face->root.style_name  = NULL;
    742     if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 )
    743     {
    744       if ( !ignore_preferred_family )
    745         GET_NAME( PREFERRED_FAMILY, &face->root.family_name );
    746       if ( !face->root.family_name )
    747         GET_NAME( FONT_FAMILY, &face->root.family_name );
    748 
    749       if ( !ignore_preferred_subfamily )
    750         GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );
    751       if ( !face->root.style_name )
    752         GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
    753     }
    754     else
    755     {
    756       GET_NAME( WWS_FAMILY, &face->root.family_name );
    757       if ( !face->root.family_name && !ignore_preferred_family )
    758         GET_NAME( PREFERRED_FAMILY, &face->root.family_name );
    759       if ( !face->root.family_name )
    760         GET_NAME( FONT_FAMILY, &face->root.family_name );
    761 
    762       GET_NAME( WWS_SUBFAMILY, &face->root.style_name );
    763       if ( !face->root.style_name && !ignore_preferred_subfamily )
    764         GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );
    765       if ( !face->root.style_name )
    766         GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
    767     }
    768 
    769     /* now set up root fields */
    770     {
    771       FT_Face  root  = &face->root;
    772       FT_Long  flags = root->face_flags;
    773 
    774 
    775       /*********************************************************************/
    776       /*                                                                   */
    777       /* Compute face flags.                                               */
    778       /*                                                                   */
    779       if ( has_outline == TRUE )
    780         flags |= FT_FACE_FLAG_SCALABLE;   /* scalable outlines */
    781 
    782       /* The sfnt driver only supports bitmap fonts natively, thus we */
    783       /* don't set FT_FACE_FLAG_HINTER.                               */
    784       flags |= FT_FACE_FLAG_SFNT       |  /* SFNT file format  */
    785                FT_FACE_FLAG_HORIZONTAL;   /* horizontal data   */
    786 
    787 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    788       if ( psnames_error == SFNT_Err_Ok               &&
    789            face->postscript.FormatType != 0x00030000L )
    790         flags |= FT_FACE_FLAG_GLYPH_NAMES;
    791 #endif
    792 
    793       /* fixed width font? */
    794       if ( face->postscript.isFixedPitch )
    795         flags |= FT_FACE_FLAG_FIXED_WIDTH;
    796 
    797       /* vertical information? */
    798       if ( face->vertical_info )
    799         flags |= FT_FACE_FLAG_VERTICAL;
    800 
    801       /* kerning available ? */
    802       if ( TT_FACE_HAS_KERNING( face ) )
    803         flags |= FT_FACE_FLAG_KERNING;
    804 
    805 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    806       /* Don't bother to load the tables unless somebody asks for them. */
    807       /* No need to do work which will (probably) not be used.          */
    808       if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
    809            tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
    810            tt_face_lookup_table( face, TTAG_gvar ) != 0 )
    811         flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
    812 #endif
    813 
    814       root->face_flags = flags;
    815 
    816       /*********************************************************************/
    817       /*                                                                   */
    818       /* Compute style flags.                                              */
    819       /*                                                                   */
    820 
    821       flags = 0;
    822       if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
    823       {
    824         /* We have an OS/2 table; use the `fsSelection' field.  Bit 9 */
    825         /* indicates an oblique font face.  This flag has been        */
    826         /* introduced in version 1.5 of the OpenType specification.   */
    827 
    828         if ( face->os2.fsSelection & 512 )       /* bit 9 */
    829           flags |= FT_STYLE_FLAG_ITALIC;
    830         else if ( face->os2.fsSelection & 1 )    /* bit 0 */
    831           flags |= FT_STYLE_FLAG_ITALIC;
    832 
    833         if ( face->os2.fsSelection & 32 )        /* bit 5 */
    834           flags |= FT_STYLE_FLAG_BOLD;
    835       }
    836       else
    837       {
    838         /* this is an old Mac font, use the header field */
    839 
    840         if ( face->header.Mac_Style & 1 )
    841           flags |= FT_STYLE_FLAG_BOLD;
    842 
    843         if ( face->header.Mac_Style & 2 )
    844           flags |= FT_STYLE_FLAG_ITALIC;
    845       }
    846 
    847       root->style_flags = flags;
    848 
    849       /*********************************************************************/
    850       /*                                                                   */
    851       /* Polish the charmaps.                                              */
    852       /*                                                                   */
    853       /*   Try to set the charmap encoding according to the platform &     */
    854       /*   encoding ID of each charmap.                                    */
    855       /*                                                                   */
    856 
    857       tt_face_build_cmaps( face );  /* ignore errors */
    858 
    859 
    860       /* set the encoding fields */
    861       {
    862         FT_Int  m;
    863 
    864 
    865         for ( m = 0; m < root->num_charmaps; m++ )
    866         {
    867           FT_CharMap  charmap = root->charmaps[m];
    868 
    869 
    870           charmap->encoding = sfnt_find_encoding( charmap->platform_id,
    871                                                   charmap->encoding_id );
    872 
    873 #if 0
    874           if ( root->charmap     == NULL &&
    875                charmap->encoding == FT_ENCODING_UNICODE )
    876           {
    877             /* set 'root->charmap' to the first Unicode encoding we find */
    878             root->charmap = charmap;
    879           }
    880 #endif
    881         }
    882       }
    883 
    884 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
    885 
    886       /*
    887        *  Now allocate the root array of FT_Bitmap_Size records and
    888        *  populate them.  Unfortunately, it isn't possible to indicate bit
    889        *  depths in the FT_Bitmap_Size record.  This is a design error.
    890        */
    891       {
    892         FT_UInt  i, count;
    893 
    894 
    895 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
    896         count = face->sbit_num_strikes;
    897 #else
    898         count = (FT_UInt)face->num_sbit_strikes;
    899 #endif
    900 
    901         if ( count > 0 )
    902         {
    903           FT_Memory        memory   = face->root.stream->memory;
    904           FT_UShort        em_size  = face->header.Units_Per_EM;
    905           FT_Short         avgwidth = face->os2.xAvgCharWidth;
    906           FT_Size_Metrics  metrics;
    907 
    908 
    909           if ( em_size == 0 || face->os2.version == 0xFFFFU )
    910           {
    911             avgwidth = 0;
    912             em_size = 1;
    913           }
    914 
    915           if ( FT_NEW_ARRAY( root->available_sizes, count ) )
    916             goto Exit;
    917 
    918           for ( i = 0; i < count; i++ )
    919           {
    920             FT_Bitmap_Size*  bsize = root->available_sizes + i;
    921 
    922 
    923             error = sfnt->load_strike_metrics( face, i, &metrics );
    924             if ( error )
    925               goto Exit;
    926 
    927             bsize->height = (FT_Short)( metrics.height >> 6 );
    928             bsize->width = (FT_Short)(
    929                 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
    930 
    931             bsize->x_ppem = metrics.x_ppem << 6;
    932             bsize->y_ppem = metrics.y_ppem << 6;
    933 
    934             /* assume 72dpi */
    935             bsize->size   = metrics.y_ppem << 6;
    936           }
    937 
    938           root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
    939           root->num_fixed_sizes = (FT_Int)count;
    940         }
    941       }
    942 
    943 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
    944 
    945       /* a font with no bitmaps and no outlines is scalable; */
    946       /* it has only empty glyphs then                       */
    947       if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) )
    948         root->face_flags |= FT_FACE_FLAG_SCALABLE;
    949 
    950 
    951       /*********************************************************************/
    952       /*                                                                   */
    953       /*  Set up metrics.                                                  */
    954       /*                                                                   */
    955       if ( FT_IS_SCALABLE( root ) )
    956       {
    957         /* XXX What about if outline header is missing */
    958         /*     (e.g. sfnt wrapped bitmap)?             */
    959         root->bbox.xMin    = face->header.xMin;
    960         root->bbox.yMin    = face->header.yMin;
    961         root->bbox.xMax    = face->header.xMax;
    962         root->bbox.yMax    = face->header.yMax;
    963         root->units_per_EM = face->header.Units_Per_EM;
    964 
    965 
    966         /* XXX: Computing the ascender/descender/height is very different */
    967         /*      from what the specification tells you.  Apparently, we    */
    968         /*      must be careful because                                   */
    969         /*                                                                */
    970         /*      - not all fonts have an OS/2 table; in this case, we take */
    971         /*        the values in the horizontal header.  However, these    */
    972         /*        values very often are not reliable.                     */
    973         /*                                                                */
    974         /*      - otherwise, the correct typographic values are in the    */
    975         /*        sTypoAscender, sTypoDescender & sTypoLineGap fields.    */
    976         /*                                                                */
    977         /*        However, certain fonts have these fields set to 0.      */
    978         /*        Rather, they have usWinAscent & usWinDescent correctly  */
    979         /*        set (but with different values).                        */
    980         /*                                                                */
    981         /*      As an example, Arial Narrow is implemented through four   */
    982         /*      files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
    983         /*                                                                */
    984         /*      Strangely, all fonts have the same values in their        */
    985         /*      sTypoXXX fields, except ARIALNB which sets them to 0.     */
    986         /*                                                                */
    987         /*      On the other hand, they all have different                */
    988         /*      usWinAscent/Descent values -- as a conclusion, the OS/2   */
    989         /*      table cannot be used to compute the text height reliably! */
    990         /*                                                                */
    991 
    992         /* The ascender/descender/height are computed from the OS/2 table */
    993         /* when found.  Otherwise, they're taken from the horizontal      */
    994         /* header.                                                        */
    995         /*                                                                */
    996 
    997         root->ascender  = face->horizontal.Ascender;
    998         root->descender = face->horizontal.Descender;
    999 
   1000         root->height    = (FT_Short)( root->ascender - root->descender +
   1001                                       face->horizontal.Line_Gap );
   1002 
   1003 #if 0
   1004         /* if the line_gap is 0, we add an extra 15% to the text height --  */
   1005         /* this computation is based on various versions of Times New Roman */
   1006         if ( face->horizontal.Line_Gap == 0 )
   1007           root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
   1008 #endif /* 0 */
   1009 
   1010 #if 0
   1011         /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
   1012         /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF             */
   1013         if ( face->os2.version != 0xFFFFU && root->ascender )
   1014         {
   1015           FT_Int  height;
   1016 
   1017 
   1018           root->ascender  =  face->os2.sTypoAscender;
   1019           root->descender = -face->os2.sTypoDescender;
   1020 
   1021           height = root->ascender + root->descender + face->os2.sTypoLineGap;
   1022           if ( height > root->height )
   1023             root->height = height;
   1024         }
   1025 #endif /* 0 */
   1026 
   1027         root->max_advance_width  = face->horizontal.advance_Width_Max;
   1028         root->max_advance_height = (FT_Short)( face->vertical_info
   1029                                      ? face->vertical.advance_Height_Max
   1030                                      : root->height );
   1031 
   1032         /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */
   1033         /* Adjust underline position from top edge to centre of     */
   1034         /* stroke to convert TrueType meaning to FreeType meaning.  */
   1035         root->underline_position  = face->postscript.underlinePosition -
   1036                                     face->postscript.underlineThickness / 2;
   1037         root->underline_thickness = face->postscript.underlineThickness;
   1038       }
   1039 
   1040     }
   1041 
   1042   Exit:
   1043     FT_TRACE2(( "sfnt_load_face: done\n" ));
   1044 
   1045     return error;
   1046   }
   1047 
   1048 
   1049 #undef LOAD_
   1050 #undef LOADM_
   1051 #undef GET_NAME
   1052 
   1053 
   1054   FT_LOCAL_DEF( void )
   1055   sfnt_done_face( TT_Face  face )
   1056   {
   1057     FT_Memory     memory;
   1058     SFNT_Service  sfnt;
   1059 
   1060 
   1061     if ( !face )
   1062       return;
   1063 
   1064     memory = face->root.memory;
   1065     sfnt   = (SFNT_Service)face->sfnt;
   1066 
   1067     if ( sfnt )
   1068     {
   1069       /* destroy the postscript names table if it is loaded */
   1070       if ( sfnt->free_psnames )
   1071         sfnt->free_psnames( face );
   1072 
   1073       /* destroy the embedded bitmaps table if it is loaded */
   1074       if ( sfnt->free_eblc )
   1075         sfnt->free_eblc( face );
   1076     }
   1077 
   1078 #ifdef TT_CONFIG_OPTION_BDF
   1079     /* freeing the embedded BDF properties */
   1080     tt_face_free_bdf_props( face );
   1081 #endif
   1082 
   1083     /* freeing the kerning table */
   1084     tt_face_done_kern( face );
   1085 
   1086     /* freeing the collection table */
   1087     FT_FREE( face->ttc_header.offsets );
   1088     face->ttc_header.count = 0;
   1089 
   1090     /* freeing table directory */
   1091     FT_FREE( face->dir_tables );
   1092     face->num_tables = 0;
   1093 
   1094     {
   1095       FT_Stream  stream = FT_FACE_STREAM( face );
   1096 
   1097 
   1098       /* simply release the 'cmap' table frame */
   1099       FT_FRAME_RELEASE( face->cmap_table );
   1100       face->cmap_size = 0;
   1101     }
   1102 
   1103     /* freeing the horizontal metrics */
   1104 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
   1105     {
   1106       FT_Stream  stream = FT_FACE_STREAM( face );
   1107 
   1108 
   1109       FT_FRAME_RELEASE( face->horz_metrics );
   1110       FT_FRAME_RELEASE( face->vert_metrics );
   1111       face->horz_metrics_size = 0;
   1112       face->vert_metrics_size = 0;
   1113     }
   1114 #else
   1115     FT_FREE( face->horizontal.long_metrics );
   1116     FT_FREE( face->horizontal.short_metrics );
   1117 #endif
   1118 
   1119     /* freeing the vertical ones, if any */
   1120     if ( face->vertical_info )
   1121     {
   1122       FT_FREE( face->vertical.long_metrics  );
   1123       FT_FREE( face->vertical.short_metrics );
   1124       face->vertical_info = 0;
   1125     }
   1126 
   1127     /* freeing the gasp table */
   1128     FT_FREE( face->gasp.gaspRanges );
   1129     face->gasp.numRanges = 0;
   1130 
   1131     /* freeing the name table */
   1132     if ( sfnt )
   1133       sfnt->free_name( face );
   1134 
   1135     /* freeing family and style name */
   1136     FT_FREE( face->root.family_name );
   1137     FT_FREE( face->root.style_name );
   1138 
   1139     /* freeing sbit size table */
   1140     FT_FREE( face->root.available_sizes );
   1141     face->root.num_fixed_sizes = 0;
   1142 
   1143     FT_FREE( face->postscript_name );
   1144 
   1145     face->sfnt = 0;
   1146   }
   1147 
   1148 
   1149 /* END */
   1150