/[freetype]/freetype2/src/sfnt/ttload.c
ViewVC logotype

Diff of /freetype2/src/sfnt/ttload.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.119 by wl, Fri Nov 18 08:23:06 2005 UTC revision 1.120 by olvaffe, Sun Nov 20 08:24:24 2005 UTC
# Line 151  Line 151 
151    /* Type 42 fonts, and will generally be invalid.                         */    /* Type 42 fonts, and will generally be invalid.                         */
152    /*                                                                       */    /*                                                                       */
153    static FT_Error    static FT_Error
154    sfnt_dir_check( FT_Stream  stream,    sfnt_dir_check( SFNT_Header  sfnt,
155                    FT_ULong   offset,                    FT_Stream    stream )
156                    FT_UInt    num_tables )    {
    {  
157      FT_Error        error;      FT_Error        error;
158      FT_UInt         nn;      FT_UInt         nn;
159      FT_UInt         has_head = 0, has_sing = 0, has_meta = 0;      FT_UInt         has_head = 0, has_sing = 0, has_meta = 0;
160        FT_ULong        offset = sfnt->offset + 12;
161    
162      const FT_ULong  glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' );      const FT_ULong  glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' );
163      const FT_ULong  locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' );      const FT_ULong  locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' );
# Line 176  Line 176 
176      };      };
177    
178    
179      /* if 'num_tables' is 0, read the table count from the file */      if ( sfnt->num_tables == 0 ||
180      if ( num_tables == 0 )           offset + sfnt->num_tables * 16 > stream->size )
181      {        return SFNT_Err_Unknown_File_Format;
       if ( FT_STREAM_SEEK( offset )     ||  
            FT_STREAM_SKIP( 4 )          ||  
            FT_READ_USHORT( num_tables ) ||  
            FT_STREAM_SKIP( 6 )          )  
         goto Bad_Format;  
182    
183        if ( offset + 12 + num_tables*16 > stream->size )      if ( FT_STREAM_SEEK( offset ) )
184          goto Bad_Format;        return error;
     }  
     else if ( FT_STREAM_SEEK( offset + 12 ) )  
       goto Bad_Format;  
185    
186      for ( nn = 0; nn < num_tables; nn++ )      for ( nn = 0; nn < sfnt->num_tables; nn++ )
187      {      {
188        TT_TableRec  table;        TT_TableRec  table;
189    
190    
191        if ( FT_STREAM_READ_FIELDS( sfnt_dir_entry_fields, &table ) )        if ( FT_STREAM_READ_FIELDS( sfnt_dir_entry_fields, &table ) )
192          goto Bad_Format;          return error;
193    
194        if ( table.Offset + table.Length > stream->size     &&        if ( table.Offset + table.Length > stream->size     &&
195             table.Tag != glyx_tag && table.Tag != locx_tag )             table.Tag != glyx_tag && table.Tag != locx_tag )
196          goto Bad_Format;          return SFNT_Err_Unknown_File_Format;
197    
198        if ( table.Tag == TTAG_head )        if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed )
199        {        {
200          FT_UInt32  magic;          FT_UInt32  magic;
201    
202    #ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
203  #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS          if ( table.Tag == TTAG_head )
204        head_retry:  #endif
205  #endif  /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */            has_head = 1;
   
         has_head = 1;  
206    
207          /* The table length should be 0x36, but certain font tools          /* The table length should be 0x36, but certain font tools
208           * make it 0x38, so we will just check that it is greater.           * make it 0x38, so we will just check that it is greater.
# Line 221  Line 211 
211           * the table must be padded to 32-bit lengths, but this doesn't           * the table must be padded to 32-bit lengths, but this doesn't
212           * apply to the value of its "Length" field!           * apply to the value of its "Length" field!
213           */           */
214          if ( table.Length < 0x36                 ||          if ( table.Length < 0x36 )
215               FT_STREAM_SEEK( table.Offset + 12 ) ||            return SFNT_Err_Unknown_File_Format;
              FT_READ_ULONG( magic )              ||  
              magic != 0x5F0F3CF5UL               )  
           goto Bad_Format;  
216    
217          if ( FT_STREAM_SEEK( offset + 28 + 16*nn ) )          if ( FT_STREAM_SEEK( table.Offset + 12 ) ||
218            goto Bad_Format;               FT_READ_ULONG( magic ) )
219        }            return error;
220    
221  #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS          if ( magic != 0x5F0F3CF5UL )
222        else if ( table.Tag == TTAG_bhed )            return SFNT_Err_Unknown_File_Format;
         goto head_retry;  
 #endif  /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */        
223    
224            if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )
225              return error;
226          }
227        else if ( table.Tag == TTAG_SING )        else if ( table.Tag == TTAG_SING )
228          has_sing = 1;          has_sing = 1;
229        else if ( table.Tag == TTAG_META )        else if ( table.Tag == TTAG_META )
230          has_meta = 1;          has_meta = 1;
231      }      }
232    
233      /* when sing and meta are present, head is not present */      if ( has_head || ( has_sing && has_meta ) )
234      if ( has_sing && has_meta && has_head == 0 )        return SFNT_Err_Ok;
235          goto Exit;      else
236          return SFNT_Err_Unknown_File_Format;
237      /* otherwise, treat a missing head as a failure */    }
     if ( has_head == 0 )  
       goto Bad_Format;  
