From 64a91137f13fbc11b6bac393be978d191eee7633 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Wed, 21 Dec 2016 19:30:33 +0100 Subject: [PATCH] [truetype, sfnt] Introduce font variation flags to `TT_Face'. * include/freetype/internal/tttypes.h (TT_FACE_FLAG_VAR_XXX): New macros describing available functionality of various OpenType tables related to font variation. (TT_Face): New fields `variation_support' and `mvar_support', replacing and extending `use_fvar'. * src/sfnt/sfobjs.c (sfnt_init_face, sfnt_load_face): Use `variation_support'. * src/truetype/ttgxvar.c (ft_var_load_hvar): Set `variation_support' field. (TT_Vary_Apply_Glyph_Deltas): Updated. --- ChangeLog | 17 ++++++ include/freetype/internal/tttypes.h | 82 +++++++++++++++++++++++++++-- src/sfnt/sfobjs.c | 9 ++-- src/truetype/ttgxvar.c | 28 +++++++--- 4 files changed, 121 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 769cb24ff..93397fd6a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2016-12-21 Werner Lemberg + + [truetype, sfnt] Introduce font variation flags to `TT_Face'. + + * include/freetype/internal/tttypes.h (TT_FACE_FLAG_VAR_XXX): + New macros describing available functionality of various OpenType + tables related to font variation. + (TT_Face): New fields `variation_support' and `mvar_support', + replacing and extending `use_fvar'. + + * src/sfnt/sfobjs.c (sfnt_init_face, sfnt_load_face): Use + `variation_support'. + + * src/truetype/ttgxvar.c (ft_var_load_hvar): Set `variation_support' + field. + (TT_Vary_Apply_Glyph_Deltas): Updated. + 2016-12-21 Werner Lemberg [base] Improve sanity check for Mac resources (#49888). diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h index 82aaafc8b..eef3b108c 100644 --- a/include/freetype/internal/tttypes.h +++ b/include/freetype/internal/tttypes.h @@ -1060,6 +1060,75 @@ FT_BEGIN_HEADER } TT_SbitTableType; + /* OpenType 1.8 brings new tables for variation font support; */ + /* to make the old MM and GX fonts still work we need to check */ + /* the presence (and validity) of the functionality provided */ + /* by those tables. The following flag macros are for the */ + /* field `variation_support'. */ + /* */ + /* Note that `fvar' gets checked immediately at font loading, */ + /* while the other features are only loaded if MM support is */ + /* actually requested. */ + + /* FVAR */ +#define TT_FACE_FLAG_VAR_FVAR ( 1 << 0 ) + + /* HVAR */ +#define TT_FACE_FLAG_VAR_HADVANCE ( 1 << 1 ) +#define TT_FACE_FLAG_VAR_LSB ( 1 << 2 ) +#define TT_FACE_FLAG_VAR_RSB ( 1 << 3 ) + + /* VVAR */ +#define TT_FACE_FLAG_VAR_VADVANCE ( 1 << 4 ) +#define TT_FACE_FLAG_VAR_TSB ( 1 << 5 ) +#define TT_FACE_FLAG_VAR_BSB ( 1 << 6 ) +#define TT_FACE_FLAG_VAR_VORG ( 1 << 7 ) + + /* MVAR gasp data */ +#define TT_FACE_FLAG_VAR_GASP_0 ( 1 << 20 ) +#define TT_FACE_FLAG_VAR_GASP_1 ( 1 << 21 ) +#define TT_FACE_FLAG_VAR_GASP_2 ( 1 << 22 ) +#define TT_FACE_FLAG_VAR_GASP_3 ( 1 << 23 ) +#define TT_FACE_FLAG_VAR_GASP_4 ( 1 << 24 ) +#define TT_FACE_FLAG_VAR_GASP_5 ( 1 << 25 ) +#define TT_FACE_FLAG_VAR_GASP_6 ( 1 << 26 ) +#define TT_FACE_FLAG_VAR_GASP_7 ( 1 << 27 ) +#define TT_FACE_FLAG_VAR_GASP_8 ( 1 << 28 ) +#define TT_FACE_FLAG_VAR_GASP_9 ( 1 << 29 ) + + /* The following flag macros are for the field `mvar_support'. */ + + /* remaining MVAR data */ +#define TT_FACE_FLAG_VAR_CPHT ( 1 << 0 ) +#define TT_FACE_FLAG_VAR_HASC ( 1 << 1 ) +#define TT_FACE_FLAG_VAR_HCLA ( 1 << 2 ) +#define TT_FACE_FLAG_VAR_HCLD ( 1 << 3 ) +#define TT_FACE_FLAG_VAR_HCOF ( 1 << 4 ) +#define TT_FACE_FLAG_VAR_HCRN ( 1 << 5 ) +#define TT_FACE_FLAG_VAR_HCRS ( 1 << 6 ) +#define TT_FACE_FLAG_VAR_HDSC ( 1 << 7 ) +#define TT_FACE_FLAG_VAR_HLGP ( 1 << 8 ) +#define TT_FACE_FLAG_VAR_SBXO ( 1 << 9 ) +#define TT_FACE_FLAG_VAR_SBXS ( 1 << 10 ) +#define TT_FACE_FLAG_VAR_SBYO ( 1 << 11 ) +#define TT_FACE_FLAG_VAR_SBYS ( 1 << 12 ) +#define TT_FACE_FLAG_VAR_SPXO ( 1 << 13 ) +#define TT_FACE_FLAG_VAR_SPXS ( 1 << 14 ) +#define TT_FACE_FLAG_VAR_SPYO ( 1 << 15 ) +#define TT_FACE_FLAG_VAR_SPYS ( 1 << 16 ) +#define TT_FACE_FLAG_VAR_STRO ( 1 << 17 ) +#define TT_FACE_FLAG_VAR_STRS ( 1 << 18 ) +#define TT_FACE_FLAG_VAR_UNDO ( 1 << 19 ) +#define TT_FACE_FLAG_VAR_UNDS ( 1 << 20 ) +#define TT_FACE_FLAG_VAR_VASC ( 1 << 21 ) +#define TT_FACE_FLAG_VAR_VCOF ( 1 << 22 ) +#define TT_FACE_FLAG_VAR_VCRN ( 1 << 23 ) +#define TT_FACE_FLAG_VAR_VCRS ( 1 << 24 ) +#define TT_FACE_FLAG_VAR_VDSC ( 1 << 25 ) +#define TT_FACE_FLAG_VAR_VLGP ( 1 << 26 ) +#define TT_FACE_FLAG_VAR_XHGT ( 1 << 27 ) + + /*************************************************************************/ /* */ /* TrueType Face Type */ @@ -1237,8 +1306,14 @@ 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. */ + /* variation_support :: Flags that indicate which OpenType */ + /* functionality related to font variation */ + /* support is present, valid, and usable. */ + /* For example, TT_FACE_FLAG_VAR_FVAR is only */ + /* set if we have at least one design axis. */ + /* */ + /* mvar_support :: Flags that indicate which metrics */ + /* variations are supported. */ /* */ /* horz_metrics_size :: The size of the `hmtx' table. */ /* */ @@ -1432,7 +1507,8 @@ FT_BEGIN_HEADER GX_Blend blend; FT_Bool is_default_instance; /* since 2.7.1 */ - FT_Bool use_fvar; /* since 2.7.1 */ + FT_UInt32 variation_support; /* since 2.7.1 */ + FT_UInt32 mvar_support; /* since 2.7.1 */ #endif /* since version 2.2 */ diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index c40325a94..919129d78 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -981,12 +981,9 @@ offset + axis_size * num_axes + instance_size * num_instances > fvar_len ) - { - num_instances = 0; - face->use_fvar = 0; - } + num_instances = 0; else - face->use_fvar = 1; + face->variation_support |= TT_FACE_FLAG_VAR_FVAR; /* we don't support Multiple Master CFFs yet */ if ( !face->goto_table( face, TTAG_CFF, stream, 0 ) ) @@ -1368,7 +1365,7 @@ #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 ( face->use_fvar ) + if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) { if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && tt_face_lookup_table( face, TTAG_gvar ) != 0 ) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 5a4e8f5f5..3b73283c9 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -742,8 +742,13 @@ FT_FREE( dataOffsetArray ); if ( !error ) + { blend->hvar_checked = TRUE; + /* TODO: implement other HVAR stuff */ + face->variation_support |= TT_FACE_FLAG_VAR_HADVANCE; + } + return error; } @@ -796,6 +801,9 @@ goto Exit; } + /* advance width adjustments are always present in an `HVAR' table, */ + /* so need to test for this capability */ + if ( gindex >= face->blend->hvar_table->widthMap.mapCount ) { FT_TRACE2(( "gindex %d out of range\n", gindex )); @@ -2608,14 +2616,22 @@ FT_Pos delta_y = FT_MulFix( deltas_y[j], apply ); - /* Experimental fix for double adjustment of advance width: */ - /* adjust phantom point 2 only if there's no HVAR. */ - /* */ - /* TODO: handle LSB (pp1) and VVAR (pp3, pp4) too */ - if ( j != ( n_points - 3 ) || blend->hvar_checked == FALSE ) + /* To avoid double adjustment of advance width or height, */ + /* adjust phantom points only if there is no HVAR or VVAR */ + /* table, respectively. */ + if ( j != ( n_points - 3 ) || + !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) + outline->points[j].x += delta_x; + if ( j != ( n_points - 2 ) || + !( face->variation_support & TT_FACE_FLAG_VAR_LSB ) ) outline->points[j].x += delta_x; - outline->points[j].y += delta_y; + if ( j != ( n_points - 1 ) || + !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) + outline->points[j].y += delta_y; + if ( j != ( n_points - 0 ) || + !( face->variation_support & TT_FACE_FLAG_VAR_TSB ) ) + outline->points[j].y += delta_y; #ifdef FT_DEBUG_LEVEL_TRACE if ( delta_x || delta_y )