Commit f89c67f043c73e709e5721e651f2b616dab72ead

Werner Lemberg 2017-10-07T13:10:53

[cff, truetype] Adjust behaviour of named instances. This commit completely separates the interaction between named instances and variation functions. In particular, resetting the variation returns to the current named instance (if set) and not to the base font. As a side effect, variation functions no longer change the named instance index. * src/cff/cffobjs.c (cff_face_init): Use MM service's `set_instance' function. Also apply `MVAR' table to named instances. * src/truetype/ttgxvar.c (TT_Get_MM_Var): Add cast. (tt_set_mm_blend): No longer check whether requested variation coincides with a named instance. (TT_Set_Var_Design): Use current named instance for default coordinates. * src/truetype/ttobjs.c (tt_face_init): Use `TT_Set_Named_Instance'.

diff --git a/ChangeLog b/ChangeLog
index 80e97b1..98c8374 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
 2017-10-07  Werner Lemberg  <wl@gnu.org>
 
+	[cff, truetype] Adjust behaviour of named instances.
+
+	This commit completely separates the interaction between named
+	instances and variation functions.  In particular, resetting the
+	variation returns to the current named instance (if set) and not to
+	the base font.
+
+	As a side effect, variation functions no longer change the named
+	instance index.
+
+	* src/cff/cffobjs.c (cff_face_init): Use MM service's `set_instance'
+	function.
+	Also apply `MVAR' table to named instances.
+
+	* src/truetype/ttgxvar.c (TT_Get_MM_Var): Add cast.
+	(tt_set_mm_blend): No longer check whether requested variation
+	coincides with a named instance.
+	(TT_Set_Var_Design): Use current named instance for default
+	coordinates.
+	* src/truetype/ttobjs.c (tt_face_init): Use `TT_Set_Named_Instance'.
+
+2017-10-07  Werner Lemberg  <wl@gnu.org>
+
 	Make `FT_Set_Named_Instance' work.
 
 	* src/cff/cffdrivr.c (cff_set_instance): New function.
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index 3499d62..77d277e 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -904,6 +904,13 @@ FT_BEGIN_HEADER
   /*                           Bit 31 is always zero (this is,             */
   /*                           `face_index' is always a positive value).   */
   /*                                                                       */
+  /*                           [Since 2.8.2] Changing the design           */
+  /*                           coordinates with                            */
+  /*                           @FT_Set_Var_Design_Coordinates or           */
+  /*                           @FT_Set_Var_Blend_Coordinates does not      */
+  /*                           influence the named instance index value    */
+  /*                           (only @FT_Set_Named_Instance does that).    */
+  /*                                                                       */
   /*    face_flags          :: A set of bit flags that give important      */
   /*                           information about the face; see             */
   /*                           @FT_FACE_FLAG_XXX for the details.          */
@@ -1403,6 +1410,11 @@ FT_BEGIN_HEADER
    *   A macro that returns true whenever a face object is a named instance
    *   of a GX or OpenType variation font.
    *
+   *   [Since 2.8.2] Changing the design coordinates with
+   *   @FT_Set_Var_Design_Coordinates or @FT_Set_Var_Blend_Coordinates does
+   *   not influence the return value of this macro (only
+   *   @FT_Set_Named_Instance does that).
+   *
    * @since:
    *   2.7
    *
diff --git a/include/freetype/ftmm.h b/include/freetype/ftmm.h
index fe66f2d..49da796 100644
--- a/include/freetype/ftmm.h
+++ b/include/freetype/ftmm.h
@@ -323,9 +323,13 @@ FT_BEGIN_HEADER
   /*    FreeType error code.  0~means success.                             */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    To reset all axes to the default values, call the function with    */
