ref: 25f3ac2b9e2482bdbe3a5fa6ce5ff6a5df05ae69
parent: eb6d02087b9f540372049eff2721ac6aff837232
author: Werner Lemberg <[email protected]>
date: Sun Dec 18 10:50:18 EST 2016
[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.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
2016-12-18 Werner Lemberg <[email protected]>
+ [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 <[email protected]>
+
Minor GX code shuffling.
* include/freetype/internal/tttypes.h (TT_Face): Move
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -1163,6 +1163,9 @@
/* */
/* 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 @@
/* 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 @@
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 */
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -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;
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -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" ));