* src/sfnt/ttload.c, src/sfnt/ttload.h, src/sfnt/ttdriver.c: changing

the SFNT loader to check for SFNT-based font files differently. We now
    ignore the range "helper" fields and check the "head" table's magic
    number instead.
This commit is contained in:
David Turner 2002-07-11 23:41:14 +00:00
parent 2ade80c8e9
commit 0f20eb2e5d
7 changed files with 126 additions and 33 deletions

View File

@ -1,9 +1,17 @@
2002-07-11 David Turner <david@freetype.org>
* src/sfnt/ttload.c, src/sfnt/ttload.h, src/sfnt/ttdriver.c: changing
the SFNT loader to check for SFNT-based font files differently. We now
ignore the range "helper" fields and check the "head" table's magic
number instead.
* src/base/ftobject.c, src/base/fthash.c: updated object sub-system and
dynamic hash table implementation (still experimental, don't use)
* include/freetype/t1tables.h, include/freetype/internal/psaux.h,
src/psaux/psobjs.c, src/type1/t1load.c, src/type1/t1tokens.h:
fixing a bug in the Type 1 loader that prevented valid font bounding
boxes to be loaded from multiple master fonts.
boxes to be loaded from multiple master fonts.
2002-07-10 David Turner <david@freetype.org>

View File

@ -100,6 +100,8 @@ FT_BEGIN_HEADER
FT_UShort entry_selector;
FT_UShort range_shift;
FT_ULong offset; /* not in file */
} SFNT_HeaderRec, *SFNT_Header;

View File

@ -197,7 +197,7 @@
num_buckets = ( table->p + table->mask + 1) ;
if ( ++ table->slack > num_buckets*FT_HASH_SUB_LOAD )
if ( ++ table->slack > (FT_Long)num_buckets*FT_HASH_SUB_LOAD )
{
FT_UInt p = table->p;
FT_UInt mask = table->mask;

View File

@ -312,6 +312,7 @@
return (clazz == NULL);
}
return 0;
}

View File

@ -251,7 +251,7 @@
SFNT_Get_Interface,
TT_Load_Any,
TT_Load_SFNT_HeaderRec,
TT_Load_SFNT_Header,
TT_Load_Directory,
TT_Load_Header,

View File

