Commit 10e2bb8b3deb85859c0dd254804959826f3be2ed

Werner Lemberg 2015-03-29T13:32:47

[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.

diff --git a/ChangeLog b/ChangeLog
index 4bb3ca0..abefef0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,18 @@
-2015-03-27  Werner Lemberg  <wl@gnu.org>
+2015-03-29  Werner Lemberg  <wl@gnu.org>
+
+	[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  <wl@gnu.org>
 
 	[type1] Minor.
 
diff --git a/include/ftmm.h b/include/ftmm.h
index 7d079f6..6ef4798 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.                         */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    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.                         */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    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.                         */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    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 77796f0..940f288 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -864,7 +864,10 @@
   /*                  Initialize the blend structure with `gvar' data.     */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    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.        */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    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 acfa486..39acef2 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] );