Commit 6713b1e41a147897887c3a9b0136104a3f9ed2cf

Werner Lemberg 2023-04-26T12:03:04

[truetype] Fix deactivation of variation font handling. According to the documentation, the functions `FT_Set_Named_Instance`, `FT_Set_MM_Design_Coordinates`, `FT_Set_Var_Design_Coordinates`, and `FT_Set_Var_Blend_Coordinates` can unset the `FT_FACE_FLAG_VARIATION` flag. (The same is true for `FT_Set_MM_WeightVector` but this information was accidentally omitted from the documentation.) However, if a call of these functions didn't change the axis values this could fail because internal shortcuts exited too early. This commit reorganizes the code to handle `FT_FACE_FLAG_VARIATION` in the top-level API functions, also taking care of the issue at hand. * src/base/ftmm.c (FT_Set_MM_Design_Coordinates, FT_Set_MM_WeightVector, FT_Set_Var_Design_Coordinates, FT_Set_MM_Blend_Coordinates, FT_Set_Var_Blend_Coordinates): Handle `FT_FACE_FLAG_VARIATION`. * src/truetype/ttgxvar.c (TT_Set_MM_Blend, TT_Set_Var_Design, TT_Set_Named_Instance) Don't handle `FT_FACE_FLAG_VARIATION`. * src/type1/t1load.c (T1_Set_MM_Blend, T1_Set_MM_WeightVector, T1_Set_MM_Design): Ditto. * src/cff/cffobjs.c (cff_face_init): Use `FT_Set_Named_Instance` instead of low-level functions. * src/truetype/ttobjs.c (tt_face_init): Ditto.

diff --git a/include/freetype/ftmm.h b/include/freetype/ftmm.h
index 2c2f165..d145128 100644
--- a/include/freetype/ftmm.h
+++ b/include/freetype/ftmm.h
@@ -602,10 +602,12 @@ FT_BEGIN_HEADER
    *
    * @note:
    *   Adobe Multiple Master fonts limit the number of designs, and thus the
-   *   length of the weight vector to~16.
+   *   length of the weight vector to 16~elements.
    *
-   *   If `len` is zero and `weightvector` is `NULL`, the weight vector array
-   *   is reset to the default values.
+   *   If `len` 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 `len` is zero, this bit flag
+   *   is unset and the weight vector array is reset to the default values.
    *
    *   The Adobe documentation also states that the values in the
    *   WeightVector array must total 1.0 +/-~0.001.  In practice this does
diff --git a/src/base/ftmm.c b/src/base/ftmm.c
index 1d5e2bc..c061431 100644
--- a/src/base/ftmm.c
+++ b/src/base/ftmm.c
@@ -185,6 +185,14 @@
       error = FT_ERR( Invalid_Argument );
       if ( service->set_mm_design )
         error = service->set_mm_design( face, num_coords, coords );
+
+      if ( !error )
+      {
+        if ( num_coords )
+          face->face_flags |= FT_FACE_FLAG_VARIATION;
+        else
+          face->face_flags &= ~FT_FACE_FLAG_VARIATION;
+      }
     }
 
     /* enforce recomputation of auto-hinting data */
@@ -220,6 +228,14 @@
       error = FT_ERR( Invalid_Argument );
       if ( service->set_mm_weightvector )
         error = service->set_mm_weightvector( face, len, weightvector );
+
+      if ( !error )
+      {
+        if ( len )
+          face->face_flags |= FT_FACE_FLAG_VARIATION;
+        else
+          face->face_flags &= ~FT_FACE_FLAG_VARIATION;
+      }
     }
 
     /* enforce recomputation of auto-hinting data */
@@ -283,6 +299,14 @@
       if ( service_mm->set_var_design )
         error = service_mm->set_var_design( face, num_coords, coords );
 
+      if ( !error || error == -1 )
+      {
+        if ( num_coords )
+          face->face_flags |= FT_FACE_FLAG_VARIATION;
+        else
+          face->face_flags &= ~FT_FACE_FLAG_VARIATION;
+      }
+
       /* internal error code -1 means `no change'; we can exit immediately */
       if ( error == -1 )
         return FT_Err_Ok;
