ttload.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ttload.c                                                               */
00004 /*                                                                         */
00005 /*    Load the basic TrueType tables, i.e., tables that can be either in   */
00006 /*    TTF or OTF fonts (body).                                             */
00007 /*                                                                         */
00008 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
00009 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00010 /*                                                                         */
00011 /*  This file is part of the FreeType project, and may only be used,       */
00012 /*  modified, and distributed under the terms of the FreeType project      */
00013 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00014 /*  this file you indicate that you have read the license and              */
00015 /*  understand and accept it fully.                                        */
00016 /*                                                                         */
00017 /***************************************************************************/
00018 
00019 
00020 #include <ft2build.h>
00021 #include FT_INTERNAL_DEBUG_H
00022 #include FT_INTERNAL_STREAM_H
00023 #include FT_TRUETYPE_TAGS_H
00024 #include "ttload.h"
00025 
00026 #include "sferrors.h"
00027 
00028 
00029   /*************************************************************************/
00030   /*                                                                       */
00031   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00032   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00033   /* messages during execution.                                            */
00034   /*                                                                       */
00035 #undef  FT_COMPONENT
00036 #define FT_COMPONENT  trace_ttload
00037 
00038 
00039   /*************************************************************************/
00040   /*                                                                       */
00041   /* <Function>                                                            */
00042   /*    tt_face_lookup_table                                               */
00043   /*                                                                       */
00044   /* <Description>                                                         */
00045   /*    Looks for a TrueType table by name.                                */
00046   /*                                                                       */
00047   /* <Input>                                                               */
00048   /*    face :: A face object handle.                                      */
00049   /*                                                                       */
00050   /*    tag  :: The searched tag.                                          */
00051   /*                                                                       */
00052   /* <Return>                                                              */
00053   /*    A pointer to the table directory entry.  0 if not found.           */
00054   /*                                                                       */
00055   FT_LOCAL_DEF( TT_Table  )
00056   tt_face_lookup_table( TT_Face   face,
00057                         FT_ULong  tag  )
00058   {
00059     TT_Table  entry;
00060     TT_Table  limit;
00061 #ifdef FT_DEBUG_LEVEL_TRACE
00062     FT_Bool   zero_length = FALSE;
00063 #endif
00064 
00065 
00066     FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ",
00067                 face,
00068                 (FT_Char)( tag >> 24 ),
00069                 (FT_Char)( tag >> 16 ),
00070                 (FT_Char)( tag >> 8  ),
00071                 (FT_Char)( tag       ) ));
00072 
00073     entry = face->dir_tables;
00074     limit = entry + face->num_tables;
00075 
00076     for ( ; entry < limit; entry++ )
00077     {
00078       /* For compatibility with Windows, we consider    */
00079       /* zero-length tables the same as missing tables. */
00080       if ( entry->Tag == tag ) {
00081         if ( entry->Length != 0 )
00082         {
00083           FT_TRACE4(( "found table.\n" ));
00084           return entry;
00085         }
00086 #ifdef FT_DEBUG_LEVEL_TRACE
00087         zero_length = TRUE;
00088 #endif
00089       }
00090     }
00091 
00092 #ifdef FT_DEBUG_LEVEL_TRACE
00093     if ( zero_length )
00094       FT_TRACE4(( "ignoring empty table\n" ));
00095     else
00096       FT_TRACE4(( "could not find table\n" ));
00097 #endif
00098 
00099     return NULL;
00100   }
00101 
00102 
00103   /*************************************************************************/
00104   /*                                                                       */
00105   /* <Function>                                                            */
00106   /*    tt_face_goto_table                                                 */
00107   /*                                                                       */
00108   /* <Description>                                                         */
00109   /*    Looks for a TrueType table by name, then seek a stream to it.      */
00110   /*                                                                       */
00111   /* <Input>                                                               */
00112   /*    face   :: A face object handle.                                    */
00113   /*                                                                       */
00114   /*    tag    :: The searched tag.                                        */
00115   /*                                                                       */
00116   /*    stream :: The stream to seek when the table is found.              */
00117   /*                                                                       */
00118   /* <Output>                                                              */
00119   /*    length :: The length of the table if found, undefined otherwise.   */
00120   /*                                                                       */
00121   /* <Return>                                                              */
00122   /*    FreeType error code.  0 means success.                             */
00123   /*                                                                       */
00124   FT_LOCAL_DEF( FT_Error )
00125   tt_face_goto_table( TT_Face    face,
00126                       FT_ULong   tag,
00127                       FT_Stream  stream,
00128                       FT_ULong*  length )
00129   {
00130     TT_Table  table;
00131     FT_Error  error;
00132 
00133 
00134     table = tt_face_lookup_table( face, tag );
00135     if ( table )
00136     {
00137       if ( length )
00138         *length = table->Length;
00139 
00140       if ( FT_STREAM_SEEK( table->Offset ) )
00141         goto Exit;
00142     }
00143     else
00144       error = SFNT_Err_Table_Missing;
00145 
00146   Exit:
00147     return error;
00148   }
00149 
00150 
00151   /* Here, we                                                         */
00152   /*                                                                  */
00153   /* - check that `num_tables' is valid (and adjust it if necessary)  */
00154   /*                                                                  */
00155   /* - look for a `head' table, check its size, and parse it to check */
00156   /*   whether its `magic' field is correctly set                     */
00157   /*                                                                  */
00158   /* - errors (except errors returned by stream handling)             */
00159   /*                                                                  */
00160   /*     SFNT_Err_Unknown_File_Format:                                */
00161   /*       no table is defined in directory, it is not sfnt-wrapped   */
00162   /*       data                                                       */
00163   /*     SFNT_Err_Table_Missing:                                      */
00164   /*       table directory is valid, but essential tables             */
00165   /*       (head/bhed/SING) are missing                               */
00166   /*                                                                  */
00167   static FT_Error
00168   check_table_dir( SFNT_Header  sfnt,
00169                    FT_Stream    stream )
00170   {
00171     FT_Error   error;
00172     FT_UShort  nn, valid_entries = 0;
00173     FT_UInt    has_head = 0, has_sing = 0, has_meta = 0;
00174     FT_ULong   offset = sfnt->offset + 12;
00175 
00176     static const FT_Frame_Field  table_dir_entry_fields[] =
00177     {
00178 #undef  FT_STRUCTURE
00179 #define FT_STRUCTURE  TT_TableRec
00180 
00181       FT_FRAME_START( 16 ),
00182         FT_FRAME_ULONG( Tag ),
00183         FT_FRAME_ULONG( CheckSum ),
00184         FT_FRAME_ULONG( Offset ),
00185         FT_FRAME_ULONG( Length ),
00186       FT_FRAME_END
00187     };
00188 
00189 
00190     if ( FT_STREAM_SEEK( offset ) )
00191       goto Exit;
00192 
00193     for ( nn = 0; nn < sfnt->num_tables; nn++ )
00194     {
00195       TT_TableRec  table;
00196 
00197 
00198       if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) )
00199       {
00200         nn--;
00201         FT_TRACE2(( "check_table_dir:"
00202                     " can read only %d table%s in font (instead of %d)\n",
00203                     nn, nn == 1 ? "" : "s", sfnt->num_tables ));
00204         sfnt->num_tables = nn;
00205         break;
00206       }
00207 
00208       /* we ignore invalid tables */
00209       if ( table.Offset + table.Length > stream->size )
00210       {
00211         FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
00212         continue;
00213       }
00214       else
00215         valid_entries++;
00216 
00217       if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed )
00218       {
00219         FT_UInt32  magic;
00220 
00221 
00222 #ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
00223         if ( table.Tag == TTAG_head )
00224 #endif
00225           has_head = 1;
00226 
00227         /*
00228          * The table length should be 0x36, but certain font tools make it
00229          * 0x38, so we will just check that it is greater.
00230          *
00231          * Note that according to the specification, the table must be
00232          * padded to 32-bit lengths, but this doesn't apply to the value of
00233          * its `Length' field!
00234          *
00235          */
00236         if ( table.Length < 0x36 )
00237         {
00238           FT_TRACE2(( "check_table_dir: `head' table too small\n" ));
00239           error = SFNT_Err_Table_Missing;
00240           goto Exit;
00241         }
00242 
00243         if ( FT_STREAM_SEEK( table.Offset + 12 ) ||
00244              FT_READ_ULONG( magic )              )
00245           goto Exit;
00246 
00247         if ( magic != 0x5F0F3CF5UL )
00248         {
00249           FT_TRACE2(( "check_table_dir:"
00250                       " no magic number found in `head' table\n"));
00251           error = SFNT_Err_Table_Missing;
00252           goto Exit;
00253         }
00254 
00255         if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )
00256           goto Exit;
00257       }
00258       else if ( table.Tag == TTAG_SING )
00259         has_sing = 1;
00260       else if ( table.Tag == TTAG_META )
00261         has_meta = 1;
00262     }
00263 
00264     sfnt->num_tables = valid_entries;
00265 
00266     if ( sfnt->num_tables == 0 )
00267     {
00268       FT_TRACE2(( "check_table_dir: no tables found\n" ));
00269       error = SFNT_Err_Unknown_File_Format;
00270       goto Exit;
00271     }
00272 
00273     /* if `sing' and `meta' tables are present, there is no `head' table */
00274     if ( has_head || ( has_sing && has_meta ) )
00275     {
00276       error = SFNT_Err_Ok;
00277       goto Exit;
00278     }
00279     else
00280     {
00281       FT_TRACE2(( "check_table_dir:" ));
00282 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
00283       FT_TRACE2(( " neither `head', `bhed', nor `sing' table found\n" ));
00284 #else
00285       FT_TRACE2(( " neither `head' nor `sing' table found\n" ));
00286 #endif
00287       error = SFNT_Err_Table_Missing;
00288     }
00289 
00290   Exit:
00291     return error;
00292   }
00293 
00294 
00295   /*************************************************************************/
00296   /*                                                                       */
00297   /* <Function>                                                            */
00298   /*    tt_face_load_font_dir                                              */
00299   /*                                                                       */
00300   /* <Description>                                                         */
00301   /*    Loads the header of a SFNT font file.                              */
00302   /*                                                                       */
00303   /* <Input>                                                               */
00304   /*    face       :: A handle to the target face object.                  */
00305   /*                                                                       */
00306   /*    stream     :: The input stream.                                    */
00307   /*                                                                       */
00308   /* <Output>                                                              */
00309   /*    sfnt       :: The SFNT header.                                     */
00310   /*                                                                       */
00311   /* <Return>                                                              */
00312   /*    FreeType error code.  0 means success.                             */
00313   /*                                                                       */
00314   /* <Note>                                                                */
00315   /*    The stream cursor must be at the beginning of the font directory.  */
00316   /*                                                                       */
00317   FT_LOCAL_DEF( FT_Error )
00318   tt_face_load_font_dir( TT_Face    face,
00319                          FT_Stream  stream )
00320   {
00321     SFNT_HeaderRec  sfnt;
00322     FT_Error        error;
00323     FT_Memory       memory = stream->memory;
00324     TT_TableRec*    entry;
00325     FT_Int          nn;
00326 
00327     static const FT_Frame_Field  offset_table_fields[] =
00328     {
00329 #undef  FT_STRUCTURE
00330 #define FT_STRUCTURE  SFNT_HeaderRec
00331 
00332       FT_FRAME_START( 8 ),
00333         FT_FRAME_USHORT( num_tables ),
00334         FT_FRAME_USHORT( search_range ),
00335         FT_FRAME_USHORT( entry_selector ),
00336         FT_FRAME_USHORT( range_shift ),
00337       FT_FRAME_END
00338     };
00339 
00340 
00341     FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face ));
00342 
00343     /* read the offset table */
00344 
00345     sfnt.offset = FT_STREAM_POS();
00346 
00347     if ( FT_READ_ULONG( sfnt.format_tag )                    ||
00348          FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) )
00349       goto Exit;
00350 
00351     /* many fonts don't have these fields set correctly */
00352 #if 0
00353     if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 )        ||
00354          sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 )
00355       return SFNT_Err_Unknown_File_Format;
00356 #endif
00357 
00358     /* load the table directory */
00359 
00360     FT_TRACE2(( "-- Number of tables: %10u\n",    sfnt.num_tables ));
00361     FT_TRACE2(( "-- Format version:   0x%08lx\n", sfnt.format_tag ));
00362 
00363     /* check first */
00364     error = check_table_dir( &sfnt, stream );
00365     if ( error )
00366     {
00367       FT_TRACE2(( "tt_face_load_font_dir:"
00368                   " invalid table directory for TrueType\n" ));
00369 
00370       goto Exit;
00371     }
00372 
00373     face->num_tables = sfnt.num_tables;
00374     face->format_tag = sfnt.format_tag;
00375 
00376     if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) )
00377       goto Exit;
00378 
00379     if ( FT_STREAM_SEEK( sfnt.offset + 12 )       ||
00380          FT_FRAME_ENTER( face->num_tables * 16L ) )
00381       goto Exit;
00382 
00383     entry = face->dir_tables;
00384 
00385     for ( nn = 0; nn < sfnt.num_tables; nn++ )
00386     {
00387       entry->Tag      = FT_GET_TAG4();
00388       entry->CheckSum = FT_GET_ULONG();
00389       entry->Offset   = FT_GET_LONG();
00390       entry->Length   = FT_GET_LONG();
00391 
00392       /* ignore invalid tables */
00393       if ( entry->Offset + entry->Length > stream->size )
00394         continue;
00395       else
00396       {
00397         FT_TRACE2(( "  %c%c%c%c  -  %08lx  -  %08lx\n",
00398                     (FT_Char)( entry->Tag >> 24 ),
00399                     (FT_Char)( entry->Tag >> 16 ),
00400                     (FT_Char)( entry->Tag >> 8  ),
00401                     (FT_Char)( entry->Tag       ),
00402                     entry->Offset,
00403                     entry->Length ));
00404         entry++;
00405       }
00406     }
00407 
00408     FT_FRAME_EXIT();
00409 
00410     FT_TRACE2(( "table directory loaded\n\n" ));
00411 
00412   Exit:
00413     return error;
00414   }
00415 
00416 
00417   /*************************************************************************/
00418   /*                                                                       */
00419   /* <Function>                                                            */
00420   /*    tt_face_load_any                                                   */
00421   /*                                                                       */
00422   /* <Description>                                                         */
00423   /*    Loads any font table into client memory.                           */
00424   /*                                                                       */
00425   /* <Input>                                                               */
00426   /*    face   :: The face object to look for.                             */
00427   /*                                                                       */
00428   /*    tag    :: The tag of table to load.  Use the value 0 if you want   */
00429   /*              to access the whole font file, else set this parameter   */
00430   /*              to a valid TrueType table tag that you can forge with    */
00431   /*              the MAKE_TT_TAG macro.                                   */
00432   /*                                                                       */
00433   /*    offset :: The starting offset in the table (or the file if         */
00434   /*              tag == 0).                                               */
00435   /*                                                                       */
00436   /*    length :: The address of the decision variable:                    */
00437   /*                                                                       */
00438   /*                If length == NULL:                                     */
00439   /*                  Loads the whole table.  Returns an error if          */
00440   /*                  `offset' == 0!                                       */
00441   /*                                                                       */
00442   /*                If *length == 0:                                       */
00443   /*                  Exits immediately; returning the length of the given */
00444   /*                  table or of the font file, depending on the value of */
00445   /*                  `tag'.                                               */
00446   /*                                                                       */
00447   /*                If *length != 0:                                       */
00448   /*                  Loads the next `length' bytes of table or font,      */
00449   /*                  starting at offset `offset' (in table or font too).  */
00450   /*                                                                       */
00451   /* <Output>                                                              */
00452   /*    buffer :: The address of target buffer.                            */
00453   /*                                                                       */
00454   /* <Return>                                                              */
00455   /*    FreeType error code.  0 means success.                             */
00456   /*                                                                       */
00457   FT_LOCAL_DEF( FT_Error )
00458   tt_face_load_any( TT_Face    face,
00459                     FT_ULong   tag,
00460                     FT_Long    offset,
00461                     FT_Byte*   buffer,
00462                     FT_ULong*  length )
00463   {
00464     FT_Error   error;
00465     FT_Stream  stream;
00466     TT_Table   table;
00467     FT_ULong   size;
00468 
00469 
00470     if ( tag != 0 )
00471     {
00472       /* look for tag in font directory */
00473       table = tt_face_lookup_table( face, tag );
00474       if ( !table )
00475       {
00476         error = SFNT_Err_Table_Missing;
00477         goto Exit;
00478       }
00479 
00480       offset += table->Offset;
00481       size    = table->Length;
00482     }
00483     else
00484       /* tag == 0 -- the user wants to access the font file directly */
00485       size = face->root.stream->size;
00486 
00487     if ( length && *length == 0 )
00488     {
00489       *length = size;
00490 
00491       return SFNT_Err_Ok;
00492     }
00493 
00494     if ( length )
00495       size = *length;
00496 
00497     stream = face->root.stream;
00498     /* the `if' is syntactic sugar for picky compilers */
00499     if ( FT_STREAM_READ_AT( offset, buffer, size ) )
00500       goto Exit;
00501 
00502   Exit:
00503     return error;
00504   }
00505 
00506 
00507   /*************************************************************************/
00508   /*                                                                       */
00509   /* <Function>                                                            */
00510   /*    tt_face_load_generic_header                                        */
00511   /*                                                                       */
00512   /* <Description>                                                         */
00513   /*    Loads the TrueType table `head' or `bhed'.                         */
00514   /*                                                                       */
00515   /* <Input>                                                               */
00516   /*    face   :: A handle to the target face object.                      */
00517   /*                                                                       */
00518   /*    stream :: The input stream.                                        */
00519   /*                                                                       */
00520   /* <Return>                                                              */
00521   /*    FreeType error code.  0 means success.                             */
00522   /*                                                                       */
00523   static FT_Error
00524   tt_face_load_generic_header( TT_Face    face,
00525                                FT_Stream  stream,
00526                                FT_ULong   tag )
00527   {
00528     FT_Error    error;
00529     TT_Header*  header;
00530 
00531     static const FT_Frame_Field  header_fields[] =
00532     {
00533 #undef  FT_STRUCTURE
00534 #define FT_STRUCTURE  TT_Header
00535 
00536       FT_FRAME_START( 54 ),
00537         FT_FRAME_ULONG ( Table_Version ),
00538         FT_FRAME_ULONG ( Font_Revision ),
00539         FT_FRAME_LONG  ( CheckSum_Adjust ),
00540         FT_FRAME_LONG  ( Magic_Number ),
00541         FT_FRAME_USHORT( Flags ),
00542         FT_FRAME_USHORT( Units_Per_EM ),
00543         FT_FRAME_LONG  ( Created[0] ),
00544         FT_FRAME_LONG  ( Created[1] ),
00545         FT_FRAME_LONG  ( Modified[0] ),
00546         FT_FRAME_LONG  ( Modified[1] ),
00547         FT_FRAME_SHORT ( xMin ),
00548         FT_FRAME_SHORT ( yMin ),
00549         FT_FRAME_SHORT ( xMax ),
00550         FT_FRAME_SHORT ( yMax ),
00551         FT_FRAME_USHORT( Mac_Style ),
00552         FT_FRAME_USHORT( Lowest_Rec_PPEM ),
00553         FT_FRAME_SHORT ( Font_Direction ),
00554         FT_FRAME_SHORT ( Index_To_Loc_Format ),
00555         FT_FRAME_SHORT ( Glyph_Data_Format ),
00556       FT_FRAME_END
00557     };
00558 
00559 
00560     error = face->goto_table( face, tag, stream, 0 );
00561     if ( error )
00562       goto Exit;
00563 
00564     header = &face->header;
00565 
00566     if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
00567       goto Exit;
00568 
00569     FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM ));
00570     FT_TRACE3(( "IndexToLoc:   %4d\n", header->Index_To_Loc_Format ));
00571 
00572   Exit:
00573     return error;
00574   }
00575 
00576 
00577   FT_LOCAL_DEF( FT_Error )
00578   tt_face_load_head( TT_Face    face,
00579                      FT_Stream  stream )
00580   {
00581     return tt_face_load_generic_header( face, stream, TTAG_head );
00582   }
00583 
00584 
00585 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
00586 
00587   FT_LOCAL_DEF( FT_Error )
00588   tt_face_load_bhed( TT_Face    face,
00589                      FT_Stream  stream )
00590   {
00591     return tt_face_load_generic_header( face, stream, TTAG_bhed );
00592   }
00593 
00594 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
00595 
00596 
00597   /*************************************************************************/
00598   /*                                                                       */
00599   /* <Function>                                                            */
00600   /*    tt_face_load_max_profile                                           */
00601   /*                                                                       */
00602   /* <Description>                                                         */
00603   /*    Loads the maximum profile into a face object.                      */
00604   /*                                                                       */
00605   /* <Input>                                                               */
00606   /*    face   :: A handle to the target face object.                      */
00607   /*                                                                       */
00608   /*    stream :: The input stream.                                        */
00609   /*                                                                       */
00610   /* <Return>                                                              */
00611   /*    FreeType error code.  0 means success.                             */
00612   /*                                                                       */
00613   FT_LOCAL_DEF( FT_Error )
00614   tt_face_load_maxp( TT_Face    face,
00615                      FT_Stream  stream )
00616   {
00617     FT_Error        error;
00618     TT_MaxProfile*  maxProfile = &face->max_profile;
00619 
00620     const FT_Frame_Field  maxp_fields[] =
00621     {
00622 #undef  FT_STRUCTURE
00623 #define FT_STRUCTURE  TT_MaxProfile
00624 
00625       FT_FRAME_START( 6 ),
00626         FT_FRAME_LONG  ( version ),
00627         FT_FRAME_USHORT( numGlyphs ),
00628       FT_FRAME_END
00629     };
00630 
00631     const FT_Frame_Field  maxp_fields_extra[] =
00632     {
00633       FT_FRAME_START( 26 ),
00634         FT_FRAME_USHORT( maxPoints ),
00635         FT_FRAME_USHORT( maxContours ),
00636         FT_FRAME_USHORT( maxCompositePoints ),
00637         FT_FRAME_USHORT( maxCompositeContours ),
00638         FT_FRAME_USHORT( maxZones ),
00639         FT_FRAME_USHORT( maxTwilightPoints ),
00640         FT_FRAME_USHORT( maxStorage ),
00641         FT_FRAME_USHORT( maxFunctionDefs ),
00642         FT_FRAME_USHORT( maxInstructionDefs ),
00643         FT_FRAME_USHORT( maxStackElements ),
00644         FT_FRAME_USHORT( maxSizeOfInstructions ),
00645         FT_FRAME_USHORT( maxComponentElements ),
00646         FT_FRAME_USHORT( maxComponentDepth ),
00647       FT_FRAME_END
00648     };
00649 
00650 
00651     error = face->goto_table( face, TTAG_maxp, stream, 0 );
00652     if ( error )
00653       goto Exit;
00654 
00655     if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
00656       goto Exit;
00657 
00658     maxProfile->maxPoints             = 0;
00659     maxProfile->maxContours           = 0;
00660     maxProfile->maxCompositePoints    = 0;
00661     maxProfile->maxCompositeContours  = 0;
00662     maxProfile->maxZones              = 0;
00663     maxProfile->maxTwilightPoints     = 0;
00664     maxProfile->maxStorage            = 0;
00665     maxProfile->maxFunctionDefs       = 0;
00666     maxProfile->maxInstructionDefs    = 0;
00667     maxProfile->maxStackElements      = 0;
00668     maxProfile->maxSizeOfInstructions = 0;
00669     maxProfile->maxComponentElements  = 0;
00670     maxProfile->maxComponentDepth     = 0;
00671 
00672     if ( maxProfile->version >= 0x10000L )
00673     {
00674       if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
00675         goto Exit;
00676 
00677       /* XXX: an adjustment that is necessary to load certain */
00678       /*      broken fonts like `Keystrokes MT' :-(           */
00679       /*                                                      */
00680       /*   We allocate 64 function entries by default when    */
00681       /*   the maxFunctionDefs field is null.                 */
00682 
00683       if ( maxProfile->maxFunctionDefs == 0 )
00684         maxProfile->maxFunctionDefs = 64;
00685 
00686       /* we add 4 phantom points later */
00687       if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) )
00688       {
00689         FT_TRACE0(( "tt_face_load_maxp:"
00690                     " too much twilight points in `maxp' table;\n"
00691                     "                  "
00692                     " some glyphs might be rendered incorrectly\n" ));
00693 
00694         maxProfile->maxTwilightPoints = 0xFFFFU - 4;
00695       }
00696     }
00697 
00698     FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs ));
00699 
00700   Exit:
00701     return error;
00702   }
00703 
00704 
00705   /*************************************************************************/
00706   /*                                                                       */
00707   /* <Function>                                                            */
00708   /*    tt_face_load_names                                                 */
00709   /*                                                                       */
00710   /* <Description>                                                         */
00711   /*    Loads the name records.                                            */
00712   /*                                                                       */
00713   /* <Input>                                                               */
00714   /*    face   :: A handle to the target face object.                      */
00715   /*                                                                       */
00716   /*    stream :: The input stream.                                        */
00717   /*                                                                       */
00718   /* <Return>                                                              */
00719   /*    FreeType error code.  0 means success.                             */
00720   /*                                                                       */
00721   FT_LOCAL_DEF( FT_Error )
00722   tt_face_load_name( TT_Face    face,
00723                      FT_Stream  stream )
00724   {
00725     FT_Error      error;
00726     FT_Memory     memory = stream->memory;
00727     FT_ULong      table_pos, table_len;
00728     FT_ULong      storage_start, storage_limit;
00729     FT_UInt       count;
00730     TT_NameTable  table;
00731 
00732     static const FT_Frame_Field  name_table_fields[] =
00733     {
00734 #undef  FT_STRUCTURE
00735 #define FT_STRUCTURE  TT_NameTableRec
00736 
00737       FT_FRAME_START( 6 ),
00738         FT_FRAME_USHORT( format ),
00739         FT_FRAME_USHORT( numNameRecords ),
00740         FT_FRAME_USHORT( storageOffset ),
00741       FT_FRAME_END
00742     };
00743 
00744     static const FT_Frame_Field  name_record_fields[] =
00745     {
00746 #undef  FT_STRUCTURE
00747 #define FT_STRUCTURE  TT_NameEntryRec
00748 
00749       /* no FT_FRAME_START */
00750         FT_FRAME_USHORT( platformID ),
00751         FT_FRAME_USHORT( encodingID ),
00752         FT_FRAME_USHORT( languageID ),
00753         FT_FRAME_USHORT( nameID ),
00754         FT_FRAME_USHORT( stringLength ),
00755         FT_FRAME_USHORT( stringOffset ),
00756       FT_FRAME_END
00757     };
00758 
00759 
00760     table         = &face->name_table;
00761     table->stream = stream;
00762 
00763     error = face->goto_table( face, TTAG_name, stream, &table_len );
00764     if ( error )
00765       goto Exit;
00766 
00767     table_pos = FT_STREAM_POS();
00768 
00769 
00770     if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
00771       goto Exit;
00772 
00773     /* Some popular Asian fonts have an invalid `storageOffset' value   */
00774     /* (it should be at least "6 + 12*num_names").  However, the string */
00775     /* offsets, computed as "storageOffset + entry->stringOffset", are  */
00776     /* valid pointers within the name table...                          */
00777     /*                                                                  */
00778     /* We thus can't check `storageOffset' right now.                   */
00779     /*                                                                  */
00780     storage_start = table_pos + 6 + 12*table->numNameRecords;
00781     storage_limit = table_pos + table_len;
00782 
00783     if ( storage_start > storage_limit )
00784     {
00785       FT_ERROR(( "tt_face_load_name: invalid `name' table\n" ));
00786       error = SFNT_Err_Name_Table_Missing;
00787       goto Exit;
00788     }
00789 
00790     /* Allocate the array of name records. */
00791     count                 = table->numNameRecords;
00792     table->numNameRecords = 0;
00793 
00794     if ( FT_NEW_ARRAY( table->names, count ) ||
00795          FT_FRAME_ENTER( count * 12 )        )
00796       goto Exit;
00797 
00798     /* Load the name records and determine how much storage is needed */
00799     /* to hold the strings themselves.                                */
00800     {
00801       TT_NameEntryRec*  entry = table->names;
00802 
00803 
00804       for ( ; count > 0; count-- )
00805       {
00806         if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
00807           continue;
00808 
00809         /* check that the name is not empty */
00810         if ( entry->stringLength == 0 )
00811           continue;
00812 
00813         /* check that the name string is within the table */
00814         entry->stringOffset += table_pos + table->storageOffset;
00815         if ( entry->stringOffset                       < storage_start ||
00816              entry->stringOffset + entry->stringLength > storage_limit )
00817         {
00818           /* invalid entry - ignore it */
00819           entry->stringOffset = 0;
00820           entry->stringLength = 0;
00821           continue;
00822         }
00823 
00824         entry++;
00825       }
00826 
00827       table->numNameRecords = (FT_UInt)( entry - table->names );
00828     }
00829 
00830     FT_FRAME_EXIT();
00831 
00832     /* everything went well, update face->num_names */
00833     face->num_names = (FT_UShort) table->numNameRecords;
00834 
00835   Exit:
00836     return error;
00837   }
00838 
00839 
00840   /*************************************************************************/
00841   /*                                                                       */
00842   /* <Function>                                                            */
00843   /*    tt_face_free_names                                                 */
00844   /*                                                                       */
00845   /* <Description>                                                         */
00846   /*    Frees the name records.                                            */
00847   /*                                                                       */
00848   /* <Input>                                                               */
00849   /*    face :: A handle to the target face object.                        */
00850   /*                                                                       */
00851   FT_LOCAL_DEF( void )
00852   tt_face_free_name( TT_Face  face )
00853   {
00854     FT_Memory     memory = face->root.driver->root.memory;
00855     TT_NameTable  table  = &face->name_table;
00856     TT_NameEntry  entry  = table->names;
00857     FT_UInt       count  = table->numNameRecords;
00858 
00859 
00860     if ( table->names )
00861     {
00862       for ( ; count > 0; count--, entry++ )
00863       {
00864         FT_FREE( entry->string );
00865         entry->stringLength = 0;
00866       }
00867 
00868       /* free strings table */
00869       FT_FREE( table->names );
00870     }
00871 
00872     table->numNameRecords = 0;
00873     table->format         = 0;
00874     table->storageOffset  = 0;
00875   }
00876 
00877 
00878   /*************************************************************************/
00879   /*                                                                       */
00880   /* <Function>                                                            */
00881   /*    tt_face_load_cmap                                                  */
00882   /*                                                                       */
00883   /* <Description>                                                         */
00884   /*    Loads the cmap directory in a face object.  The cmaps themselves   */
00885   /*    are loaded on demand in the `ttcmap.c' module.                     */
00886   /*                                                                       */
00887   /* <Input>                                                               */
00888   /*    face   :: A handle to the target face object.                      */
00889   /*                                                                       */
00890   /*    stream :: A handle to the input stream.                            */
00891   /*                                                                       */
00892   /* <Return>                                                              */
00893   /*    FreeType error code.  0 means success.                             */
00894   /*                                                                       */
00895 
00896   FT_LOCAL_DEF( FT_Error )
00897   tt_face_load_cmap( TT_Face    face,
00898                      FT_Stream  stream )
00899   {
00900     FT_Error  error;
00901 
00902 
00903     error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
00904     if ( error )
00905       goto Exit;
00906 
00907     if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
00908       face->cmap_size = 0;
00909 
00910   Exit:
00911     return error;
00912   }
00913 
00914 
00915 
00916   /*************************************************************************/
00917   /*                                                                       */
00918   /* <Function>                                                            */
00919   /*    tt_face_load_os2                                                   */
00920   /*                                                                       */
00921   /* <Description>                                                         */
00922   /*    Loads the OS2 table.                                               */
00923   /*                                                                       */
00924   /* <Input>                                                               */
00925   /*    face   :: A handle to the target face object.                      */
00926   /*                                                                       */
00927   /*    stream :: A handle to the input stream.                            */
00928   /*                                                                       */
00929   /* <Return>                                                              */
00930   /*    FreeType error code.  0 means success.                             */
00931   /*                                                                       */
00932   FT_LOCAL_DEF( FT_Error )
00933   tt_face_load_os2( TT_Face    face,
00934                     FT_Stream  stream )
00935   {
00936     FT_Error  error;
00937     TT_OS2*   os2;
00938 
00939     const FT_Frame_Field  os2_fields[] =
00940     {
00941 #undef  FT_STRUCTURE
00942 #define FT_STRUCTURE  TT_OS2
00943 
00944       FT_FRAME_START( 78 ),
00945         FT_FRAME_USHORT( version ),
00946         FT_FRAME_SHORT ( xAvgCharWidth ),
00947         FT_FRAME_USHORT( usWeightClass ),
00948         FT_FRAME_USHORT( usWidthClass ),
00949         FT_FRAME_SHORT ( fsType ),
00950         FT_FRAME_SHORT ( ySubscriptXSize ),
00951         FT_FRAME_SHORT ( ySubscriptYSize ),
00952         FT_FRAME_SHORT ( ySubscriptXOffset ),
00953         FT_FRAME_SHORT ( ySubscriptYOffset ),
00954         FT_FRAME_SHORT ( ySuperscriptXSize ),
00955         FT_FRAME_SHORT ( ySuperscriptYSize ),
00956         FT_FRAME_SHORT ( ySuperscriptXOffset ),
00957         FT_FRAME_SHORT ( ySuperscriptYOffset ),
00958         FT_FRAME_SHORT ( yStrikeoutSize ),
00959         FT_FRAME_SHORT ( yStrikeoutPosition ),
00960         FT_FRAME_SHORT ( sFamilyClass ),
00961         FT_FRAME_BYTE  ( panose[0] ),
00962         FT_FRAME_BYTE  ( panose[1] ),
00963         FT_FRAME_BYTE  ( panose[2] ),
00964         FT_FRAME_BYTE  ( panose[3] ),
00965         FT_FRAME_BYTE  ( panose[4] ),
00966         FT_FRAME_BYTE  ( panose[5] ),
00967         FT_FRAME_BYTE  ( panose[6] ),
00968         FT_FRAME_BYTE  ( panose[7] ),
00969         FT_FRAME_BYTE  ( panose[8] ),
00970         FT_FRAME_BYTE  ( panose[9] ),
00971         FT_FRAME_ULONG ( ulUnicodeRange1 ),
00972         FT_FRAME_ULONG ( ulUnicodeRange2 ),
00973         FT_FRAME_ULONG ( ulUnicodeRange3 ),
00974         FT_FRAME_ULONG ( ulUnicodeRange4 ),
00975         FT_FRAME_BYTE  ( achVendID[0] ),
00976         FT_FRAME_BYTE  ( achVendID[1] ),
00977         FT_FRAME_BYTE  ( achVendID[2] ),
00978         FT_FRAME_BYTE  ( achVendID[3] ),
00979 
00980         FT_FRAME_USHORT( fsSelection ),
00981         FT_FRAME_USHORT( usFirstCharIndex ),
00982         FT_FRAME_USHORT( usLastCharIndex ),
00983         FT_FRAME_SHORT ( sTypoAscender ),
00984         FT_FRAME_SHORT ( sTypoDescender ),
00985         FT_FRAME_SHORT ( sTypoLineGap ),
00986         FT_FRAME_USHORT( usWinAscent ),
00987         FT_FRAME_USHORT( usWinDescent ),
00988       FT_FRAME_END
00989     };
00990 
00991     const FT_Frame_Field  os2_fields_extra[] =
00992     {
00993       FT_FRAME_START( 8 ),
00994         FT_FRAME_ULONG( ulCodePageRange1 ),
00995         FT_FRAME_ULONG( ulCodePageRange2 ),
00996       FT_FRAME_END
00997     };
00998 
00999     const FT_Frame_Field  os2_fields_extra2[] =
01000     {
01001       FT_FRAME_START( 10 ),
01002         FT_FRAME_SHORT ( sxHeight ),
01003         FT_FRAME_SHORT ( sCapHeight ),
01004         FT_FRAME_USHORT( usDefaultChar ),
01005         FT_FRAME_USHORT( usBreakChar ),
01006         FT_FRAME_USHORT( usMaxContext ),
01007       FT_FRAME_END
01008     };
01009 
01010 
01011     /* We now support old Mac fonts where the OS/2 table doesn't  */
01012     /* exist.  Simply put, we set the `version' field to 0xFFFF   */
01013     /* and test this value each time we need to access the table. */
01014     error = face->goto_table( face, TTAG_OS2, stream, 0 );
01015     if ( error )
01016       goto Exit;
01017 
01018     os2 = &face->os2;
01019 
01020     if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
01021       goto Exit;
01022 
01023     os2->ulCodePageRange1 = 0;
01024     os2->ulCodePageRange2 = 0;
01025     os2->sxHeight         = 0;
01026     os2->sCapHeight       = 0;
01027     os2->usDefaultChar    = 0;
01028     os2->usBreakChar      = 0;
01029     os2->usMaxContext     = 0;
01030 
01031     if ( os2->version >= 0x0001 )
01032     {
01033       /* only version 1 tables */
01034       if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
01035         goto Exit;
01036 
01037       if ( os2->version >= 0x0002 )
01038       {
01039         /* only version 2 tables */
01040         if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
01041           goto Exit;
01042       }
01043     }
01044 
01045     FT_TRACE3(( "sTypoAscender:  %4d\n",   os2->sTypoAscender ));
01046     FT_TRACE3(( "sTypoDescender: %4d\n",   os2->sTypoDescender ));
01047     FT_TRACE3(( "usWinAscent:    %4u\n",   os2->usWinAscent ));
01048     FT_TRACE3(( "usWinDescent:   %4u\n",   os2->usWinDescent ));
01049     FT_TRACE3(( "fsSelection:    0x%2x\n", os2->fsSelection ));
01050 
01051   Exit:
01052     return error;
01053   }
01054 
01055 
01056   /*************************************************************************/
01057   /*                                                                       */
01058   /* <Function>                                                            */
01059   /*    tt_face_load_postscript                                            */
01060   /*                                                                       */
01061   /* <Description>                                                         */
01062   /*    Loads the Postscript table.                                        */
01063   /*                                                                       */
01064   /* <Input>                                                               */
01065   /*    face   :: A handle to the target face object.                      */
01066   /*                                                                       */
01067   /*    stream :: A handle to the input stream.                            */
01068   /*                                                                       */
01069   /* <Return>                                                              */
01070   /*    FreeType error code.  0 means success.                             */
01071   /*                                                                       */
01072   FT_LOCAL_DEF( FT_Error )
01073   tt_face_load_post( TT_Face    face,
01074                      FT_Stream  stream )
01075   {
01076     FT_Error        error;
01077     TT_Postscript*  post = &face->postscript;
01078 
01079     static const FT_Frame_Field  post_fields[] =
01080     {
01081 #undef  FT_STRUCTURE
01082 #define FT_STRUCTURE  TT_Postscript
01083 
01084       FT_FRAME_START( 32 ),
01085         FT_FRAME_ULONG( FormatType ),
01086         FT_FRAME_ULONG( italicAngle ),
01087         FT_FRAME_SHORT( underlinePosition ),
01088         FT_FRAME_SHORT( underlineThickness ),
01089         FT_FRAME_ULONG( isFixedPitch ),
01090         FT_FRAME_ULONG( minMemType42 ),
01091         FT_FRAME_ULONG( maxMemType42 ),
01092         FT_FRAME_ULONG( minMemType1 ),
01093         FT_FRAME_ULONG( maxMemType1 ),
01094       FT_FRAME_END
01095     };
01096 
01097 
01098     error = face->goto_table( face, TTAG_post, stream, 0 );
01099     if ( error )
01100       return error;
01101 
01102     if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
01103       return error;
01104 
01105     /* we don't load the glyph names, we do that in another */
01106     /* module (ttpost).                                     */
01107 
01108     FT_TRACE3(( "FormatType:   0x%x\n", post->FormatType ));
01109     FT_TRACE3(( "isFixedPitch:   %s\n", post->isFixedPitch
01110                                         ? "  yes" : "   no" ));
01111 
01112     return SFNT_Err_Ok;
01113   }
01114 
01115 
01116   /*************************************************************************/
01117   /*                                                                       */
01118   /* <Function>                                                            */
01119   /*    tt_face_load_pclt                                                  */
01120   /*                                                                       */
01121   /* <Description>                                                         */
01122   /*    Loads the PCL 5 Table.                                             */
01123   /*                                                                       */
01124   /* <Input>                                                               */
01125   /*    face   :: A handle to the target face object.                      */
01126   /*                                                                       */
01127   /*    stream :: A handle to the input stream.                            */
01128   /*                                                                       */
01129   /* <Return>                                                              */
01130   /*    FreeType error code.  0 means success.                             */
01131   /*                                                                       */
01132   FT_LOCAL_DEF( FT_Error )
01133   tt_face_load_pclt( TT_Face    face,
01134                      FT_Stream  stream )
01135   {
01136     static const FT_Frame_Field  pclt_fields[] =
01137     {
01138 #undef  FT_STRUCTURE
01139 #define FT_STRUCTURE  TT_PCLT
01140 
01141       FT_FRAME_START( 54 ),
01142         FT_FRAME_ULONG ( Version ),
01143         FT_FRAME_ULONG ( FontNumber ),
01144         FT_FRAME_USHORT( Pitch ),
01145         FT_FRAME_USHORT( xHeight ),
01146         FT_FRAME_USHORT( Style ),
01147         FT_FRAME_USHORT( TypeFamily ),
01148         FT_FRAME_USHORT( CapHeight ),
01149         FT_FRAME_BYTES ( TypeFace, 16 ),
01150         FT_FRAME_BYTES ( CharacterComplement, 8 ),
01151         FT_FRAME_BYTES ( FileName, 6 ),
01152         FT_FRAME_CHAR  ( StrokeWeight ),
01153         FT_FRAME_CHAR  ( WidthType ),
01154         FT_FRAME_BYTE  ( SerifStyle ),
01155         FT_FRAME_BYTE  ( Reserved ),
01156       FT_FRAME_END
01157     };
01158 
01159     FT_Error  error;
01160     TT_PCLT*  pclt = &face->pclt;
01161 
01162 
01163     /* optional table */
01164     error = face->goto_table( face, TTAG_PCLT, stream, 0 );
01165     if ( error )
01166       goto Exit;
01167 
01168     if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
01169       goto Exit;
01170 
01171   Exit:
01172     return error;
01173   }
01174 
01175 
01176   /*************************************************************************/
01177   /*                                                                       */
01178   /* <Function>                                                            */
01179   /*    tt_face_load_gasp                                                  */
01180   /*                                                                       */
01181   /* <Description>                                                         */
01182   /*    Loads the `gasp' table into a face object.                         */
01183   /*                                                                       */
01184   /* <Input>                                                               */
01185   /*    face   :: A handle to the target face object.                      */
01186   /*                                                                       */
01187   /*    stream :: The input stream.                                        */
01188   /*                                                                       */
01189   /* <Return>                                                              */
01190   /*    FreeType error code.  0 means success.                             */
01191   /*                                                                       */
01192   FT_LOCAL_DEF( FT_Error )
01193   tt_face_load_gasp( TT_Face    face,
01194                      FT_Stream  stream )
01195   {
01196     FT_Error   error;
01197     FT_Memory  memory = stream->memory;
01198 
01199     FT_UInt        j,num_ranges;
01200     TT_GaspRange   gaspranges;
01201 
01202 
01203     /* the gasp table is optional */
01204     error = face->goto_table( face, TTAG_gasp, stream, 0 );
01205     if ( error )
01206       goto Exit;
01207 
01208     if ( FT_FRAME_ENTER( 4L ) )
01209       goto Exit;
01210 
01211     face->gasp.version   = FT_GET_USHORT();
01212     face->gasp.numRanges = FT_GET_USHORT();
01213 
01214     FT_FRAME_EXIT();
01215 
01216     /* only support versions 0 and 1 of the table */
01217     if ( face->gasp.version >= 2 )
01218     {
01219       face->gasp.numRanges = 0;
01220       error = SFNT_Err_Invalid_Table;
01221       goto Exit;
01222     }
01223 
01224     num_ranges = face->gasp.numRanges;
01225     FT_TRACE3(( "numRanges: %u\n", num_ranges ));
01226 
01227     if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) ||
01228          FT_FRAME_ENTER( num_ranges * 4L )      )
01229       goto Exit;
01230 
01231     face->gasp.gaspRanges = gaspranges;
01232 
01233     for ( j = 0; j < num_ranges; j++ )
01234     {
01235       gaspranges[j].maxPPEM  = FT_GET_USHORT();
01236       gaspranges[j].gaspFlag = FT_GET_USHORT();
01237 
01238       FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n",
01239                   j,
01240                   gaspranges[j].maxPPEM,
01241                   gaspranges[j].gaspFlag ));
01242     }
01243 
01244     FT_FRAME_EXIT();
01245 
01246   Exit:
01247     return error;
01248   }
01249 
01250 
01251 /* END */

Generated on Tue Jul 5 14:13:51 2011 for ROOT_528-00b_version by  doxygen 1.5.1