[sfnt] Don't provide (completely) broken strike data.
FreeType tries to sanitize strike header data; we now reject completely broken ones. * include/freetype/internal/tttypes.h (TT_FaceRec): New `sbit_strike_map' array pointer. * src/base/ftobjs.c (FT_Match_Size): Reject matches where either width or height would be zero. Add tracing message in case of error. * src/sfnt/sfobjs.c (sfnt_load_face): Populate `sbit_strike_map', only using (more or less) valid strike header data for FT_Face's `available_sizes' array. (sfnt_done_face): Updated. * src/sfnt/ttsbit.c (tt_face_set_sbit_strike): Use `sbit_strike_map'. (tt_face_load_strike_metrics): Improve tracing. * src/truetype/ttdriver.c (tt_size_select): Use `sbit_strike_map'.
This commit is contained in:
parent
d2d5968aed
commit
d609b7c158
25
ChangeLog
25
ChangeLog
|
@ -1,3 +1,28 @@
|
||||||
|
2016-09-09 Werner Lemberg <wl@gnu.org>
|
||||||
|
|
||||||
|
[sfnt] Don't provide (completely) broken strike data.
|
||||||
|
|
||||||
|
FreeType tries to sanitize strike header data; we now reject
|
||||||
|
completely broken ones.
|
||||||
|
|
||||||
|
* include/freetype/internal/tttypes.h (TT_FaceRec): New
|
||||||
|
`sbit_strike_map' array pointer.
|
||||||
|
|
||||||
|
* src/base/ftobjs.c (FT_Match_Size): Reject matches where either
|
||||||
|
width or height would be zero.
|
||||||
|
Add tracing message in case of error.
|
||||||
|
|
||||||
|
* src/sfnt/sfobjs.c (sfnt_load_face): Populate `sbit_strike_map',
|
||||||
|
only using (more or less) valid strike header data for
|
||||||
|
FT_Face's `available_sizes' array.
|
||||||
|
(sfnt_done_face): Updated.
|
||||||
|
|
||||||
|
* src/sfnt/ttsbit.c (tt_face_set_sbit_strike): Use
|
||||||
|
`sbit_strike_map'.
|
||||||
|
(tt_face_load_strike_metrics): Improve tracing.
|
||||||
|
|
||||||
|
* src/truetype/ttdriver.c (tt_size_select): Use `sbit_strike_map'.
|
||||||
|
|
||||||
2016-09-08 Werner Lemberg <wl@gnu.org>
|
2016-09-08 Werner Lemberg <wl@gnu.org>
|
||||||
|
|
||||||
* Version 2.7 released.
|
* Version 2.7 released.
|
||||||
|
|
|
@ -951,6 +951,10 @@ FT_BEGIN_HEADER
|
||||||
/* strikes in the face. It is set to NULL if */
|
/* strikes in the face. It is set to NULL if */
|
||||||
/* there is no bitmap strike. */
|
/* there is no bitmap strike. */
|
||||||
/* */
|
/* */
|
||||||
|
/* Note that FreeType tries to sanitize the */
|
||||||
|
/* strike data since they are sometimes sloppy */
|
||||||
|
/* or incorrect, but this can easily fail. */
|
||||||
|
/* */
|
||||||
/* num_charmaps :: The number of charmaps in the face. */
|
/* num_charmaps :: The number of charmaps in the face. */
|
||||||
/* */
|
/* */
|
||||||
/* charmaps :: An array of the charmaps of the face. */
|
/* charmaps :: An array of the charmaps of the face. */
|
||||||
|
|
|
@ -1371,6 +1371,7 @@ FT_BEGIN_HEADER
|
||||||
FT_ULong sbit_table_size;
|
FT_ULong sbit_table_size;
|
||||||
TT_SbitTableType sbit_table_type;
|
TT_SbitTableType sbit_table_type;
|
||||||
FT_UInt sbit_num_strikes;
|
FT_UInt sbit_num_strikes;
|
||||||
|
FT_UInt* sbit_strike_map;
|
||||||
|
|
||||||
FT_Byte* kern_table;
|
FT_Byte* kern_table;
|
||||||
FT_ULong kern_table_size;
|
FT_ULong kern_table_size;
|
||||||
|
|
|
@ -2631,6 +2631,9 @@
|
||||||
w = FT_PIX_ROUND( w );
|
w = FT_PIX_ROUND( w );
|
||||||
h = FT_PIX_ROUND( h );
|
h = FT_PIX_ROUND( h );
|
||||||
|
|
||||||
|
if ( !w || !h )
|
||||||
|
return FT_THROW( Invalid_Pixel_Size );
|
||||||
|
|
||||||
for ( i = 0; i < face->num_fixed_sizes; i++ )
|
for ( i = 0; i < face->num_fixed_sizes; i++ )
|
||||||
{
|
{
|
||||||
FT_Bitmap_Size* bsize = face->available_sizes + i;
|
FT_Bitmap_Size* bsize = face->available_sizes + i;
|
||||||
|
@ -2650,6 +2653,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_TRACE3(( "FT_Match_Size: no matching bitmap strike\n" ));
|
||||||
|
|
||||||
return FT_THROW( Invalid_Pixel_Size );
|
return FT_THROW( Invalid_Pixel_Size );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1411,7 +1411,7 @@
|
||||||
* depths in the FT_Bitmap_Size record. This is a design error.
|
* depths in the FT_Bitmap_Size record. This is a design error.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
FT_UInt i, count;
|
FT_UInt count;
|
||||||
|
|
||||||
|
|
||||||
count = face->sbit_num_strikes;
|
count = face->sbit_num_strikes;
|
||||||
|
@ -1423,6 +1423,8 @@
|
||||||
FT_Short avgwidth = face->os2.xAvgCharWidth;
|
FT_Short avgwidth = face->os2.xAvgCharWidth;
|
||||||
FT_Size_Metrics metrics;
|
FT_Size_Metrics metrics;
|
||||||
|
|
||||||
|
FT_UInt strike_idx, bsize_idx;
|
||||||
|
|
||||||
|
|
||||||
if ( em_size == 0 || face->os2.version == 0xFFFFU )
|
if ( em_size == 0 || face->os2.version == 0xFFFFU )
|
||||||
{
|
{
|
||||||
|
@ -1430,31 +1432,43 @@
|
||||||
em_size = 1;
|
em_size = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( FT_NEW_ARRAY( root->available_sizes, count ) )
|
/* to avoid invalid strike data in the `available_sizes' field */
|
||||||
|
/* of `FT_Face', we map `available_sizes' indices to strike */
|
||||||
|
/* indices */
|
||||||
|
if ( FT_NEW_ARRAY( root->available_sizes, count ) ||
|
||||||
|
FT_NEW_ARRAY( face->sbit_strike_map, count ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
for ( i = 0; i < count; i++ )
|
bsize_idx = 0;
|
||||||
|
for ( strike_idx = 0; strike_idx < count; strike_idx++ )
|
||||||
{
|
{
|
||||||
FT_Bitmap_Size* bsize = root->available_sizes + i;
|
FT_Bitmap_Size* bsize = root->available_sizes + bsize_idx;
|
||||||
|
|
||||||
|
|
||||||
error = sfnt->load_strike_metrics( face, i, &metrics );
|
error = sfnt->load_strike_metrics( face, strike_idx, &metrics );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
bsize->height = (FT_Short)( metrics.height >> 6 );
|
bsize->height = (FT_Short)( metrics.height >> 6 );
|
||||||
bsize->width = (FT_Short)(
|
bsize->width = (FT_Short)(
|
||||||
( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
|
( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
|
||||||
|
|
||||||
bsize->x_ppem = metrics.x_ppem << 6;
|
bsize->x_ppem = metrics.x_ppem << 6;
|
||||||
bsize->y_ppem = metrics.y_ppem << 6;
|
bsize->y_ppem = metrics.y_ppem << 6;
|
||||||
|
|
||||||
/* assume 72dpi */
|
/* assume 72dpi */
|
||||||
bsize->size = metrics.y_ppem << 6;
|
bsize->size = metrics.y_ppem << 6;
|
||||||
|
|
||||||
|
/* only use strikes with valid PPEM values */
|
||||||
|
if ( bsize->x_ppem && bsize->y_ppem )
|
||||||
|
face->sbit_strike_map[bsize_idx++] = strike_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* reduce array size to the actually used elements */
|
||||||
|
(void)FT_RENEW_ARRAY( face->sbit_strike_map, count, bsize_idx );
|
||||||
|
|
||||||
root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
|
root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
|
||||||
root->num_fixed_sizes = (FT_Int)count;
|
root->num_fixed_sizes = (FT_Int)bsize_idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1648,6 +1662,7 @@
|
||||||
|
|
||||||
/* freeing sbit size table */
|
/* freeing sbit size table */
|
||||||
FT_FREE( face->root.available_sizes );
|
FT_FREE( face->root.available_sizes );
|
||||||
|
FT_FREE( face->sbit_strike_map );
|
||||||
face->root.num_fixed_sizes = 0;
|
face->root.num_fixed_sizes = 0;
|
||||||
|
|
||||||
FT_FREE( face->postscript_name );
|
FT_FREE( face->postscript_name );
|
||||||
|
|
|
@ -251,7 +251,14 @@
|
||||||
FT_Size_Request req,
|
FT_Size_Request req,
|
||||||
FT_ULong* astrike_index )
|
FT_ULong* astrike_index )
|
||||||
{
|
{
|
||||||
return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
|
FT_Error error;
|
||||||
|
|
||||||
|
|
||||||
|
error = FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
|
||||||
|
if ( !error )
|
||||||
|
*astrike_index = face->sbit_strike_map[*astrike_index];
|
||||||
|
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -305,7 +312,8 @@
|
||||||
FT_TRACE2(( "tt_face_load_strike_metrics:"
|
FT_TRACE2(( "tt_face_load_strike_metrics:"
|
||||||
" sanitizing invalid ascender and descender\n"
|
" sanitizing invalid ascender and descender\n"
|
||||||
" "
|
" "
|
||||||
" values for strike (%d, %d)\n",
|
" values for strike %d (%dppem, %dppem)\n",
|
||||||
|
strike_index,
|
||||||
metrics->x_ppem, metrics->y_ppem ));
|
metrics->x_ppem, metrics->y_ppem ));
|
||||||
|
|
||||||
/* sanitize buggy ascender and descender values */
|
/* sanitize buggy ascender and descender values */
|
||||||
|
|
|
@ -273,25 +273,27 @@
|
||||||
|
|
||||||
static FT_Error
|
static FT_Error
|
||||||
tt_size_select( FT_Size size,
|
tt_size_select( FT_Size size,
|
||||||
FT_ULong strike_index )
|
FT_ULong bsize_index )
|
||||||
{
|
{
|
||||||
TT_Face ttface = (TT_Face)size->face;
|
TT_Face ttface = (TT_Face)size->face;
|
||||||
TT_Size ttsize = (TT_Size)size;
|
TT_Size ttsize = (TT_Size)size;
|
||||||
FT_Error error = FT_Err_Ok;
|
FT_Error error = FT_Err_Ok;
|
||||||
|
|
||||||
|
FT_UInt strike_index = ttface->sbit_strike_map[bsize_index];
|
||||||
|
|
||||||
|
|
||||||
ttsize->strike_index = strike_index;
|
ttsize->strike_index = strike_index;
|
||||||
|
|
||||||
if ( FT_IS_SCALABLE( size->face ) )
|
if ( FT_IS_SCALABLE( size->face ) )
|
||||||
{
|
{
|
||||||
/* use the scaled metrics, even when tt_size_reset fails */
|
/* use the scaled metrics, even when tt_size_reset fails */
|
||||||
FT_Select_Metrics( size->face, strike_index );
|
FT_Select_Metrics( size->face, bsize_index );
|
||||||
|
|
||||||
tt_size_reset( ttsize ); /* ignore return value */
|
tt_size_reset( ttsize ); /* ignore return value */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SFNT_Service sfnt = (SFNT_Service) ttface->sfnt;
|
SFNT_Service sfnt = (SFNT_Service)ttface->sfnt;
|
||||||
FT_Size_Metrics* metrics = &size->metrics;
|
FT_Size_Metrics* metrics = &size->metrics;
|
||||||
|
|
||||||
|
|
||||||
|
@ -319,7 +321,7 @@
|
||||||
if ( FT_HAS_FIXED_SIZES( size->face ) )
|
if ( FT_HAS_FIXED_SIZES( size->face ) )
|
||||||
{
|
{
|
||||||
TT_Face ttface = (TT_Face)size->face;
|
TT_Face ttface = (TT_Face)size->face;
|
||||||
SFNT_Service sfnt = (SFNT_Service) ttface->sfnt;
|
SFNT_Service sfnt = (SFNT_Service)ttface->sfnt;
|
||||||
FT_ULong strike_index;
|
FT_ULong strike_index;
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue