* 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:
parent
660138753b
commit
7acd73fd6a
|
@ -1,5 +1,13 @@
|
||||||
2002-07-11 David Turner <david@freetype.org>
|
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,
|
* include/freetype/t1tables.h, include/freetype/internal/psaux.h,
|
||||||
src/psaux/psobjs.c, src/type1/t1load.c, src/type1/t1tokens.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
|
fixing a bug in the Type 1 loader that prevented valid font bounding
|
||||||
|
|
|
@ -100,6 +100,8 @@ FT_BEGIN_HEADER
|
||||||
FT_UShort entry_selector;
|
FT_UShort entry_selector;
|
||||||
FT_UShort range_shift;
|
FT_UShort range_shift;
|
||||||
|
|
||||||
|
FT_ULong offset; /* not in file */
|
||||||
|
|
||||||
} SFNT_HeaderRec, *SFNT_Header;
|
} SFNT_HeaderRec, *SFNT_Header;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -197,7 +197,7 @@
|
||||||
|
|
||||||
num_buckets = ( table->p + table->mask + 1) ;
|
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 p = table->p;
|
||||||
FT_UInt mask = table->mask;
|
FT_UInt mask = table->mask;
|
||||||
|
|
|
@ -312,6 +312,7 @@
|
||||||
|
|
||||||
return (clazz == NULL);
|
return (clazz == NULL);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -251,7 +251,7 @@
|
||||||
SFNT_Get_Interface,
|
SFNT_Get_Interface,
|
||||||
|
|
||||||
TT_Load_Any,
|
TT_Load_Any,
|
||||||
TT_Load_SFNT_HeaderRec,
|
TT_Load_SFNT_Header,
|
||||||
TT_Load_Directory,
|
TT_Load_Directory,
|
||||||
|
|
||||||
TT_Load_Header,
|
TT_Load_Header,
|
||||||
|
|
|
@ -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> */
|
/* <Function> */
|
||||||
|
@ -166,16 +251,16 @@
|
||||||
/* values of `search_range', `entry_selector', and `range_shift'. */
|
/* values of `search_range', `entry_selector', and `range_shift'. */
|
||||||
/* */
|
/* */
|
||||||
FT_LOCAL_DEF( FT_Error )
|
FT_LOCAL_DEF( FT_Error )
|
||||||
TT_Load_SFNT_HeaderRec( TT_Face face,
|
TT_Load_SFNT_Header( TT_Face face,
|
||||||
FT_Stream stream,
|
FT_Stream stream,
|
||||||
FT_Long face_index,
|
FT_Long face_index,
|
||||||
SFNT_Header sfnt )
|
SFNT_Header sfnt )
|
||||||
{
|
{
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
FT_ULong format_tag;
|
FT_ULong format_tag, offset;
|
||||||
FT_Memory memory = stream->memory;
|
FT_Memory memory = stream->memory;
|
||||||
|
|
||||||
const FT_Frame_Field sfnt_header_fields[] =
|
static const FT_Frame_Field sfnt_header_fields[] =
|
||||||
{
|
{
|
||||||
#undef FT_STRUCTURE
|
#undef FT_STRUCTURE
|
||||||
#define FT_STRUCTURE SFNT_HeaderRec
|
#define FT_STRUCTURE SFNT_HeaderRec
|
||||||
|
@ -188,7 +273,7 @@
|
||||||
FT_FRAME_END
|
FT_FRAME_END
|
||||||
};
|
};
|
||||||
|
|
||||||
const FT_Frame_Field ttc_header_fields[] =
|
static const FT_Frame_Field ttc_header_fields[] =
|
||||||
{
|
{
|
||||||
#undef FT_STRUCTURE
|
#undef FT_STRUCTURE
|
||||||
#define FT_STRUCTURE TTC_HeaderRec
|
#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, face_index ));
|
||||||
|
|
||||||
face->ttc_header.tag = 0;
|
face->ttc_header.tag = 0;
|
||||||
|
@ -213,6 +298,8 @@
|
||||||
/* file is a TrueType collection, otherwise it can be any other */
|
/* file is a TrueType collection, otherwise it can be any other */
|
||||||
/* kind of font. */
|
/* kind of font. */
|
||||||
/* */
|
/* */
|
||||||
|
offset = FT_STREAM_POS();
|
||||||
|
|
||||||
if ( FT_READ_ULONG( format_tag ) )
|
if ( FT_READ_ULONG( format_tag ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
@ -221,7 +308,7 @@
|
||||||
FT_Int n;
|
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 */
|
/* It is a TrueType collection, i.e. a file containing several */
|
||||||
/* font files. Read the font directory now */
|
/* font files. Read the font directory now */
|
||||||
|
@ -246,33 +333,27 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* seek to the appropriate TrueType file, then read tag */
|
/* 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 ) )
|
FT_READ_LONG( format_tag ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the format tag was read, now check the rest of the header */
|
/* the format tag was read, now check the rest of the header */
|
||||||
sfnt->format_tag = format_tag;
|
sfnt->format_tag = format_tag;
|
||||||
|
sfnt->offset = offset;
|
||||||
|
|
||||||
if ( FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) )
|
if ( FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) )
|
||||||
goto Exit;
|
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_TRACE2(( "TT_Load_SFNT_Header: file is not SFNT!\n" ));
|
||||||
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;
|
error = SFNT_Err_Unknown_File_Format;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Exit:
|
Exit:
|
||||||
return error;
|
return error;
|
||||||
|
@ -322,7 +403,8 @@
|
||||||
if ( FT_NEW_ARRAY( face->dir_tables, face->num_tables ) )
|
if ( FT_NEW_ARRAY( face->dir_tables, face->num_tables ) )
|
||||||
goto Exit;
|
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;
|
goto Exit;
|
||||||
|
|
||||||
entry = face->dir_tables;
|
entry = face->dir_tables;
|
||||||
|
|
|
@ -41,7 +41,7 @@ FT_BEGIN_HEADER
|
||||||
|
|
||||||
|
|
||||||
FT_LOCAL( FT_Error )
|
FT_LOCAL( FT_Error )
|
||||||
TT_Load_SFNT_HeaderRec( TT_Face face,
|
TT_Load_SFNT_Header( TT_Face face,
|
||||||
FT_Stream stream,
|
FT_Stream stream,
|
||||||
FT_Long face_index,
|
FT_Long face_index,
|
||||||
SFNT_Header sfnt );
|
SFNT_Header sfnt );
|
||||||
|
|
Loading…
Reference in New Issue