238    
   Exit:  
     return error;  
239    
240    Bad_Format:    /* Fill in face->ttc_header.  If the font is not a TTC, it is            */
241      error = SFNT_Err_Unknown_File_Format;    /* synthesized into a TTC with one offset table.                         */
242      goto Exit;    static FT_Error
243      sfnt_init( FT_Stream  stream,
244                 TT_Face    face )
245      {
246        FT_Memory  memory = stream->memory;
247        FT_Error   error;
248        FT_ULong   tag, offset;
249    
250        static const FT_Frame_Field  ttc_header_fields[] =
251        {
252    #undef  FT_STRUCTURE
253    #define FT_STRUCTURE  TTC_HeaderRec
254    
255          FT_FRAME_START( 8 ),
256            FT_FRAME_LONG( version ),
257            FT_FRAME_LONG( count   ),
258          FT_FRAME_END
259        };
260    
261        face->ttc_header.tag = 0;
262        face->ttc_header.version = 0;
263        face->ttc_header.count = 0;
264    
265        offset = FT_STREAM_POS();
266    
267        if ( FT_READ_ULONG( tag ) )
268          return error;
269    
270        face->ttc_header.tag = TTAG_ttcf;
271    
272        if ( tag == TTAG_ttcf )
273        {
274          FT_Int  n;
275    
276    
277          FT_TRACE3(( "sfnt_init: file is a collection\n" ));
278    
279          if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
280            return error;
281    
282          /* now read the offsets of each font in the file */
283          if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
284            return error;
285    
286          if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
287            return error;
288    
289          for ( n = 0; n < face->ttc_header.count; n++ )
290            face->ttc_header.offsets[n] = FT_GET_ULONG();
291    
292          FT_FRAME_EXIT();
293        }
294        else
295        {
296          face->ttc_header.version = 1 << 16;
297          face->ttc_header.count = 1;
298    
299          if ( FT_NEW( face->ttc_header.offsets) )
300            return error;
301    
302          face->ttc_header.offsets[0] = offset;
303        }
304    
305        return error;
306    }    }
307    
308    
# Line 295  Line 342 
342                              FT_Long      face_index,                              FT_Long      face_index,
343                              SFNT_Header  sfnt )                              SFNT_Header  sfnt )
344    {    {
345      FT_Error   error;      FT_Error  error;
     FT_ULong   font_format_tag, format_tag, offset;  
     FT_Memory  memory = stream->memory;  
346    
347      static const FT_Frame_Field  sfnt_header_fields[] =      static const FT_Frame_Field  sfnt_header_fields[] =
348      {      {
# Line 312  Line 357 
357        FT_FRAME_END        FT_FRAME_END
358      };      };
359    
     static const FT_Frame_Field  ttc_header_fields[] =  
     {  
 #undef  FT_STRUCTURE  
 #define FT_STRUCTURE  TTC_HeaderRec  
   
       FT_FRAME_START( 8 ),  
         FT_FRAME_LONG( version ),  
         FT_FRAME_LONG( count   ),  
       FT_FRAME_END  
     };  
   
360    
361      FT_TRACE2(( "tt_face_load_sfnt_header: %08p, %ld\n",      FT_TRACE2(( "tt_face_load_sfnt_header: %08p, %ld\n",
362                  face, face_index ));                  face, face_index ));
363    
364      face->ttc_header.tag     = 0;      error = sfnt_init( stream, face );
365      face->ttc_header.version = 0;      if ( error )
366      face->ttc_header.count   = 0;        return error;
   
     face->num_tables = 0;  
   
     /* First of all, read the first 4 bytes.  If it is `ttcf', then the   */  
     /* file is a TrueType collection, otherwise it is a single-face font. */  
     /*                                                                    */  
     offset = FT_STREAM_POS();  
   
     if ( FT_READ_ULONG( font_format_tag ) )  
       goto Exit;  
   
     format_tag = font_format_tag;  
   
     if ( font_format_tag == TTAG_ttcf )  
     {  
       FT_Int  n;  
   
   
       FT_TRACE3(( "tt_face_load_sfnt_header: file is a collection\n" ));  
   
       /* It is a TrueType collection, i.e. a file containing several */  
       /* font files.  Read the font directory now                    */  
       if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )  
         goto Exit;  
   
       /* now read the offsets of each font in the file */  
       if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ||  
            FT_FRAME_ENTER( face->ttc_header.count * 4L )                    )  
         goto Exit;  
   
       for ( n = 0; n < face->ttc_header.count; n++ )  
         face->ttc_header.offsets[n] = FT_GET_ULONG();  
367    
368        FT_FRAME_EXIT();      if ( face_index < 0 )
369          face_index = 0;
370    
371        /* check face index */      if ( face_index >= face->ttc_header.count )
372        if ( face_index >= face->ttc_header.count )          return SFNT_Err_Bad_Argument;
       {  
         error = SFNT_Err_Bad_Argument;  
         goto Exit;  
       }  
373    
374        /* seek to the appropriate TrueType file, then read tag */      sfnt->offset = face->ttc_header.offsets[face_index];
       offset = face->ttc_header.offsets[face_index];  
375    
376        if ( FT_STREAM_SEEK( offset )   ||      if ( FT_STREAM_SEEK( sfnt->offset ) )
377             FT_READ_LONG( format_tag ) )        return error;
         goto Exit;  
     }  
   
     /* the format tag was read, now check the rest of the header */  
     sfnt->format_tag = format_tag;  
     sfnt->offset     = offset;  
378    
379      if ( FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) )      /* read offset table */
380        goto Exit;      if ( FT_READ_ULONG( sfnt->format_tag ) ||
381             FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) )
382          return error;
383    
384      /* now check the sfnt directory */      /* now check the sfnt directory */
385      error = sfnt_dir_check( stream, offset, sfnt->num_tables );      error = sfnt_dir_check( sfnt, stream );
386      if ( error )      if ( error )
387      {        FT_TRACE2(( "tt_face_load_sfnt_header: invalid SFNT!\n" ));
       FT_TRACE2(( "tt_face_load_sfnt_header: file is not SFNT!\n" ));  
       error = SFNT_Err_Unknown_File_Format;  
       goto Exit;  
     }  
   
     /* disallow face index values > 0 for non-TTC files */  
     if ( font_format_tag != TTAG_ttcf && face_index > 0 )  
       error = SFNT_Err_Bad_Argument;  
388    
   Exit:  
389      return error;      return error;
390    }    }
391    

Legend:
Removed from v.1.119  
changed lines
  Added in v.1.120

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26