@ -135,6 +135,91 @@
}
/* in theory, we should check the values of `search_range', */
/* `entry_selector' and `range_shift' to detect non-SFNT based files */
/* whose header might also start with 0x100000L (yes, these exist). */
/* */
/* Very unfortunately, many TrueType fonts don't have these fields */
/* set correctly and we must ignore them to support them. An alternative */
/* way to check the font file is thus to: */
/* */
/* - check that `num_tables' is valid */
/* - look for a "head" table, check its size, and parse it to */
/* see if its "magic" field is correctly set to */
/* */
/* Voila, here comes robust though tolerant font format checking :-) */
/* */
static FT_Error
sfnt_dir_check( FT_Stream stream,
FT_ULong offset,
FT_UInt num_tables )
{
FT_Error error;
FT_UInt nn;
static const FT_Frame_Field sfnt_dir_entry_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE TT_TableRec
FT_FRAME_START( 16 ),
FT_FRAME_ULONG( Tag ),
FT_FRAME_ULONG( CheckSum ),
FT_FRAME_ULONG( Offset ),
FT_FRAME_ULONG( Length ),
FT_FRAME_END
};
/* if 'num_tables' is 0, read the table count from the file */
if ( num_tables == 0 )
{
FT_ULong format_tag;
if ( FT_STREAM_SEEK( offset ) ||
FT_READ_ULONG ( format_tag ) ||
FT_READ_USHORT( num_tables ) ||
FT_STREAM_SKIP( 6 ) )
goto Bad_Format;
if ( offset + 12 + num_tables*16 > stream->size )
goto Bad_Format;
}
else if ( FT_STREAM_SEEK( offset + 12 ) )
goto Bad_Format;
for ( nn = 0; nn < num_tables; nn++ )
{
TT_TableRec table;
if ( FT_STREAM_READ_FIELDS( sfnt_dir_entry_fields, &table ) )
goto Bad_Format;
if ( offset + table.Offset + table.Length > stream->size )
goto Bad_Format;
if ( table.Tag == TTAG_head )
{
FT_UInt32 magic;
if ( table.Length != 0x36 ||
FT_STREAM_SEEK( offset + table.Offset + 12 ) ||
FT_READ_ULONG( magic ) ||
magic != 0x5F0F3CF5U )
goto Bad_Format;
if ( FT_STREAM_SEEK( offset + 28 + 16*nn ) )
goto Bad_Format;
}
}
Exit:
return error;
Bad_Format:
error = FT_Err_Unknown_File_Format;
goto Exit;
}
/*************************************************************************/
/* */
/* <Function> */
@ -166,16 +251,16 @@
/* values of `search_range', `entry_selector', and `range_shift'. */
/* */
FT_LOCAL_DEF( FT_Error )
TT_Load_SFNT_HeaderRec( TT_Face face,
FT_Stream stream,
FT_Long face_index,
SFNT_Header sfnt )
TT_Load_SFNT_Header( TT_Face face,
FT_Stream stream,
FT_Long face_index,
SFNT_Header sfnt )
{
FT_Error error;
FT_ULong format_tag;
FT_ULong format_tag, offset;
FT_Memory memory = stream->memory;
const FT_Frame_Field sfnt_header_fields[] =
static const FT_Frame_Field sfnt_header_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE SFNT_HeaderRec
@ -188,7 +273,7 @@
FT_FRAME_END
};
const FT_Frame_Field ttc_header_fields[] =
static const FT_Frame_Field ttc_header_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE TTC_HeaderRec
@ -200,7 +285,7 @@
};
FT_TRACE2(( "TT_Load_SFNT_HeaderRec: %08p, %ld\n",
FT_TRACE2(( "TT_Load_SFNT_Header: %08p, %ld\n",
face, face_index ));
face->ttc_header.tag = 0;
@ -213,6 +298,8 @@
/* file is a TrueType collection, otherwise it can be any other */
/* kind of font. */
/* */
offset = FT_STREAM_POS();
if ( FT_READ_ULONG( format_tag ) )
goto Exit;
@ -221,7 +308,7 @@
FT_Int n;
FT_TRACE3(( "TT_Load_SFNT_HeaderRec: file is a collection\n" ));
FT_TRACE3(( "TT_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 */
@ -246,32 +333,26 @@
}
/* seek to the appropriate TrueType file, then read tag */
if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ||
offset = face->ttc_header.offsets[ face_index ];
if ( FT_STREAM_SEEK( offset ) ||
FT_READ_LONG( format_tag ) )
goto Exit;
}
/* the format tag was read, now check the rest of the header */
sfnt->format_tag = format_tag;
sfnt->offset = offset;
if ( FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) )
goto Exit;
/* now, check the values of `num_tables', `seach_range', etc. */
/* now check the sfnt directory */
error = sfnt_dir_check( stream, offset, sfnt->num_tables );
if ( error )
{
FT_UInt num_tables = sfnt->num_tables;
FT_ULong entry_selector = 1L << sfnt->entry_selector;
/* IMPORTANT: Many fonts have an incorrect `search_range' value, so */
/* we only check the `entry_selector' correctness here. */
/* */
if ( num_tables == 0 ||
entry_selector > num_tables ||
entry_selector * 2 <= num_tables )
{
FT_TRACE2(( "TT_Load_SFNT_HeaderRec: file is not SFNT!\n" ));
error = SFNT_Err_Unknown_File_Format;
}
FT_TRACE2(( "TT_Load_SFNT_Header: file is not SFNT!\n" ));
error = SFNT_Err_Unknown_File_Format;
}
Exit:
@ -322,7 +403,8 @@
if ( FT_NEW_ARRAY( face->dir_tables, face->num_tables ) )
goto Exit;
if ( FT_FRAME_ENTER( face->num_tables * 16L ) )
if ( FT_STREAM_SEEK( sfnt->offset + 12 ) ||
FT_FRAME_ENTER( face->num_tables * 16L ) )
goto Exit;
entry = face->dir_tables;

View File

@ -41,10 +41,10 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Error )
TT_Load_SFNT_HeaderRec( TT_Face face,
FT_Stream stream,
FT_Long face_index,
SFNT_Header sfnt );
TT_Load_SFNT_Header( TT_Face face,
FT_Stream stream,
FT_Long face_index,
SFNT_Header sfnt );
FT_LOCAL( FT_Error )
TT_Load_Directory( TT_Face face,