@@ -359,6 +383,14 @@
       if ( service_mm->set_mm_blend )
         error = service_mm->set_mm_blend( face, num_coords, coords );
 
+      if ( !error || error == -1 )
+      {
+        if ( num_coords )
+          face->face_flags |= FT_FACE_FLAG_VARIATION;
+        else
+          face->face_flags &= ~FT_FACE_FLAG_VARIATION;
+      }
+
       /* internal error code -1 means `no change'; we can exit immediately */
       if ( error == -1 )
         return FT_Err_Ok;
@@ -410,6 +442,14 @@
       if ( service_mm->set_mm_blend )
         error = service_mm->set_mm_blend( face, num_coords, coords );
 
+      if ( !error || error == -1 )
+      {
+        if ( num_coords )
+          face->face_flags |= FT_FACE_FLAG_VARIATION;
+        else
+          face->face_flags &= ~FT_FACE_FLAG_VARIATION;
+      }
+
       /* internal error code -1 means `no change'; we can exit immediately */
       if ( error == -1 )
         return FT_Err_Ok;
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index 2285c1a..1f24f3d 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -719,24 +719,15 @@
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
       {
-        FT_Service_MultiMasters
-          mm = (FT_Service_MultiMasters)face->mm;
-        FT_Service_MetricsVariations
-          var = (FT_Service_MetricsVariations)face->face_var;
-
         FT_UInt  instance_index = (FT_UInt)face_index >> 16;
 
 
         if ( FT_HAS_MULTIPLE_MASTERS( cffface ) &&
-             mm                                 &&
              instance_index > 0                 )
         {
-          error = mm->set_named_instance( cffface, instance_index );
+          error = FT_Set_Named_Instance( cffface, instance_index );
           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 d28cc24..4448362 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -2985,11 +2985,6 @@
     if ( error )
       return error;
 
-    if ( num_coords )
-      face->root.face_flags |= FT_FACE_FLAG_VARIATION;
-    else
-      face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
-
     return FT_Err_Ok;
   }
 
@@ -3208,11 +3203,6 @@
     if ( error )
       goto Exit;
 
-    if ( num_coords )
-      face->root.face_flags |= FT_FACE_FLAG_VARIATION;
-    else
-      face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
-
   Exit:
     FT_FREE( normalized );
     return error;
@@ -3382,9 +3372,8 @@
     else
       error = TT_Set_Var_Design( face, 0, NULL );
 
-    face->root.face_index  = ( instance_index << 16 )             |
-                             ( face->root.face_index & 0xFFFFL );
-    face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
+    face->root.face_index = ( instance_index << 16 )             |
+                            ( face->root.face_index & 0xFFFFL );
 
   Exit:
     return error;
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index c351e08..29d41da 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -777,7 +777,6 @@
     }
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-
     {
       FT_UInt  instance_index = (FT_UInt)face_index >> 16;
 
@@ -785,14 +784,11 @@
       if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
            instance_index > 0                )
       {
-        error = TT_Set_Named_Instance( face, instance_index );
+        error = FT_Set_Named_Instance( ttface, instance_index );
         if ( error )
           goto Exit;
-
-        tt_apply_mvar( face );
       }
     }
-
 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
 
     /* initialize standard glyph loading routines */
diff --git a/src/type1/t1load.c b/src/type1/t1load.c
index 371edf4..a3b2810 100644
--- a/src/type1/t1load.c
+++ b/src/type1/t1load.c
@@ -449,11 +449,6 @@
     if ( error )
       return error;
 
-    if ( num_coords )
-      face->root.face_flags |= FT_FACE_FLAG_VARIATION;
-    else
-      face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
-
     return FT_Err_Ok;
   }
 
@@ -522,11 +517,6 @@
 
       for ( ; i < blend->num_designs; i++ )
         blend->weight_vector[i] = (FT_Fixed)0;
-
-      if ( len )
-        face->root.face_flags |= FT_FACE_FLAG_VARIATION;
-      else
-        face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
     }
 
     return FT_Err_Ok;
@@ -638,11 +628,6 @@
     if ( error )
       return error;
 
-    if ( num_coords )
-      face->root.face_flags |= FT_FACE_FLAG_VARIATION;
-    else
-      face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
-
     return FT_Err_Ok;
   }