From 10e2bb8b3deb85859c0dd254804959826f3be2ed Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Sun, 29 Mar 2015 13:32:47 +0200 Subject: [PATCH] [type1, truetype] Make the MM API more flexible w.r.t. `num_coords'. This commit allows `num_coords' to be larger or smaller than the number of available axes while selecting a design instance, either ignoring excess data or using defaults if data is missing. * src/truetype/ttgxvar.c (TT_Set_MM_Blend, TT_Set_Var_Design): Implement it. * src/type1/t1load.c (T1_Set_MM_Blend, T1_Set_MM_Design, T1_Set_Var_Design): Ditto. --- ChangeLog | 16 ++++++++++++++- include/ftmm.h | 26 +++++++++++++++---------- src/truetype/ttgxvar.c | 44 +++++++++++++++++++++++++++--------------- src/type1/t1load.c | 29 ++++++++++++++++++++-------- 4 files changed, 80 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4bb3ca069..abefef0a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,18 @@ -2015-03-27 Werner Lemberg +2015-03-29 Werner Lemberg + + [type1, truetype] Make the MM API more flexible w.r.t. `num_coords'. + + This commit allows `num_coords' to be larger or smaller than the + number of available axes while selecting a design instance, either + ignoring excess data or using defaults if data is missing. + + * src/truetype/ttgxvar.c (TT_Set_MM_Blend, TT_Set_Var_Design): + Implement it. + + * src/type1/t1load.c (T1_Set_MM_Blend, T1_Set_MM_Design, + T1_Set_Var_Design): Ditto. + +2015-03-29 Werner Lemberg [type1] Minor. diff --git a/include/ftmm.h b/include/ftmm.h index 7d079f6d2..6ef47987e 100644 --- a/include/ftmm.h +++ b/include/ftmm.h @@ -95,8 +95,8 @@ FT_BEGIN_HEADER /* */ /* num_designs :: Number of designs; should be normally 2^num_axis */ /* even though the Type~1 specification strangely */ - /* allows for intermediate designs to be present. This */ - /* number cannot exceed~16. */ + /* allows for intermediate designs to be present. */ + /* This number cannot exceed~16. */ /* */ /* axis :: A table of axis descriptors. */ /* */ @@ -201,10 +201,10 @@ FT_BEGIN_HEADER /* associated with them. The font can tell the */ /* user that, for example, Weight=1.5 is `Bold'. */ /* */ - /* axis :: A table of axis descriptors. */ + /* axis :: An axis descriptor table. */ /* GX fonts contain slightly more data than MM. */ /* */ - /* namedstyles :: A table of named styles. */ + /* namedstyle :: A named style table. */ /* Only meaningful with GX. */ /* */ typedef struct FT_MM_Var_ @@ -280,8 +280,10 @@ FT_BEGIN_HEADER /* face :: A handle to the source face. */ /* */ /* */ - /* num_coords :: The number of design coordinates (must be equal to */ - /* the number of axes in the font). */ + /* num_coords :: The number of available design coordinates. If it */ + /* is larger than the number of axes, ignore the excess */ + /* values. If it is smaller than the number of axes, */ + /* use default values for the remaining axes. */ /* */ /* coords :: An array of design coordinates. */ /* */ @@ -307,8 +309,10 @@ FT_BEGIN_HEADER /* face :: A handle to the source face. */ /* */ /* */ - /* num_coords :: The number of design coordinates (must be equal to */ - /* the number of axes in the font). */ + /* num_coords :: The number of available design coordinates. If it */ + /* is larger than the number of axes, ignore the excess */ + /* values. If it is smaller than the number of axes, */ + /* use default values for the remaining axes. */ /* */ /* coords :: An array of design coordinates. */ /* */ @@ -334,8 +338,10 @@ FT_BEGIN_HEADER /* face :: A handle to the source face. */ /* */ /* */ - /* num_coords :: The number of design coordinates (must be equal to */ - /* the number of axes in the font). */ + /* num_coords :: The number of available design coordinates. If it */ + /* is larger than the number of axes, ignore the excess */ + /* values. If it is smaller than the number of axes, */ + /* use default values for the remaining axes. */ /* */ /* coords :: The design coordinates array (each element must be */ /* between 0 and 1.0). */ diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 77796f051..940f288f4 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -864,7 +864,10 @@ /* Initialize the blend structure with `gvar' data. */ /* */ /* */ - /* num_coords :: Must be the axis count of the font. */ + /* num_coords :: The number of available coordinates. If it is */ + /* larger than the number of axes, ignore the excess */ + /* values. If it is smaller than the number of axes, */ + /* use the default value (0) for the remaining axes. */ /* */ /* coords :: An array of `num_coords', each between [-1,1]. */ /* */ @@ -902,11 +905,8 @@ blend = face->blend; mmvar = blend->mmvar; - if ( num_coords != mmvar->num_axis ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } + if ( num_coords > mmvar->num_axis ) + num_coords = mmvar->num_axis; for ( i = 0; i < num_coords; i++ ) if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L ) @@ -921,7 +921,7 @@ if ( blend->normalizedcoords == NULL ) { - if ( FT_NEW_ARRAY( blend->normalizedcoords, num_coords ) ) + if ( FT_NEW_ARRAY( blend->normalizedcoords, mmvar->num_axis ) ) goto Exit; manageCvt = mcvt_modify; @@ -943,13 +943,22 @@ } } + for ( ; i < mmvar->num_axis; i++ ) + { + if ( blend->normalizedcoords[i] != 0 ) + { + manageCvt = mcvt_load; + break; + } + } + /* If we don't change the blend coords then we don't need to do */ /* anything to the cvt table. It will be correct. Otherwise we */ /* no longer have the original cvt (it was modified when we set */ /* the blend last time), so we must reload and then modify it. */ } - blend->num_axis = num_coords; + blend->num_axis = mmvar->num_axis; FT_MEM_COPY( blend->normalizedcoords, coords, num_coords * sizeof ( FT_Fixed ) ); @@ -1001,7 +1010,10 @@ /* Initialize the blend struct with `gvar' data. */ /* */ /* */ - /* num_coords :: This must be the axis count of the font. */ + /* num_coords :: The number of available coordinates. If it is */ + /* larger than the number of axes, ignore the excess */ + /* values. If it is smaller than the number of axes, */ + /* use the default values for the remaining axes. */ /* */ /* coords :: A coordinate array with `num_coords' elements. */ /* */ @@ -1032,11 +1044,8 @@ blend = face->blend; mmvar = blend->mmvar; - if ( num_coords != mmvar->num_axis ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } + if ( num_coords > mmvar->num_axis ) + num_coords = mmvar->num_axis; /* Axis normalization is a two stage process. First we normalize */ /* based on the [min,def,max] values for the axis to be [-1,0,1]. */ @@ -1046,7 +1055,7 @@ goto Exit; a = mmvar->axis; - for ( i = 0; i < mmvar->num_axis; i++, a++ ) + for ( i = 0; i < num_coords; i++, a++ ) { if ( coords[i] > a->maximum || coords[i] < a->minimum ) { @@ -1064,6 +1073,9 @@ a->maximum - a->def ); } + for ( ; i < mmvar->num_axis; i++ ) + normalized[i] = 0; + if ( !blend->avar_checked ) ft_var_load_avar( face ); @@ -1087,7 +1099,7 @@ } } - error = TT_Set_MM_Blend( face, num_coords, normalized ); + error = TT_Set_MM_Blend( face, mmvar->num_axis, normalized ); Exit: FT_FREE( normalized ); diff --git a/src/type1/t1load.c b/src/type1/t1load.c index acfa48678..39acef263 100644 --- a/src/type1/t1load.c +++ b/src/type1/t1load.c @@ -371,9 +371,12 @@ FT_UInt n, m; - if ( !blend || blend->num_axis != num_coords ) + if ( !blend ) return FT_THROW( Invalid_Argument ); + if ( num_coords > blend->num_axis ) + num_coords = blend->num_axis; + /* recompute the weight vector from the blend coordinates */ for ( n = 0; n < blend->num_designs; n++ ) { @@ -385,8 +388,9 @@ FT_Fixed factor; - /* get current blend axis position */ - factor = coords[m]; + /* get current blend axis position; */ + /* use a default value if we don't have a coordinate */ + factor = m < num_coords ? coords[m] : 0x8000; if ( factor < 0 ) factor = 0; if ( factor > 0x10000L ) @@ -414,14 +418,17 @@ FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; - if ( !blend || blend->num_axis != num_coords ) + if ( !blend ) return FT_THROW( Invalid_Argument ); + if ( num_coords > blend->num_axis ) + num_coords = blend->num_axis; + /* compute the blend coordinates through the blend design map */ for ( n = 0; n < blend->num_axis; n++ ) { - FT_Long design = coords[n]; + FT_Long design; FT_Fixed the_blend; PS_DesignMap map = blend->design_map + n; FT_Long* designs = map->design_points; @@ -429,6 +436,12 @@ FT_Int before = -1, after = -1; + /* use a default value if we don't have a coordinate */ + if ( n < num_coords ) + design = coords[n]; + else + design = ( designs[map->num_points - 1] - designs[0] ) / 2; + for ( p = 0; p < (FT_UInt)map->num_points; p++ ) { FT_Long p_design = designs[p]; @@ -466,7 +479,7 @@ final_blends[n] = the_blend; } - return T1_Set_MM_Blend( face, num_coords, final_blends ); + return T1_Set_MM_Blend( face, blend->num_axis, final_blends ); } @@ -484,8 +497,8 @@ FT_UInt i; - if ( num_coords > T1_MAX_MM_AXIS || num_coords == 0 ) - return FT_THROW( Invalid_Argument ); + if ( num_coords > T1_MAX_MM_AXIS ) + num_coords = T1_MAX_MM_AXIS; for ( i = 0; i < num_coords; ++i ) lcoords[i] = FIXED_TO_INT( coords[i] );