[sfnt] Handle `fvar' with zero axes as a non-MM font.

This is better behaviour than exiting with an error.

* include/freetype/internal/tttypes.h (TT_Face): Add `use_fvar'
field.

* src/sfnt/sfobjs.c (sfnt_init_face): Compute `use_fvar', also
updating the validation code.
Use `use_fvar' to compute FT_FACE_FLAG_MULTIPLE_MASTERS.

* src/truetype/ttgxvar.c (TT_Get_MM_Var): Remove `fvar' validation
code.
This commit is contained in:
Werner Lemberg 2016-12-18 15:50:18 +01:00
parent eb6d02087b
commit 25f3ac2b9e
4 changed files with 52 additions and 44 deletions

View File

@ -1,3 +1,19 @@
2016-12-18 Werner Lemberg <wl@gnu.org>
[sfnt] Handle `fvar' with zero axes as a non-MM font.
This is better behaviour than exiting with an error.
* include/freetype/internal/tttypes.h (TT_Face): Add `use_fvar'
field.
* src/sfnt/sfobjs.c (sfnt_init_face): Compute `use_fvar', also
updating the validation code.
Use `use_fvar' to compute FT_FACE_FLAG_MULTIPLE_MASTERS.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): Remove `fvar' validation
code.
2016-12-18 Werner Lemberg <wl@gnu.org>
Minor GX code shuffling.

View File

@ -1163,6 +1163,9 @@ FT_BEGIN_HEADER
/* */
/* mm :: A pointer to the Multiple Masters service. */
/* */
/* var :: A pointer to the Metrics Variations */
/* service. */
/* */
/* hdmx :: The face's horizontal device metrics */
/* (`hdmx' table). This table is optional in */
/* TrueType/OpenType fonts. */
@ -1234,6 +1237,9 @@ FT_BEGIN_HEADER
/* unmodified (i.e., without applying glyph */
/* variation deltas). */
/* */
/* use_fvar :: Set if the `fvar' table header is valid, */
/* and we have at least one design axis. */
/* */
/* horz_metrics_size :: The size of the `hmtx' table. */
/* */
/* vert_metrics_size :: The size of the `vmtx' table. */
@ -1426,6 +1432,7 @@ FT_BEGIN_HEADER
GX_Blend blend;
FT_Bool is_default_instance; /* since 2.7.1 */
FT_Bool use_fvar; /* since 2.7.1 */
#endif
/* since version 2.2 */

View File

@ -949,7 +949,7 @@
fvar_len < 20 ||
FT_READ_ULONG( version ) ||
FT_READ_USHORT( offset ) ||
FT_STREAM_SKIP( 2 ) ||
FT_STREAM_SKIP( 2 ) /* count_size_pairs */ ||
FT_READ_USHORT( num_axes ) ||
FT_READ_USHORT( axis_size ) ||
FT_READ_USHORT( num_instances ) ||
@ -963,18 +963,30 @@
instance_size = 0;
}
/* check that the data is bound by the table length; */
/* based on similar code in function `TT_Get_MM_Var' */
/* check that the data is bound by the table length */
if ( version != 0x00010000UL ||
#if 0
/* fonts like `JamRegular.ttf' have an incorrect value for */
/* `count_size_pairs'; since value 2 is hard-coded in `fvar' */
/* version 1.0, we simply ignore it */
count_size_pairs != 2 ||
#endif
axis_size != 20 ||
num_axes == 0 ||
/* `num_axes' limit implied by 16-bit `instance_size' */
num_axes > 0x3FFE ||
instance_size != 4 + 4 * num_axes ||
!( instance_size == 4 + 4 * num_axes ||
instance_size == 6 + 4 * num_axes ) ||
num_instances > 0x7EFF ||
offset +
axis_size * num_axes +
instance_size * num_instances > fvar_len )
num_instances = 0;
{
num_instances = 0;
face->use_fvar = 0;
}
else
face->use_fvar = 1;
/* we don't support Multiple Master CFFs yet */
if ( !face->goto_table( face, TTAG_CFF, stream, 0 ) )
@ -1356,13 +1368,14 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
/* Don't bother to load the tables unless somebody asks for them. */
/* No need to do work which will (probably) not be used. */
if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
tt_face_lookup_table( face, TTAG_gvar ) != 0 )
flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 &&
tt_face_lookup_table( face, TTAG_fvar ) != 0 )
flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
if ( face->use_fvar )
{
if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
tt_face_lookup_table( face, TTAG_gvar ) != 0 )
flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 )
flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
}
#endif
root->face_flags = flags;

View File

@ -1344,41 +1344,13 @@
fvar_start = FT_STREAM_POS( );
/* the validity of the `fvar' header data was already checked */
/* in function `sfnt_init_face' */
if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) )
goto Exit;
if ( fvar_head.version != (FT_Long)0x00010000L ||
#if 0
/* fonts like `JamRegular.ttf' have an incorrect value for */
/* `countSizePairs'; since value 2 is hard-coded in `fvar' */
/* version 1.0, we simply ignore it */
fvar_head.countSizePairs != 2 ||
#endif
fvar_head.axisSize != 20 ||
fvar_head.axisCount == 0 ||
/* axisCount limit implied by 16-bit instanceSize */
fvar_head.axisCount > 0x3FFE ||
fvar_head.instanceCount > 0x7EFF ||
fvar_head.offsetToData + fvar_head.axisCount * 20U +
fvar_head.instanceCount * fvar_head.instanceSize > table_len )
{
FT_TRACE1(( "\n"
"TT_Get_MM_Var: invalid `fvar' header\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
if ( fvar_head.instanceSize == 4 + 4 * fvar_head.axisCount )
usePsName = FALSE;
else if ( fvar_head.instanceSize == 6 + 4 * fvar_head.axisCount )
usePsName = TRUE;
else
{
FT_TRACE1(( "\n"
"TT_Get_MM_Var: invalid `fvar' header\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
usePsName = FT_BOOL( fvar_head.instanceSize ==
6 + 4 * fvar_head.axisCount );
FT_TRACE2(( "loaded\n" ));