New base function `FT_Matrix_Check' (#54019).
* src/base/ftcalc.c (FT_Matrix_Check): New base function to properly reject degenerate font matrices. * include/freetype/internal/ftcalc.h: Updated. * src/cff/cffparse.c (cff_parse_font_matrix), src/cid/cidload.c (cid_parse_font_matrix), src/type1/t1load.c (t1_parse_font_matrix), src/type42/t42parse.c (t42_parse_font_matrix): Use `FT_Matrix_Check'.
This commit is contained in:
parent
d7393e22ee
commit
cc3333902b
14
ChangeLog
14
ChangeLog
@ -1,3 +1,17 @@
|
||||
2018-06-24 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
New base function `FT_Matrix_Check' (#54019).
|
||||
|
||||
* src/base/ftcalc.c (FT_Matrix_Check): New base function to properly
|
||||
reject degenerate font matrices.
|
||||
|
||||
* include/freetype/internal/ftcalc.h: Updated.
|
||||
|
||||
* src/cff/cffparse.c (cff_parse_font_matrix), src/cid/cidload.c
|
||||
(cid_parse_font_matrix), src/type1/t1load.c (t1_parse_font_matrix),
|
||||
src/type42/t42parse.c (t42_parse_font_matrix): Use
|
||||
`FT_Matrix_Check'.
|
||||
|
||||
2018-06-23 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
Fix typo.
|
||||
|
@ -292,6 +292,21 @@ FT_BEGIN_HEADER
|
||||
FT_Long scaling );
|
||||
|
||||
|
||||
/*
|
||||
* Check a matrix. If the transformation would lead to extreme shear or
|
||||
* extreme scaling, for example, return 0. If everything is OK, return 1.
|
||||
*
|
||||
* Based on geometric considerations we use the following inequality to
|
||||
* identify a degenerate matrix.
|
||||
*
|
||||
* 50 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2
|
||||
*
|
||||
* Value 50 is heuristic.
|
||||
*/
|
||||
FT_BASE( FT_Bool )
|
||||
FT_Matrix_Check( const FT_Matrix* matrix );
|
||||
|
||||
|
||||
/*
|
||||
* A variant of FT_Vector_Transform. See comments for
|
||||
* FT_Matrix_Multiply_Scaled.
|
||||
|
@ -745,6 +745,72 @@
|
||||
}
|
||||
|
||||
|
||||
/* documentation is in ftcalc.h */
|
||||
|
||||
FT_BASE_DEF( FT_Bool )
|
||||
FT_Matrix_Check( const FT_Matrix* matrix )
|
||||
{
|
||||
FT_Matrix m;
|
||||
FT_Fixed val[4];
|
||||
FT_Fixed nonzero_minval, maxval;
|
||||
FT_Fixed temp1, temp2;
|
||||
FT_UInt i;
|
||||
|
||||
|
||||
if ( !matrix )
|
||||
return 0;
|
||||
|
||||
val[0] = FT_ABS( matrix->xx );
|
||||
val[1] = FT_ABS( matrix->xy );
|
||||
val[2] = FT_ABS( matrix->yx );
|
||||
val[3] = FT_ABS( matrix->yy );
|
||||
|
||||
/*
|
||||
* To avoid overflow, we ensure that each value is not larger than
|
||||
*
|
||||
* int(sqrt(2^31 / 4)) = 23170 ;
|
||||
*
|
||||
* we also check that no value becomes zero if we have to scale.
|
||||
*/
|
||||
|
||||
maxval = 0;
|
||||
nonzero_minval = FT_LONG_MAX;
|
||||
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
if ( val[i] > maxval )
|
||||
maxval = val[i];
|
||||
if ( val[i] && val[i] < nonzero_minval )
|
||||
nonzero_minval = val[i];
|
||||
}
|
||||
|
||||
if ( maxval > 23170 )
|
||||
{
|
||||
FT_Fixed scale = FT_DivFix( maxval, 23170 );
|
||||
|
||||
|
||||
if ( !FT_DivFix( nonzero_minval, scale ) )
|
||||
return 0; /* value range too large */
|
||||
|
||||
m.xx = FT_DivFix( matrix->xx, scale );
|
||||
m.xy = FT_DivFix( matrix->xy, scale );
|
||||
m.yx = FT_DivFix( matrix->yx, scale );
|
||||
m.yy = FT_DivFix( matrix->yy, scale );
|
||||
}
|
||||
else
|
||||
m = *matrix;
|
||||
|
||||
temp1 = FT_ABS( m.xx * m.yy - m.xy * m.yx );
|
||||
temp2 = m.xx * m.xx + m.xy * m.xy + m.yx * m.yx + m.yy * m.yy;
|
||||
|
||||
if ( temp1 == 0 ||
|
||||
temp2 / temp1 > 50 )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* documentation is in ftcalc.h */
|
||||
|
||||
FT_BASE_DEF( void )
|
||||
|
@ -604,7 +604,6 @@
|
||||
FT_Vector* offset = &dict->font_offset;
|
||||
FT_ULong* upm = &dict->units_per_em;
|
||||
FT_Byte** data = parser->stack;
|
||||
FT_Error error = FT_ERR( Stack_Underflow );
|
||||
|
||||
|
||||
if ( parser->top >= parser->stack + 6 )
|
||||
@ -616,8 +615,6 @@
|
||||
int i;
|
||||
|
||||
|
||||
error = FT_Err_Ok;
|
||||
|
||||
dict->has_font_matrix = TRUE;
|
||||
|
||||
/* We expect a well-formed font matrix, this is, the matrix elements */
|
||||
@ -646,22 +643,11 @@
|
||||
( max_scaling - min_scaling ) < 0 ||
|
||||
( max_scaling - min_scaling ) > 9 )
|
||||
{
|
||||
/* Return default matrix in case of unlikely values. */
|
||||
|
||||
FT_TRACE1(( "cff_parse_font_matrix:"
|
||||
" strange scaling values (minimum %d, maximum %d),\n"
|
||||
" "
|
||||
" using default matrix\n", min_scaling, max_scaling ));
|
||||
|
||||
matrix->xx = 0x10000L;
|
||||
matrix->yx = 0;
|
||||
matrix->xy = 0;
|
||||
matrix->yy = 0x10000L;
|
||||
offset->x = 0;
|
||||
offset->y = 0;
|
||||
*upm = 1;
|
||||
|
||||
goto Exit;
|
||||
goto Unlikely;
|
||||
}
|
||||
|
||||
for ( i = 0; i < 6; i++ )
|
||||
@ -708,10 +694,31 @@
|
||||
(double)matrix->yy / *upm / 65536,
|
||||
(double)offset->x / *upm / 65536,
|
||||
(double)offset->y / *upm / 65536 ));
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
if ( !FT_Matrix_Check( matrix ) )
|
||||
{
|
||||
FT_TRACE1(( "cff_parse_font_matrix:"
|
||||
" degenerate values, using default matrix\n" ));
|
||||
goto Unlikely;
|
||||
}
|
||||
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
else
|
||||
return FT_THROW( Stack_Underflow );
|
||||
|
||||
Unlikely:
|
||||
/* Return default matrix in case of unlikely values. */
|
||||
|
||||
matrix->xx = 0x10000L;
|
||||
matrix->yx = 0;
|
||||
matrix->xy = 0;
|
||||
matrix->yy = 0x10000L;
|
||||
offset->x = 0;
|
||||
offset->y = 0;
|
||||
*upm = 1;
|
||||
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
|
||||
|
||||
|
@ -200,6 +200,13 @@
|
||||
matrix->xy = temp[2];
|
||||
matrix->yy = temp[3];
|
||||
|
||||
if ( !FT_Matrix_Check( matrix ) )
|
||||
{
|
||||
FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" ));
|
||||
parser->root.error = FT_THROW( Invalid_File_Format );
|
||||
return FT_THROW( Invalid_File_Format );
|
||||
}
|
||||
|
||||
/* note that the font offsets are expressed in integer font units */
|
||||
offset->x = temp[4] >> 16;
|
||||
offset->y = temp[5] >> 16;
|
||||
|
@ -1286,6 +1286,13 @@
|
||||
matrix->xy = temp[2];
|
||||
matrix->yy = temp[3];
|
||||
|
||||
if ( !FT_Matrix_Check( matrix ) )
|
||||
{
|
||||
FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" ));
|
||||
parser->root.error = FT_THROW( Invalid_File_Format );
|
||||
return;
|
||||
}
|
||||
|
||||
/* note that the offsets must be expressed in integer font units */
|
||||
offset->x = temp[4] >> 16;
|
||||
offset->y = temp[5] >> 16;
|
||||
|
@ -284,6 +284,13 @@
|
||||
matrix->xy = temp[2];
|
||||
matrix->yy = temp[3];
|
||||
|
||||
if ( !FT_Matrix_Check( matrix ) )
|
||||
{
|
||||
FT_ERROR(( "t42_parse_font_matrix: invalid font matrix\n" ));
|
||||
parser->root.error = FT_THROW( Invalid_File_Format );
|
||||
return;
|
||||
}
|
||||
|
||||
/* note that the offsets must be expressed in integer font units */
|
||||
offset->x = temp[4] >> 16;
|
||||
offset->y = temp[5] >> 16;
|
||||
|
Loading…
Reference in New Issue
Block a user