misc/libfreetype/src/sfnt/ttload.c
changeset 5172 88f2e05288ba
equal deleted inserted replaced
5171:f9283dc4860d 5172:88f2e05288ba
       
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  ttload.c                                                               */
       
     4 /*                                                                         */
       
     5 /*    Load the basic TrueType tables, i.e., tables that can be either in   */
       
     6 /*    TTF or OTF fonts (body).                                             */
       
     7 /*                                                                         */
       
     8 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
       
     9 /*            2010 by                                                      */
       
    10 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
       
    11 /*                                                                         */
       
    12 /*  This file is part of the FreeType project, and may only be used,       */
       
    13 /*  modified, and distributed under the terms of the FreeType project      */
       
    14 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
       
    15 /*  this file you indicate that you have read the license and              */
       
    16 /*  understand and accept it fully.                                        */
       
    17 /*                                                                         */
       
    18 /***************************************************************************/
       
    19 
       
    20 
       
    21 #include <ft2build.h>
       
    22 #include FT_INTERNAL_DEBUG_H
       
    23 #include FT_INTERNAL_STREAM_H
       
    24 #include FT_TRUETYPE_TAGS_H
       
    25 #include "ttload.h"
       
    26 
       
    27 #include "sferrors.h"
       
    28 
       
    29 
       
    30   /*************************************************************************/
       
    31   /*                                                                       */
       
    32   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
       
    33   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
       
    34   /* messages during execution.                                            */
       
    35   /*                                                                       */
       
    36 #undef  FT_COMPONENT
       
    37 #define FT_COMPONENT  trace_ttload
       
    38 
       
    39 
       
    40   /*************************************************************************/
       
    41   /*                                                                       */
       
    42   /* <Function>                                                            */
       
    43   /*    tt_face_lookup_table                                               */
       
    44   /*                                                                       */
       
    45   /* <Description>                                                         */
       
    46   /*    Looks for a TrueType table by name.                                */
       
    47   /*                                                                       */
       
    48   /* <Input>                                                               */
       
    49   /*    face :: A face object handle.                                      */
       
    50   /*                                                                       */
       
    51   /*    tag  :: The searched tag.                                          */
       
    52   /*                                                                       */
       
    53   /* <Return>                                                              */
       
    54   /*    A pointer to the table directory entry.  0 if not found.           */
       
    55   /*                                                                       */
       
    56   FT_LOCAL_DEF( TT_Table  )
       
    57   tt_face_lookup_table( TT_Face   face,
       
    58                         FT_ULong  tag  )
       
    59   {
       
    60     TT_Table  entry;
       
    61     TT_Table  limit;
       
    62 #ifdef FT_DEBUG_LEVEL_TRACE
       
    63     FT_Bool   zero_length = FALSE;
       
    64 #endif
       
    65 
       
    66 
       
    67     FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ",
       
    68                 face,
       
    69                 (FT_Char)( tag >> 24 ),
       
    70                 (FT_Char)( tag >> 16 ),
       
    71                 (FT_Char)( tag >> 8  ),
       
    72                 (FT_Char)( tag       ) ));
       
    73 
       
    74     entry = face->dir_tables;
       
    75     limit = entry + face->num_tables;
       
    76 
       
    77     for ( ; entry < limit; entry++ )
       
    78     {
       
    79       /* For compatibility with Windows, we consider    */
       
    80       /* zero-length tables the same as missing tables. */
       
    81       if ( entry->Tag == tag )
       
    82       {
       
    83         if ( entry->Length != 0 )
       
    84         {
       
    85           FT_TRACE4(( "found table.\n" ));
       
    86           return entry;
       
    87         }
       
    88 #ifdef FT_DEBUG_LEVEL_TRACE
       
    89         zero_length = TRUE;
       
    90 #endif
       
    91       }
       
    92     }
       
    93 
       
    94 #ifdef FT_DEBUG_LEVEL_TRACE
       
    95     if ( zero_length )
       
    96       FT_TRACE4(( "ignoring empty table\n" ));
       
    97     else
       
    98       FT_TRACE4(( "could not find table\n" ));
       
    99 #endif
       
   100 
       
   101     return NULL;
       
   102   }
       
   103 
       
   104 
       
   105   /*************************************************************************/
       
   106   /*                                                                       */
       
   107   /* <Function>                                                            */
       
   108   /*    tt_face_goto_table                                                 */
       
   109   /*                                                                       */
       
   110   /* <Description>                                                         */
       
   111   /*    Looks for a TrueType table by name, then seek a stream to it.      */
       
   112   /*                                                                       */
       
   113   /* <Input>                                                               */
       
   114   /*    face   :: A face object handle.                                    */
       
   115   /*                                                                       */
       
   116   /*    tag    :: The searched tag.                                        */
       
   117   /*                                                                       */
       
   118   /*    stream :: The stream to seek when the table is found.              */
       
   119   /*                                                                       */
       
   120   /* <Output>                                                              */
       
   121   /*    length :: The length of the table if found, undefined otherwise.   */
       
   122   /*                                                                       */
       
   123   /* <Return>                                                              */
       
   124   /*    FreeType error code.  0 means success.                             */
       
   125   /*                                                                       */
       
   126   FT_LOCAL_DEF( FT_Error )
       
   127   tt_face_goto_table( TT_Face    face,
       
   128                       FT_ULong   tag,
       
   129                       FT_Stream  stream,
       
   130                       FT_ULong*  length )
       
   131   {
       
   132     TT_Table  table;
       
   133     FT_Error  error;
       
   134 
       
   135 
       
   136     table = tt_face_lookup_table( face, tag );
       
   137     if ( table )
       
   138     {
       
   139       if ( length )
       
   140         *length = table->Length;
       
   141 
       
   142       if ( FT_STREAM_SEEK( table->Offset ) )
       
   143         goto Exit;
       
   144     }
       
   145     else
       
   146       error = SFNT_Err_Table_Missing;
       
   147 
       
   148   Exit:
       
   149     return error;
       
   150   }
       
   151 
       
   152 
       
   153   /* Here, we                                                         */
       
   154   /*                                                                  */
       
   155   /* - check that `num_tables' is valid (and adjust it if necessary)  */
       
   156   /*                                                                  */
       
   157   /* - look for a `head' table, check its size, and parse it to check */
       
   158   /*   whether its `magic' field is correctly set                     */
       
   159   /*                                                                  */
       
   160   /* - errors (except errors returned by stream handling)             */
       
   161   /*                                                                  */
       
   162   /*     SFNT_Err_Unknown_File_Format:                                */
       
   163   /*       no table is defined in directory, it is not sfnt-wrapped   */
       
   164   /*       data                                                       */
       
   165   /*     SFNT_Err_Table_Missing:                                      */
       
   166   /*       table directory is valid, but essential tables             */
       
   167   /*       (head/bhed/SING) are missing                               */
       
   168   /*                                                                  */
       
   169   static FT_Error
       
   170   check_table_dir( SFNT_Header  sfnt,
       
   171                    FT_Stream    stream )
       
   172   {
       
   173     FT_Error   error;
       
   174     FT_UShort  nn, valid_entries = 0;
       
   175     FT_UInt    has_head = 0, has_sing = 0, has_meta = 0;
       
   176     FT_ULong   offset = sfnt->offset + 12;
       
   177 
       
   178     static const FT_Frame_Field  table_dir_entry_fields[] =
       
   179     {
       
   180 #undef  FT_STRUCTURE
       
   181 #define FT_STRUCTURE  TT_TableRec
       
   182 
       
   183       FT_FRAME_START( 16 ),
       
   184         FT_FRAME_ULONG( Tag ),
       
   185         FT_FRAME_ULONG( CheckSum ),
       
   186         FT_FRAME_ULONG( Offset ),
       
   187         FT_FRAME_ULONG( Length ),
       
   188       FT_FRAME_END
       
   189     };
       
   190 
       
   191 
       
   192     if ( FT_STREAM_SEEK( offset ) )
       
   193       goto Exit;
       
   194 
       
   195     for ( nn = 0; nn < sfnt->num_tables; nn++ )
       
   196     {
       
   197       TT_TableRec  table;
       
   198 
       
   199 
       
   200       if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) )
       
   201       {
       
   202         nn--;
       
   203         FT_TRACE2(( "check_table_dir:"
       
   204                     " can read only %d table%s in font (instead of %d)\n",
       
   205                     nn, nn == 1 ? "" : "s", sfnt->num_tables ));
       
   206         sfnt->num_tables = nn;
       
   207         break;
       
   208       }
       
   209 
       
   210       /* we ignore invalid tables */
       
   211       if ( table.Offset + table.Length > stream->size )
       
   212       {
       
   213         FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
       
   214         continue;
       
   215       }
       
   216       else
       
   217         valid_entries++;
       
   218 
       
   219       if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed )
       
   220       {
       
   221         FT_UInt32  magic;
       
   222 
       
   223 
       
   224 #ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
       
   225         if ( table.Tag == TTAG_head )
       
   226 #endif
       
   227           has_head = 1;
       
   228 
       
   229         /*
       
   230          * The table length should be 0x36, but certain font tools make it
       
   231          * 0x38, so we will just check that it is greater.
       
   232          *
       
   233          * Note that according to the specification, the table must be
       
   234          * padded to 32-bit lengths, but this doesn't apply to the value of
       
   235          * its `Length' field!
       
   236          *
       
   237          */
       
   238         if ( table.Length < 0x36 )
       
   239         {
       
   240           FT_TRACE2(( "check_table_dir: `head' table too small\n" ));
       
   241           error = SFNT_Err_Table_Missing;
       
   242           goto Exit;
       
   243         }
       
   244 
       
   245         if ( FT_STREAM_SEEK( table.Offset + 12 ) ||
       
   246              FT_READ_ULONG( magic )              )
       
   247           goto Exit;
       
   248 
       
   249         if ( magic != 0x5F0F3CF5UL )
       
   250         {
       
   251           FT_TRACE2(( "check_table_dir:"
       
   252                       " no magic number found in `head' table\n"));
       
   253           error = SFNT_Err_Table_Missing;
       
   254           goto Exit;
       
   255         }
       
   256 
       
   257         if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )
       
   258           goto Exit;
       
   259       }
       
   260       else if ( table.Tag == TTAG_SING )
       
   261         has_sing = 1;
       
   262       else if ( table.Tag == TTAG_META )
       
   263         has_meta = 1;
       
   264     }
       
   265 
       
   266     sfnt->num_tables = valid_entries;
       
   267 
       
   268     if ( sfnt->num_tables == 0 )
       
   269     {
       
   270       FT_TRACE2(( "check_table_dir: no tables found\n" ));
       
   271       error = SFNT_Err_Unknown_File_Format;
       
   272       goto Exit;
       
   273     }
       
   274 
       
   275     /* if `sing' and `meta' tables are present, there is no `head' table */
       
   276     if ( has_head || ( has_sing && has_meta ) )
       
   277     {
       
   278       error = SFNT_Err_Ok;
       
   279       goto Exit;
       
   280     }
       
   281     else
       
   282     {
       
   283       FT_TRACE2(( "check_table_dir:" ));
       
   284 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
       
   285       FT_TRACE2(( " neither `head', `bhed', nor `sing' table found\n" ));
       
   286 #else
       
   287       FT_TRACE2(( " neither `head' nor `sing' table found\n" ));
       
   288 #endif
       
   289       error = SFNT_Err_Table_Missing;
       
   290     }
       
   291 
       
   292   Exit:
       
   293     return error;
       
   294   }
       
   295 
       
   296 
       
   297   /*************************************************************************/
       
   298   /*                                                                       */
       
   299   /* <Function>                                                            */
       
   300   /*    tt_face_load_font_dir                                              */
       
   301   /*                                                                       */
       
   302   /* <Description>                                                         */
       
   303   /*    Loads the header of a SFNT font file.                              */
       
   304   /*                                                                       */
       
   305   /* <Input>                                                               */
       
   306   /*    face       :: A handle to the target face object.                  */
       
   307   /*                                                                       */
       
   308   /*    stream     :: The input stream.                                    */
       
   309   /*                                                                       */
       
   310   /* <Output>                                                              */
       
   311   /*    sfnt       :: The SFNT header.                                     */
       
   312   /*                                                                       */
       
   313   /* <Return>                                                              */
       
   314   /*    FreeType error code.  0 means success.                             */
       
   315   /*                                                                       */
       
   316   /* <Note>                                                                */
       
   317   /*    The stream cursor must be at the beginning of the font directory.  */
       
   318   /*                                                                       */
       
   319   FT_LOCAL_DEF( FT_Error )
       
   320   tt_face_load_font_dir( TT_Face    face,
       
   321                          FT_Stream  stream )
       
   322   {
       
   323     SFNT_HeaderRec  sfnt;
       
   324     FT_Error        error;
       
   325     FT_Memory       memory = stream->memory;
       
   326     TT_TableRec*    entry;
       
   327     FT_Int          nn;
       
   328 
       
   329     static const FT_Frame_Field  offset_table_fields[] =
       
   330     {
       
   331 #undef  FT_STRUCTURE
       
   332 #define FT_STRUCTURE  SFNT_HeaderRec
       
   333 
       
   334       FT_FRAME_START( 8 ),
       
   335         FT_FRAME_USHORT( num_tables ),
       
   336         FT_FRAME_USHORT( search_range ),
       
   337         FT_FRAME_USHORT( entry_selector ),
       
   338         FT_FRAME_USHORT( range_shift ),
       
   339       FT_FRAME_END
       
   340     };
       
   341 
       
   342 
       
   343     FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face ));
       
   344 
       
   345     /* read the offset table */
       
   346 
       
   347     sfnt.offset = FT_STREAM_POS();
       
   348 
       
   349     if ( FT_READ_ULONG( sfnt.format_tag )                    ||
       
   350          FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) )
       
   351       goto Exit;
       
   352 
       
   353     /* many fonts don't have these fields set correctly */
       
   354 #if 0
       
   355     if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 )        ||
       
   356          sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 )
       
   357       return SFNT_Err_Unknown_File_Format;
       
   358 #endif
       
   359 
       
   360     /* load the table directory */
       
   361 
       
   362     FT_TRACE2(( "-- Number of tables: %10u\n",    sfnt.num_tables ));
       
   363     FT_TRACE2(( "-- Format version:   0x%08lx\n", sfnt.format_tag ));
       
   364 
       
   365     /* check first */
       
   366     error = check_table_dir( &sfnt, stream );
       
   367     if ( error )
       
   368     {
       
   369       FT_TRACE2(( "tt_face_load_font_dir:"
       
   370                   " invalid table directory for TrueType\n" ));
       
   371 
       
   372       goto Exit;
       
   373     }
       
   374 
       
   375     face->num_tables = sfnt.num_tables;
       
   376     face->format_tag = sfnt.format_tag;
       
   377 
       
   378     if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) )
       
   379       goto Exit;
       
   380 
       
   381     if ( FT_STREAM_SEEK( sfnt.offset + 12 )       ||
       
   382          FT_FRAME_ENTER( face->num_tables * 16L ) )
       
   383       goto Exit;
       
   384 
       
   385     entry = face->dir_tables;
       
   386 
       
   387     FT_TRACE2(( "\n"
       
   388                 "  tag    offset    length   checksum\n"
       
   389                 "  ----------------------------------\n" ));
       
   390 
       
   391     for ( nn = 0; nn < sfnt.num_tables; nn++ )
       
   392     {
       
   393       entry->Tag      = FT_GET_TAG4();
       
   394       entry->CheckSum = FT_GET_ULONG();
       
   395       entry->Offset   = FT_GET_LONG();
       
   396       entry->Length   = FT_GET_LONG();
       
   397 
       
   398       /* ignore invalid tables */
       
   399       if ( entry->Offset + entry->Length > stream->size )
       
   400         continue;
       
   401       else
       
   402       {
       
   403         FT_TRACE2(( "  %c%c%c%c  %08lx  %08lx  %08lx\n",
       
   404                     (FT_Char)( entry->Tag >> 24 ),
       
   405                     (FT_Char)( entry->Tag >> 16 ),
       
   406                     (FT_Char)( entry->Tag >> 8  ),
       
   407                     (FT_Char)( entry->Tag       ),
       
   408                     entry->Offset,
       
   409                     entry->Length,
       
   410                     entry->CheckSum ));
       
   411         entry++;
       
   412       }
       
   413     }
       
   414 
       
   415     FT_FRAME_EXIT();
       
   416 
       
   417     FT_TRACE2(( "table directory loaded\n\n" ));
       
   418 
       
   419   Exit:
       
   420     return error;
       
   421   }
       
   422 
       
   423 
       
   424   /*************************************************************************/
       
   425   /*                                                                       */
       
   426   /* <Function>                                                            */
       
   427   /*    tt_face_load_any                                                   */
       
   428   /*                                                                       */
       
   429   /* <Description>                                                         */
       
   430   /*    Loads any font table into client memory.                           */
       
   431   /*                                                                       */
       
   432   /* <Input>                                                               */
       
   433   /*    face   :: The face object to look for.                             */
       
   434   /*                                                                       */
       
   435   /*    tag    :: The tag of table to load.  Use the value 0 if you want   */
       
   436   /*              to access the whole font file, else set this parameter   */
       
   437   /*              to a valid TrueType table tag that you can forge with    */
       
   438   /*              the MAKE_TT_TAG macro.                                   */
       
   439   /*                                                                       */
       
   440   /*    offset :: The starting offset in the table (or the file if         */
       
   441   /*              tag == 0).                                               */
       
   442   /*                                                                       */
       
   443   /*    length :: The address of the decision variable:                    */
       
   444   /*                                                                       */
       
   445   /*                If length == NULL:                                     */
       
   446   /*                  Loads the whole table.  Returns an error if          */
       
   447   /*                  `offset' == 0!                                       */
       
   448   /*                                                                       */
       
   449   /*                If *length == 0:                                       */
       
   450   /*                  Exits immediately; returning the length of the given */
       
   451   /*                  table or of the font file, depending on the value of */
       
   452   /*                  `tag'.                                               */
       
   453   /*                                                                       */
       
   454   /*                If *length != 0:                                       */
       
   455   /*                  Loads the next `length' bytes of table or font,      */
       
   456   /*                  starting at offset `offset' (in table or font too).  */
       
   457   /*                                                                       */
       
   458   /* <Output>                                                              */
       
   459   /*    buffer :: The address of target buffer.                            */
       
   460   /*                                                                       */
       
   461   /* <Return>                                                              */
       
   462   /*    FreeType error code.  0 means success.                             */
       
   463   /*                                                                       */
       
   464   FT_LOCAL_DEF( FT_Error )
       
   465   tt_face_load_any( TT_Face    face,
       
   466                     FT_ULong   tag,
       
   467                     FT_Long    offset,
       
   468                     FT_Byte*   buffer,
       
   469                     FT_ULong*  length )
       
   470   {
       
   471     FT_Error   error;
       
   472     FT_Stream  stream;
       
   473     TT_Table   table;
       
   474     FT_ULong   size;
       
   475 
       
   476 
       
   477     if ( tag != 0 )
       
   478     {
       
   479       /* look for tag in font directory */
       
   480       table = tt_face_lookup_table( face, tag );
       
   481       if ( !table )
       
   482       {
       
   483         error = SFNT_Err_Table_Missing;
       
   484         goto Exit;
       
   485       }
       
   486 
       
   487       offset += table->Offset;
       
   488       size    = table->Length;
       
   489     }
       
   490     else
       
   491       /* tag == 0 -- the user wants to access the font file directly */
       
   492       size = face->root.stream->size;
       
   493 
       
   494     if ( length && *length == 0 )
       
   495     {
       
   496       *length = size;
       
   497 
       
   498       return SFNT_Err_Ok;
       
   499     }
       
   500 
       
   501     if ( length )
       
   502       size = *length;
       
   503 
       
   504     stream = face->root.stream;
       
   505     /* the `if' is syntactic sugar for picky compilers */
       
   506     if ( FT_STREAM_READ_AT( offset, buffer, size ) )
       
   507       goto Exit;
       
   508 
       
   509   Exit:
       
   510     return error;
       
   511   }
       
   512 
       
   513 
       
   514   /*************************************************************************/
       
   515   /*                                                                       */
       
   516   /* <Function>                                                            */
       
   517   /*    tt_face_load_generic_header                                        */
       
   518   /*                                                                       */
       
   519   /* <Description>                                                         */
       
   520   /*    Loads the TrueType table `head' or `bhed'.                         */
       
   521   /*                                                                       */
       
   522   /* <Input>                                                               */
       
   523   /*    face   :: A handle to the target face object.                      */
       
   524   /*                                                                       */
       
   525   /*    stream :: The input stream.                                        */
       
   526   /*                                                                       */
       
   527   /* <Return>                                                              */
       
   528   /*    FreeType error code.  0 means success.                             */
       
   529   /*                                                                       */
       
   530   static FT_Error
       
   531   tt_face_load_generic_header( TT_Face    face,
       
   532                                FT_Stream  stream,
       
   533                                FT_ULong   tag )
       
   534   {
       
   535     FT_Error    error;
       
   536     TT_Header*  header;
       
   537 
       
   538     static const FT_Frame_Field  header_fields[] =
       
   539     {
       
   540 #undef  FT_STRUCTURE
       
   541 #define FT_STRUCTURE  TT_Header
       
   542 
       
   543       FT_FRAME_START( 54 ),
       
   544         FT_FRAME_ULONG ( Table_Version ),
       
   545         FT_FRAME_ULONG ( Font_Revision ),
       
   546         FT_FRAME_LONG  ( CheckSum_Adjust ),
       
   547         FT_FRAME_LONG  ( Magic_Number ),
       
   548         FT_FRAME_USHORT( Flags ),
       
   549         FT_FRAME_USHORT( Units_Per_EM ),
       
   550         FT_FRAME_LONG  ( Created[0] ),
       
   551         FT_FRAME_LONG  ( Created[1] ),
       
   552         FT_FRAME_LONG  ( Modified[0] ),
       
   553         FT_FRAME_LONG  ( Modified[1] ),
       
   554         FT_FRAME_SHORT ( xMin ),
       
   555         FT_FRAME_SHORT ( yMin ),
       
   556         FT_FRAME_SHORT ( xMax ),
       
   557         FT_FRAME_SHORT ( yMax ),
       
   558         FT_FRAME_USHORT( Mac_Style ),
       
   559         FT_FRAME_USHORT( Lowest_Rec_PPEM ),
       
   560         FT_FRAME_SHORT ( Font_Direction ),
       
   561         FT_FRAME_SHORT ( Index_To_Loc_Format ),
       
   562         FT_FRAME_SHORT ( Glyph_Data_Format ),
       
   563       FT_FRAME_END
       
   564     };
       
   565 
       
   566 
       
   567     error = face->goto_table( face, tag, stream, 0 );
       
   568     if ( error )
       
   569       goto Exit;
       
   570 
       
   571     header = &face->header;
       
   572 
       
   573     if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
       
   574       goto Exit;
       
   575 
       
   576     FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM ));
       
   577     FT_TRACE3(( "IndexToLoc:   %4d\n", header->Index_To_Loc_Format ));
       
   578 
       
   579   Exit:
       
   580     return error;
       
   581   }
       
   582 
       
   583 
       
   584   FT_LOCAL_DEF( FT_Error )
       
   585   tt_face_load_head( TT_Face    face,
       
   586                      FT_Stream  stream )
       
   587   {
       
   588     return tt_face_load_generic_header( face, stream, TTAG_head );
       
   589   }
       
   590 
       
   591 
       
   592 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
       
   593 
       
   594   FT_LOCAL_DEF( FT_Error )
       
   595   tt_face_load_bhed( TT_Face    face,
       
   596                      FT_Stream  stream )
       
   597   {
       
   598     return tt_face_load_generic_header( face, stream, TTAG_bhed );
       
   599   }
       
   600 
       
   601 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
       
   602 
       
   603 
       
   604   /*************************************************************************/
       
   605   /*                                                                       */
       
   606   /* <Function>                                                            */
       
   607   /*    tt_face_load_max_profile                                           */
       
   608   /*                                                                       */
       
   609   /* <Description>                                                         */
       
   610   /*    Loads the maximum profile into a face object.                      */
       
   611   /*                                                                       */
       
   612   /* <Input>                                                               */
       
   613   /*    face   :: A handle to the target face object.                      */
       
   614   /*                                                                       */
       
   615   /*    stream :: The input stream.                                        */
       
   616   /*                                                                       */
       
   617   /* <Return>                                                              */
       
   618   /*    FreeType error code.  0 means success.                             */
       
   619   /*                                                                       */
       
   620   FT_LOCAL_DEF( FT_Error )
       
   621   tt_face_load_maxp( TT_Face    face,
       
   622                      FT_Stream  stream )
       
   623   {
       
   624     FT_Error        error;
       
   625     TT_MaxProfile*  maxProfile = &face->max_profile;
       
   626 
       
   627     const FT_Frame_Field  maxp_fields[] =
       
   628     {
       
   629 #undef  FT_STRUCTURE
       
   630 #define FT_STRUCTURE  TT_MaxProfile
       
   631 
       
   632       FT_FRAME_START( 6 ),
       
   633         FT_FRAME_LONG  ( version ),
       
   634         FT_FRAME_USHORT( numGlyphs ),
       
   635       FT_FRAME_END
       
   636     };
       
   637 
       
   638     const FT_Frame_Field  maxp_fields_extra[] =
       
   639     {
       
   640       FT_FRAME_START( 26 ),
       
   641         FT_FRAME_USHORT( maxPoints ),
       
   642         FT_FRAME_USHORT( maxContours ),
       
   643         FT_FRAME_USHORT( maxCompositePoints ),
       
   644         FT_FRAME_USHORT( maxCompositeContours ),
       
   645         FT_FRAME_USHORT( maxZones ),
       
   646         FT_FRAME_USHORT( maxTwilightPoints ),
       
   647         FT_FRAME_USHORT( maxStorage ),
       
   648         FT_FRAME_USHORT( maxFunctionDefs ),
       
   649         FT_FRAME_USHORT( maxInstructionDefs ),
       
   650         FT_FRAME_USHORT( maxStackElements ),
       
   651         FT_FRAME_USHORT( maxSizeOfInstructions ),
       
   652         FT_FRAME_USHORT( maxComponentElements ),
       
   653         FT_FRAME_USHORT( maxComponentDepth ),
       
   654       FT_FRAME_END
       
   655     };
       
   656 
       
   657 
       
   658     error = face->goto_table( face, TTAG_maxp, stream, 0 );
       
   659     if ( error )
       
   660       goto Exit;
       
   661 
       
   662     if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
       
   663       goto Exit;
       
   664 
       
   665     maxProfile->maxPoints             = 0;
       
   666     maxProfile->maxContours           = 0;
       
   667     maxProfile->maxCompositePoints    = 0;
       
   668     maxProfile->maxCompositeContours  = 0;
       
   669     maxProfile->maxZones              = 0;
       
   670     maxProfile->maxTwilightPoints     = 0;
       
   671     maxProfile->maxStorage            = 0;
       
   672     maxProfile->maxFunctionDefs       = 0;
       
   673     maxProfile->maxInstructionDefs    = 0;
       
   674     maxProfile->maxStackElements      = 0;
       
   675     maxProfile->maxSizeOfInstructions = 0;
       
   676     maxProfile->maxComponentElements  = 0;
       
   677     maxProfile->maxComponentDepth     = 0;
       
   678 
       
   679     if ( maxProfile->version >= 0x10000L )
       
   680     {
       
   681       if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
       
   682         goto Exit;
       
   683 
       
   684       /* XXX: an adjustment that is necessary to load certain */
       
   685       /*      broken fonts like `Keystrokes MT' :-(           */
       
   686       /*                                                      */
       
   687       /*   We allocate 64 function entries by default when    */
       
   688       /*   the maxFunctionDefs value is smaller.              */
       
   689 
       
   690       if ( maxProfile->maxFunctionDefs < 64 )
       
   691         maxProfile->maxFunctionDefs = 64;
       
   692 
       
   693       /* we add 4 phantom points later */
       
   694       if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) )
       
   695       {
       
   696         FT_TRACE0(( "tt_face_load_maxp:"
       
   697                     " too much twilight points in `maxp' table;\n"
       
   698                     "                  "
       
   699                     " some glyphs might be rendered incorrectly\n" ));
       
   700 
       
   701         maxProfile->maxTwilightPoints = 0xFFFFU - 4;
       
   702       }
       
   703 
       
   704       /* we arbitrarily limit recursion to avoid stack exhaustion */
       
   705       if ( maxProfile->maxComponentDepth > 100 )
       
   706       {
       
   707         FT_TRACE0(( "tt_face_load_maxp:"
       
   708                     " abnormally large component depth (%d) set to 100\n",
       
   709                     maxProfile->maxComponentDepth ));
       
   710         maxProfile->maxComponentDepth = 100;
       
   711       }
       
   712     }
       
   713 
       
   714     FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs ));
       
   715 
       
   716   Exit:
       
   717     return error;
       
   718   }
       
   719 
       
   720 
       
   721   /*************************************************************************/
       
   722   /*                                                                       */
       
   723   /* <Function>                                                            */
       
   724   /*    tt_face_load_names                                                 */
       
   725   /*                                                                       */
       
   726   /* <Description>                                                         */
       
   727   /*    Loads the name records.                                            */
       
   728   /*                                                                       */
       
   729   /* <Input>                                                               */
       
   730   /*    face   :: A handle to the target face object.                      */
       
   731   /*                                                                       */
       
   732   /*    stream :: The input stream.                                        */
       
   733   /*                                                                       */
       
   734   /* <Return>                                                              */
       
   735   /*    FreeType error code.  0 means success.                             */
       
   736   /*                                                                       */
       
   737   FT_LOCAL_DEF( FT_Error )
       
   738   tt_face_load_name( TT_Face    face,
       
   739                      FT_Stream  stream )
       
   740   {
       
   741     FT_Error      error;
       
   742     FT_Memory     memory = stream->memory;
       
   743     FT_ULong      table_pos, table_len;
       
   744     FT_ULong      storage_start, storage_limit;
       
   745     FT_UInt       count;
       
   746     TT_NameTable  table;
       
   747 
       
   748     static const FT_Frame_Field  name_table_fields[] =
       
   749     {
       
   750 #undef  FT_STRUCTURE
       
   751 #define FT_STRUCTURE  TT_NameTableRec
       
   752 
       
   753       FT_FRAME_START( 6 ),
       
   754         FT_FRAME_USHORT( format ),
       
   755         FT_FRAME_USHORT( numNameRecords ),
       
   756         FT_FRAME_USHORT( storageOffset ),
       
   757       FT_FRAME_END
       
   758     };
       
   759 
       
   760     static const FT_Frame_Field  name_record_fields[] =
       
   761     {
       
   762 #undef  FT_STRUCTURE
       
   763 #define FT_STRUCTURE  TT_NameEntryRec
       
   764 
       
   765       /* no FT_FRAME_START */
       
   766         FT_FRAME_USHORT( platformID ),
       
   767         FT_FRAME_USHORT( encodingID ),
       
   768         FT_FRAME_USHORT( languageID ),
       
   769         FT_FRAME_USHORT( nameID ),
       
   770         FT_FRAME_USHORT( stringLength ),
       
   771         FT_FRAME_USHORT( stringOffset ),
       
   772       FT_FRAME_END
       
   773     };
       
   774 
       
   775 
       
   776     table         = &face->name_table;
       
   777     table->stream = stream;
       
   778 
       
   779     error = face->goto_table( face, TTAG_name, stream, &table_len );
       
   780     if ( error )
       
   781       goto Exit;
       
   782 
       
   783     table_pos = FT_STREAM_POS();
       
   784 
       
   785 
       
   786     if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
       
   787       goto Exit;
       
   788 
       
   789     /* Some popular Asian fonts have an invalid `storageOffset' value   */
       
   790     /* (it should be at least "6 + 12*num_names").  However, the string */
       
   791     /* offsets, computed as "storageOffset + entry->stringOffset", are  */
       
   792     /* valid pointers within the name table...                          */
       
   793     /*                                                                  */
       
   794     /* We thus can't check `storageOffset' right now.                   */
       
   795     /*                                                                  */
       
   796     storage_start = table_pos + 6 + 12*table->numNameRecords;
       
   797     storage_limit = table_pos + table_len;
       
   798 
       
   799     if ( storage_start > storage_limit )
       
   800     {
       
   801       FT_ERROR(( "tt_face_load_name: invalid `name' table\n" ));
       
   802       error = SFNT_Err_Name_Table_Missing;
       
   803       goto Exit;
       
   804     }
       
   805 
       
   806     /* Allocate the array of name records. */
       
   807     count                 = table->numNameRecords;
       
   808     table->numNameRecords = 0;
       
   809 
       
   810     if ( FT_NEW_ARRAY( table->names, count ) ||
       
   811          FT_FRAME_ENTER( count * 12 )        )
       
   812       goto Exit;
       
   813 
       
   814     /* Load the name records and determine how much storage is needed */
       
   815     /* to hold the strings themselves.                                */
       
   816     {
       
   817       TT_NameEntryRec*  entry = table->names;
       
   818 
       
   819 
       
   820       for ( ; count > 0; count-- )
       
   821       {
       
   822         if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
       
   823           continue;
       
   824 
       
   825         /* check that the name is not empty */
       
   826         if ( entry->stringLength == 0 )
       
   827           continue;
       
   828 
       
   829         /* check that the name string is within the table */
       
   830         entry->stringOffset += table_pos + table->storageOffset;
       
   831         if ( entry->stringOffset                       < storage_start ||
       
   832              entry->stringOffset + entry->stringLength > storage_limit )
       
   833         {
       
   834           /* invalid entry - ignore it */
       
   835           entry->stringOffset = 0;
       
   836           entry->stringLength = 0;
       
   837           continue;
       
   838         }
       
   839 
       
   840         entry++;
       
   841       }
       
   842 
       
   843       table->numNameRecords = (FT_UInt)( entry - table->names );
       
   844     }
       
   845 
       
   846     FT_FRAME_EXIT();
       
   847 
       
   848     /* everything went well, update face->num_names */
       
   849     face->num_names = (FT_UShort) table->numNameRecords;
       
   850 
       
   851   Exit:
       
   852     return error;
       
   853   }
       
   854 
       
   855 
       
   856   /*************************************************************************/
       
   857   /*                                                                       */
       
   858   /* <Function>                                                            */
       
   859   /*    tt_face_free_names                                                 */
       
   860   /*                                                                       */
       
   861   /* <Description>                                                         */
       
   862   /*    Frees the name records.                                            */
       
   863   /*                                                                       */
       
   864   /* <Input>                                                               */
       
   865   /*    face :: A handle to the target face object.                        */
       
   866   /*                                                                       */
       
   867   FT_LOCAL_DEF( void )
       
   868   tt_face_free_name( TT_Face  face )
       
   869   {
       
   870     FT_Memory     memory = face->root.driver->root.memory;
       
   871     TT_NameTable  table  = &face->name_table;
       
   872     TT_NameEntry  entry  = table->names;
       
   873     FT_UInt       count  = table->numNameRecords;
       
   874 
       
   875 
       
   876     if ( table->names )
       
   877     {
       
   878       for ( ; count > 0; count--, entry++ )
       
   879       {
       
   880         FT_FREE( entry->string );
       
   881         entry->stringLength = 0;
       
   882       }
       
   883 
       
   884       /* free strings table */
       
   885       FT_FREE( table->names );
       
   886     }
       
   887 
       
   888     table->numNameRecords = 0;
       
   889     table->format         = 0;
       
   890     table->storageOffset  = 0;
       
   891   }
       
   892 
       
   893 
       
   894   /*************************************************************************/
       
   895   /*                                                                       */
       
   896   /* <Function>                                                            */
       
   897   /*    tt_face_load_cmap                                                  */
       
   898   /*                                                                       */
       
   899   /* <Description>                                                         */
       
   900   /*    Loads the cmap directory in a face object.  The cmaps themselves   */
       
   901   /*    are loaded on demand in the `ttcmap.c' module.                     */
       
   902   /*                                                                       */
       
   903   /* <Input>                                                               */
       
   904   /*    face   :: A handle to the target face object.                      */
       
   905   /*                                                                       */
       
   906   /*    stream :: A handle to the input stream.                            */
       
   907   /*                                                                       */
       
   908   /* <Return>                                                              */
       
   909   /*    FreeType error code.  0 means success.                             */
       
   910   /*                                                                       */
       
   911 
       
   912   FT_LOCAL_DEF( FT_Error )
       
   913   tt_face_load_cmap( TT_Face    face,
       
   914                      FT_Stream  stream )
       
   915   {
       
   916     FT_Error  error;
       
   917 
       
   918 
       
   919     error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
       
   920     if ( error )
       
   921       goto Exit;
       
   922 
       
   923     if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
       
   924       face->cmap_size = 0;
       
   925 
       
   926   Exit:
       
   927     return error;
       
   928   }
       
   929 
       
   930 
       
   931 
       
   932   /*************************************************************************/
       
   933   /*                                                                       */
       
   934   /* <Function>                                                            */
       
   935   /*    tt_face_load_os2                                                   */
       
   936   /*                                                                       */
       
   937   /* <Description>                                                         */
       
   938   /*    Loads the OS2 table.                                               */
       
   939   /*                                                                       */
       
   940   /* <Input>                                                               */
       
   941   /*    face   :: A handle to the target face object.                      */
       
   942   /*                                                                       */
       
   943   /*    stream :: A handle to the input stream.                            */
       
   944   /*                                                                       */
       
   945   /* <Return>                                                              */
       
   946   /*    FreeType error code.  0 means success.                             */
       
   947   /*                                                                       */
       
   948   FT_LOCAL_DEF( FT_Error )
       
   949   tt_face_load_os2( TT_Face    face,
       
   950                     FT_Stream  stream )
       
   951   {
       
   952     FT_Error  error;
       
   953     TT_OS2*   os2;
       
   954 
       
   955     const FT_Frame_Field  os2_fields[] =
       
   956     {
       
   957 #undef  FT_STRUCTURE
       
   958 #define FT_STRUCTURE  TT_OS2
       
   959 
       
   960       FT_FRAME_START( 78 ),
       
   961         FT_FRAME_USHORT( version ),
       
   962         FT_FRAME_SHORT ( xAvgCharWidth ),
       
   963         FT_FRAME_USHORT( usWeightClass ),
       
   964         FT_FRAME_USHORT( usWidthClass ),
       
   965         FT_FRAME_SHORT ( fsType ),
       
   966         FT_FRAME_SHORT ( ySubscriptXSize ),
       
   967         FT_FRAME_SHORT ( ySubscriptYSize ),
       
   968         FT_FRAME_SHORT ( ySubscriptXOffset ),
       
   969         FT_FRAME_SHORT ( ySubscriptYOffset ),
       
   970         FT_FRAME_SHORT ( ySuperscriptXSize ),
       
   971         FT_FRAME_SHORT ( ySuperscriptYSize ),
       
   972         FT_FRAME_SHORT ( ySuperscriptXOffset ),
       
   973         FT_FRAME_SHORT ( ySuperscriptYOffset ),
       
   974         FT_FRAME_SHORT ( yStrikeoutSize ),
       
   975         FT_FRAME_SHORT ( yStrikeoutPosition ),
       
   976         FT_FRAME_SHORT ( sFamilyClass ),
       
   977         FT_FRAME_BYTE  ( panose[0] ),
       
   978         FT_FRAME_BYTE  ( panose[1] ),
       
   979         FT_FRAME_BYTE  ( panose[2] ),
       
   980         FT_FRAME_BYTE  ( panose[3] ),
       
   981         FT_FRAME_BYTE  ( panose[4] ),
       
   982         FT_FRAME_BYTE  ( panose[5] ),
       
   983         FT_FRAME_BYTE  ( panose[6] ),
       
   984         FT_FRAME_BYTE  ( panose[7] ),
       
   985         FT_FRAME_BYTE  ( panose[8] ),
       
   986         FT_FRAME_BYTE  ( panose[9] ),
       
   987         FT_FRAME_ULONG ( ulUnicodeRange1 ),
       
   988         FT_FRAME_ULONG ( ulUnicodeRange2 ),
       
   989         FT_FRAME_ULONG ( ulUnicodeRange3 ),
       
   990         FT_FRAME_ULONG ( ulUnicodeRange4 ),
       
   991         FT_FRAME_BYTE  ( achVendID[0] ),
       
   992         FT_FRAME_BYTE  ( achVendID[1] ),
       
   993         FT_FRAME_BYTE  ( achVendID[2] ),
       
   994         FT_FRAME_BYTE  ( achVendID[3] ),
       
   995 
       
   996         FT_FRAME_USHORT( fsSelection ),
       
   997         FT_FRAME_USHORT( usFirstCharIndex ),
       
   998         FT_FRAME_USHORT( usLastCharIndex ),
       
   999         FT_FRAME_SHORT ( sTypoAscender ),
       
  1000         FT_FRAME_SHORT ( sTypoDescender ),
       
  1001         FT_FRAME_SHORT ( sTypoLineGap ),
       
  1002         FT_FRAME_USHORT( usWinAscent ),
       
  1003         FT_FRAME_USHORT( usWinDescent ),
       
  1004       FT_FRAME_END
       
  1005     };
       
  1006 
       
  1007     const FT_Frame_Field  os2_fields_extra[] =
       
  1008     {
       
  1009       FT_FRAME_START( 8 ),
       
  1010         FT_FRAME_ULONG( ulCodePageRange1 ),
       
  1011         FT_FRAME_ULONG( ulCodePageRange2 ),
       
  1012       FT_FRAME_END
       
  1013     };
       
  1014 
       
  1015     const FT_Frame_Field  os2_fields_extra2[] =
       
  1016     {
       
  1017       FT_FRAME_START( 10 ),
       
  1018         FT_FRAME_SHORT ( sxHeight ),
       
  1019         FT_FRAME_SHORT ( sCapHeight ),
       
  1020         FT_FRAME_USHORT( usDefaultChar ),
       
  1021         FT_FRAME_USHORT( usBreakChar ),
       
  1022         FT_FRAME_USHORT( usMaxContext ),
       
  1023       FT_FRAME_END
       
  1024     };
       
  1025 
       
  1026 
       
  1027     /* We now support old Mac fonts where the OS/2 table doesn't  */
       
  1028     /* exist.  Simply put, we set the `version' field to 0xFFFF   */
       
  1029     /* and test this value each time we need to access the table. */
       
  1030     error = face->goto_table( face, TTAG_OS2, stream, 0 );
       
  1031     if ( error )
       
  1032       goto Exit;
       
  1033 
       
  1034     os2 = &face->os2;
       
  1035 
       
  1036     if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
       
  1037       goto Exit;
       
  1038 
       
  1039     os2->ulCodePageRange1 = 0;
       
  1040     os2->ulCodePageRange2 = 0;
       
  1041     os2->sxHeight         = 0;
       
  1042     os2->sCapHeight       = 0;
       
  1043     os2->usDefaultChar    = 0;
       
  1044     os2->usBreakChar      = 0;
       
  1045     os2->usMaxContext     = 0;
       
  1046 
       
  1047     if ( os2->version >= 0x0001 )
       
  1048     {
       
  1049       /* only version 1 tables */
       
  1050       if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
       
  1051         goto Exit;
       
  1052 
       
  1053       if ( os2->version >= 0x0002 )
       
  1054       {
       
  1055         /* only version 2 tables */
       
  1056         if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
       
  1057           goto Exit;
       
  1058       }
       
  1059     }
       
  1060 
       
  1061     FT_TRACE3(( "sTypoAscender:  %4d\n",   os2->sTypoAscender ));
       
  1062     FT_TRACE3(( "sTypoDescender: %4d\n",   os2->sTypoDescender ));
       
  1063     FT_TRACE3(( "usWinAscent:    %4u\n",   os2->usWinAscent ));
       
  1064     FT_TRACE3(( "usWinDescent:   %4u\n",   os2->usWinDescent ));
       
  1065     FT_TRACE3(( "fsSelection:    0x%2x\n", os2->fsSelection ));
       
  1066 
       
  1067   Exit:
       
  1068     return error;
       
  1069   }
       
  1070 
       
  1071 
       
  1072   /*************************************************************************/
       
  1073   /*                                                                       */
       
  1074   /* <Function>                                                            */
       
  1075   /*    tt_face_load_postscript                                            */
       
  1076   /*                                                                       */
       
  1077   /* <Description>                                                         */
       
  1078   /*    Loads the Postscript table.                                        */
       
  1079   /*                                                                       */
       
  1080   /* <Input>                                                               */
       
  1081   /*    face   :: A handle to the target face object.                      */
       
  1082   /*                                                                       */
       
  1083   /*    stream :: A handle to the input stream.                            */
       
  1084   /*                                                                       */
       
  1085   /* <Return>                                                              */
       
  1086   /*    FreeType error code.  0 means success.                             */
       
  1087   /*                                                                       */
       
  1088   FT_LOCAL_DEF( FT_Error )
       
  1089   tt_face_load_post( TT_Face    face,
       
  1090                      FT_Stream  stream )
       
  1091   {
       
  1092     FT_Error        error;
       
  1093     TT_Postscript*  post = &face->postscript;
       
  1094 
       
  1095     static const FT_Frame_Field  post_fields[] =
       
  1096     {
       
  1097 #undef  FT_STRUCTURE
       
  1098 #define FT_STRUCTURE  TT_Postscript
       
  1099 
       
  1100       FT_FRAME_START( 32 ),
       
  1101         FT_FRAME_ULONG( FormatType ),
       
  1102         FT_FRAME_ULONG( italicAngle ),
       
  1103         FT_FRAME_SHORT( underlinePosition ),
       
  1104         FT_FRAME_SHORT( underlineThickness ),
       
  1105         FT_FRAME_ULONG( isFixedPitch ),
       
  1106         FT_FRAME_ULONG( minMemType42 ),
       
  1107         FT_FRAME_ULONG( maxMemType42 ),
       
  1108         FT_FRAME_ULONG( minMemType1 ),
       
  1109         FT_FRAME_ULONG( maxMemType1 ),
       
  1110       FT_FRAME_END
       
  1111     };
       
  1112 
       
  1113 
       
  1114     error = face->goto_table( face, TTAG_post, stream, 0 );
       
  1115     if ( error )
       
  1116       return error;
       
  1117 
       
  1118     if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
       
  1119       return error;
       
  1120 
       
  1121     /* we don't load the glyph names, we do that in another */
       
  1122     /* module (ttpost).                                     */
       
  1123 
       
  1124     FT_TRACE3(( "FormatType:   0x%x\n", post->FormatType ));
       
  1125     FT_TRACE3(( "isFixedPitch:   %s\n", post->isFixedPitch
       
  1126                                         ? "  yes" : "   no" ));
       
  1127 
       
  1128     return SFNT_Err_Ok;
       
  1129   }
       
  1130 
       
  1131 
       
  1132   /*************************************************************************/
       
  1133   /*                                                                       */
       
  1134   /* <Function>                                                            */
       
  1135   /*    tt_face_load_pclt                                                  */
       
  1136   /*                                                                       */
       
  1137   /* <Description>                                                         */
       
  1138   /*    Loads the PCL 5 Table.                                             */
       
  1139   /*                                                                       */
       
  1140   /* <Input>                                                               */
       
  1141   /*    face   :: A handle to the target face object.                      */
       
  1142   /*                                                                       */
       
  1143   /*    stream :: A handle to the input stream.                            */
       
  1144   /*                                                                       */
       
  1145   /* <Return>                                                              */
       
  1146   /*    FreeType error code.  0 means success.                             */
       
  1147   /*                                                                       */
       
  1148   FT_LOCAL_DEF( FT_Error )
       
  1149   tt_face_load_pclt( TT_Face    face,
       
  1150                      FT_Stream  stream )
       
  1151   {
       
  1152     static const FT_Frame_Field  pclt_fields[] =
       
  1153     {
       
  1154 #undef  FT_STRUCTURE
       
  1155 #define FT_STRUCTURE  TT_PCLT
       
  1156 
       
  1157       FT_FRAME_START( 54 ),
       
  1158         FT_FRAME_ULONG ( Version ),
       
  1159         FT_FRAME_ULONG ( FontNumber ),
       
  1160         FT_FRAME_USHORT( Pitch ),
       
  1161         FT_FRAME_USHORT( xHeight ),
       
  1162         FT_FRAME_USHORT( Style ),
       
  1163         FT_FRAME_USHORT( TypeFamily ),
       
  1164         FT_FRAME_USHORT( CapHeight ),
       
  1165         FT_FRAME_BYTES ( TypeFace, 16 ),
       
  1166         FT_FRAME_BYTES ( CharacterComplement, 8 ),
       
  1167         FT_FRAME_BYTES ( FileName, 6 ),
       
  1168         FT_FRAME_CHAR  ( StrokeWeight ),
       
  1169         FT_FRAME_CHAR  ( WidthType ),
       
  1170         FT_FRAME_BYTE  ( SerifStyle ),
       
  1171         FT_FRAME_BYTE  ( Reserved ),
       
  1172       FT_FRAME_END
       
  1173     };
       
  1174 
       
  1175     FT_Error  error;
       
  1176     TT_PCLT*  pclt = &face->pclt;
       
  1177 
       
  1178 
       
  1179     /* optional table */
       
  1180     error = face->goto_table( face, TTAG_PCLT, stream, 0 );
       
  1181     if ( error )
       
  1182       goto Exit;
       
  1183 
       
  1184     if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
       
  1185       goto Exit;
       
  1186 
       
  1187   Exit:
       
  1188     return error;
       
  1189   }
       
  1190 
       
  1191 
       
  1192   /*************************************************************************/
       
  1193   /*                                                                       */
       
  1194   /* <Function>                                                            */
       
  1195   /*    tt_face_load_gasp                                                  */
       
  1196   /*                                                                       */
       
  1197   /* <Description>                                                         */
       
  1198   /*    Loads the `gasp' table into a face object.                         */
       
  1199   /*                                                                       */
       
  1200   /* <Input>                                                               */
       
  1201   /*    face   :: A handle to the target face object.                      */
       
  1202   /*                                                                       */
       
  1203   /*    stream :: The input stream.                                        */
       
  1204   /*                                                                       */
       
  1205   /* <Return>                                                              */
       
  1206   /*    FreeType error code.  0 means success.                             */
       
  1207   /*                                                                       */
       
  1208   FT_LOCAL_DEF( FT_Error )
       
  1209   tt_face_load_gasp( TT_Face    face,
       
  1210                      FT_Stream  stream )
       
  1211   {
       
  1212     FT_Error   error;
       
  1213     FT_Memory  memory = stream->memory;
       
  1214 
       
  1215     FT_UInt        j,num_ranges;
       
  1216     TT_GaspRange   gaspranges;
       
  1217 
       
  1218 
       
  1219     /* the gasp table is optional */
       
  1220     error = face->goto_table( face, TTAG_gasp, stream, 0 );
       
  1221     if ( error )
       
  1222       goto Exit;
       
  1223 
       
  1224     if ( FT_FRAME_ENTER( 4L ) )
       
  1225       goto Exit;
       
  1226 
       
  1227     face->gasp.version   = FT_GET_USHORT();
       
  1228     face->gasp.numRanges = FT_GET_USHORT();
       
  1229 
       
  1230     FT_FRAME_EXIT();
       
  1231 
       
  1232     /* only support versions 0 and 1 of the table */
       
  1233     if ( face->gasp.version >= 2 )
       
  1234     {
       
  1235       face->gasp.numRanges = 0;
       
  1236       error = SFNT_Err_Invalid_Table;
       
  1237       goto Exit;
       
  1238     }
       
  1239 
       
  1240     num_ranges = face->gasp.numRanges;
       
  1241     FT_TRACE3(( "numRanges: %u\n", num_ranges ));
       
  1242 
       
  1243     if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) ||
       
  1244          FT_FRAME_ENTER( num_ranges * 4L )      )
       
  1245       goto Exit;
       
  1246 
       
  1247     face->gasp.gaspRanges = gaspranges;
       
  1248 
       
  1249     for ( j = 0; j < num_ranges; j++ )
       
  1250     {
       
  1251       gaspranges[j].maxPPEM  = FT_GET_USHORT();
       
  1252       gaspranges[j].gaspFlag = FT_GET_USHORT();
       
  1253 
       
  1254       FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n",
       
  1255                   j,
       
  1256                   gaspranges[j].maxPPEM,
       
  1257                   gaspranges[j].gaspFlag ));
       
  1258     }
       
  1259 
       
  1260     FT_FRAME_EXIT();
       
  1261 
       
  1262   Exit:
       
  1263     return error;
       
  1264   }
       
  1265 
       
  1266 
       
  1267 /* END */