-  /*    `num_coords' set to zero and `coords' set to NULL (new feature in  */
-  /*    FreeType version 2.8.1).                                           */
+  /*    [Since 2.8.1] To reset all axes to the default values, call the    */
+  /*    function with `num_coords' set to zero and `coords' set to NULL.   */
+  /*                                                                       */
+  /*    [Since 2.8.2] If `num_coords' is larger than zero, this function   */
+  /*    sets the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags'    */
+  /*    field (i.e., @FT_IS_VARIATION will return true).  If `num_coords'  */
+  /*    is zero, this bit flag gets unset.                                 */
   /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Set_MM_Design_Coordinates( FT_Face   face,
@@ -358,9 +362,15 @@ FT_BEGIN_HEADER
   /*    FreeType error code.  0~means success.                             */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    To reset all axes to the default values, call the function with    */
-  /*    `num_coords' set to zero and `coords' set to NULL (new feature in  */
-  /*    FreeType version 2.8.1).                                           */
+  /*    [Since 2.8.1] To reset all axes to the default values, call the    */
+  /*    function with `num_coords' set to zero and `coords' set to NULL.   */
+  /*    [Since 2.8.2] `Default values' means the currently selected named  */
+  /*    instance (or the base font if no named instance is selected).      */
+  /*                                                                       */
+  /*    [Since 2.8.2] If `num_coords' is larger than zero, this function   */
+  /*    sets the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags'    */
+  /*    field (i.e., @FT_IS_VARIATION will return true).  If `num_coords'  */
+  /*    is zero, this bit flag gets unset.                                 */
   /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Set_Var_Design_Coordinates( FT_Face    face,
@@ -430,9 +440,15 @@ FT_BEGIN_HEADER
   /*    FreeType error code.  0~means success.                             */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    To reset all axes to the default values, call the function with    */
-  /*    `num_coords' set to zero and `coords' set to NULL (new feature in  */
-  /*    FreeType version 2.8.1).                                           */
+  /*    [Since 2.8.1] To reset all axes to the default values, call the    */
+  /*    function with `num_coords' set to zero and `coords' set to NULL.   */
+  /*    [Since 2.8.2] `Default values' means the currently selected named  */
+  /*    instance (or the base font if no named instance is selected).      */
+  /*                                                                       */
+  /*    [Since 2.8.2] If `num_coords' is larger than zero, this function   */
+  /*    sets the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags'    */
+  /*    field (i.e., @FT_IS_VARIATION will return true).  If `num_coords'  */
+  /*    is zero, this bit flag gets unset.                                 */
   /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Set_MM_Blend_Coordinates( FT_Face    face,
@@ -518,6 +534,9 @@ FT_BEGIN_HEADER
   /*    FT_VAR_AXIS_FLAG_HIDDEN ::                                         */
   /*      The variation axis should not be exposed to user interfaces.     */
   /*                                                                       */
+  /* <Since>                                                               */
+  /*    2.8.1                                                              */
+  /*                                                                       */
 #define FT_VAR_AXIS_FLAG_HIDDEN  1
 
 
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index c794d32..983fd2e 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -708,50 +708,22 @@
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
       {
-        FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+        FT_Service_MultiMasters       mm  = (FT_Service_MultiMasters)face->mm;
+        FT_Service_MetricsVariations  var = (FT_Service_MetricsVariations)face->var;
 
-        FT_Int  instance_index = face_index >> 16;
+        FT_UInt  instance_index = (FT_UInt)face_index >> 16;
 
 
         if ( FT_HAS_MULTIPLE_MASTERS( cffface ) &&
              mm                                 &&
              instance_index > 0                 )
         {
-          FT_MM_Var*  mm_var;
-
-
-          error = mm->get_mm_var( cffface, NULL );
+          error = mm->set_instance( cffface, instance_index );
           if ( error )
             goto Exit;
 
-          mm->get_var_blend( cffface, NULL, NULL, NULL, &mm_var );
-
-          if ( mm_var->namedstyle )
-          {
-            FT_Var_Named_Style*  named_style;
-            FT_String*           style_name;
-
-
-            /* in `face_index', the instance index starts with value 1 */
-            named_style = mm_var->namedstyle + instance_index - 1;
-            error = sfnt->get_name( face,
-                                    (FT_UShort)named_style->strid,
-                                    &style_name );
-            if ( error )
-              goto Exit;
-
-            /* set style name; if already set, replace it */
-            if ( face->root.style_name )
-              FT_FREE( face->root.style_name );
-            face->root.style_name = style_name;
-
-            /* finally, select the named instance */
-            error = mm->set_var_design( cffface,
-                                        mm_var->num_axis,
-                                        named_style->coords );
-            if ( error )
-              goto Exit;
-          }
+          if ( var )
+            var->metrics_adjust( cffface );
         }
       }
 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 4ad6533..f3c2430 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -2057,7 +2057,7 @@
     /* `num_instances' holds the number of all named instances, */
     /* including the default instance which might be missing    */
     /* in fvar's table of named instances                       */
-    num_instances = face->root.style_flags >> 16;
+    num_instances = (FT_UInt)face->root.style_flags >> 16;
 
     /* prepare storage area for MM data; this cannot overflow   */
     /* 32-bit arithmetic because of the size limits used in the */
@@ -2348,7 +2348,7 @@
     FT_Error    error = FT_Err_Ok;
     GX_Blend    blend;
     FT_MM_Var*  mmvar;
-    FT_UInt     i, j;
+    FT_UInt     i;
 
     FT_Bool     all_design_coords = FALSE;
 
@@ -2489,30 +2489,6 @@
       }
     }
 
-    /* check whether the current variation tuple coincides */
-    /* with a named instance                               */
-
-    for ( i = 0; i < blend->mmvar->num_namedstyles; i++ )
-    {
-      FT_Fixed*  nsc = blend->normalized_stylecoords + i * blend->num_axis;
-      FT_Fixed*  ns  = blend->normalizedcoords;
-
-
-      for ( j = 0; j < blend->num_axis; j++, nsc++, ns++ )
-      {
-        if ( *nsc != *ns )
-          break;
-      }
-
-      if ( j == blend->num_axis )
-        break;
-    }
-
-    /* adjust named instance index */
-    face->root.face_index &= 0xFFFF;
-    if ( i < blend->mmvar->num_namedstyles )
-      face->root.face_index |= ( i + 1 ) << 16;
-
     /* enforce recomputation of the PostScript name; */
     FT_FREE( face->postscript_name );
     face->postscript_name = NULL;
@@ -2680,9 +2656,7 @@
     FT_UInt     i;
     FT_Memory   memory = face->root.memory;
 
-    FT_Var_Axis*  a;
-    FT_Fixed*     c;
-
+    FT_Fixed*  c;
     FT_Fixed*  normalized = NULL;
 
 
@@ -2713,10 +2687,31 @@
                  coords,
                  num_coords * sizeof ( FT_Fixed ) );
 
