Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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