-    a = mmvar->axis + num_coords;
     c = blend->coords + num_coords;
-    for ( i = num_coords; i < mmvar->num_axis; i++, a++, c++ )
-      *c = a->def;
+
+    if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) )
+    {
+      FT_UInt              instance_index;
+      FT_Var_Named_Style*  named_style;
+      FT_Fixed*            n;
+
+
+      instance_index = (FT_UInt)face->root.face_index >> 16;
+      named_style    = mmvar->namedstyle + instance_index - 1;
+
+      n = named_style->coords + num_coords;
+      for ( i = num_coords; i < mmvar->num_axis; i++, n++, c++ )
+        *c = *n;
+    }
+    else
+    {
+      FT_Var_Axis*  a;
+
+
+      a = mmvar->axis + num_coords;
+      for ( i = num_coords; i < mmvar->num_axis; i++, a++, c++ )
+        *c = a->def;
+    }
 
     if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) )
       goto Exit;
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 081fa2f..70df32b 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -657,46 +657,17 @@
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
     {
-      FT_Int  instance_index = face_index >> 16;
+      FT_UInt  instance_index = (FT_UInt)face_index >> 16;
 
 
       if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
            instance_index > 0                )
       {
-        error = TT_Get_MM_Var( face, NULL );
+        error = TT_Set_Named_Instance( face, instance_index );
         if ( error )
           goto Exit;
 
-        if ( face->blend->mmvar->namedstyle )
-        {
-          FT_Memory  memory = ttface->memory;
-
-          FT_Var_Named_Style*  named_style;
-          FT_String*           style_name;
-
-
-          /* in `face_index', the instance index starts with value 1 */
-          named_style = face->blend->mmvar->namedstyle + instance_index - 1;
-          error = sfnt->get_name( face,
-                                  (FT_UShort)named_style->strid,
-                                  &style_name );
-          if ( error )
-            goto Exit;
-
-          /* set style name; if already set, replace it */
-          if ( face->root.style_name )
-            FT_FREE( face->root.style_name );
-          face->root.style_name = style_name;
-
-          /* finally, select the named instance */
-          error = TT_Set_Var_Design( face,
-                                     face->blend->mmvar->num_axis,
-                                     named_style->coords );
-          if ( error )
-            goto Exit;
-
-          tt_apply_mvar( face );
-        }
+        tt_apply_mvar( face );
       }
     }