Commit e9ef538a4fb6745ed26bdc6905abb6b5af325e91

Werner Lemberg 2017-10-07T12:57:11

Make `FT_Set_Named_Instance' work. * src/cff/cffdrivr.c (cff_set_instance): New function. (cff_service_multi_masters): Register it. * src/truetype/ttgxvar.c (TT_Set_Named_Instance): New function. * src/truetype/ttgxvar.h: Updated. * src/truetype/ttdriver.c (tt_service_gx_multi_masters): Register it. * src/type1/t1load.c (T1_Reset_MM_Blend): New function. * src/type1/t1load.h: Updated. * src/type1/t1driver.c (t1_service_multi_masters): Register it.

diff --git a/ChangeLog b/ChangeLog
index 1bdfbe4..80e97b1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2017-10-07  Werner Lemberg  <wl@gnu.org>
 
+	Make `FT_Set_Named_Instance' work.
+
+	* src/cff/cffdrivr.c (cff_set_instance): New function.
+	(cff_service_multi_masters): Register it.
+
+	* src/truetype/ttgxvar.c (TT_Set_Named_Instance): New function.
+	* src/truetype/ttgxvar.h: Updated.
+	* src/truetype/ttdriver.c (tt_service_gx_multi_masters): Register
+	it.
+
+	* src/type1/t1load.c (T1_Reset_MM_Blend): New function.
+	* src/type1/t1load.h: Updated.
+	* src/type1/t1driver.c (t1_service_multi_masters): Register it.
+
+2017-10-07  Werner Lemberg  <wl@gnu.org>
+
 	Make `FT_FACE_FLAG_VARIATION' work.
 
 	* include/freetype/internal/tttypes.h (TT_Face): Remove
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index 032ce37..cf630a8 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -1109,6 +1109,17 @@
   }
 
 
+  static FT_Error
+  cff_set_instance( CFF_Face  face,
+                    FT_UInt   instance_index )
+  {
+    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+
+    return mm->set_instance( FT_FACE( face ), instance_index );
+  }
+
+
   FT_DEFINE_SERVICE_MULTIMASTERSREC(
     cff_service_multi_masters,
 
@@ -1119,7 +1130,7 @@
     (FT_Get_MM_Var_Func)    cff_get_mm_var,         /* get_mm_var     */
     (FT_Set_Var_Design_Func)cff_set_var_design,     /* set_var_design */
     (FT_Get_Var_Design_Func)cff_get_var_design,     /* get_var_design */
-    (FT_Set_Instance_Func)  NULL,                   /* set_instance   */
+    (FT_Set_Instance_Func)  cff_set_instance,       /* set_instance   */
 
     (FT_Get_Var_Blend_Func) cff_get_var_blend,      /* get_var_blend  */
     (FT_Done_Blend_Func)    cff_done_blend          /* done_blend     */
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index af36481..ba05cef 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -498,7 +498,7 @@
     (FT_Get_MM_Var_Func)    TT_Get_MM_Var,          /* get_mm_var     */
     (FT_Set_Var_Design_Func)TT_Set_Var_Design,      /* set_var_design */
     (FT_Get_Var_Design_Func)TT_Get_Var_Design,      /* get_var_design */
-    (FT_Set_Instance_Func)  NULL,                   /* set_instance   */
+    (FT_Set_Instance_Func)  TT_Set_Named_Instance,  /* set_instance   */
 
     (FT_Get_Var_Blend_Func) tt_get_var_blend,       /* get_var_blend  */
     (FT_Done_Blend_Func)    tt_done_blend           /* done_blend     */
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index d2365ac..4ad6533 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -2817,6 +2817,90 @@
 
 
   /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Set_Named_Instance                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Set the given named instance, also resetting any further           */
+  /*    variation.                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face           :: A handle to the source face.                     */
+  /*                                                                       */
+  /*    instance_index :: The instance index, starting with value 1.       */
+  /*                      Value 0 indicates to not use an instance.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0~means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF( FT_Error )
+  TT_Set_Named_Instance( TT_Face  face,
+                         FT_UInt  instance_index )
+  {
+    FT_Error    error = FT_ERR( Invalid_Argument );
+    GX_Blend    blend;
+    FT_MM_Var*  mmvar;
+
+    FT_UInt  num_instances;
+
+
+    if ( !face->blend )
+    {
+      if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) )
+        goto Exit;
+    }
+
+    blend = face->blend;
+    mmvar = blend->mmvar;
+
+    num_instances = (FT_UInt)face->root.style_flags >> 16;
+
+    /* `instance_index' starts with value 1, thus `>' */
+    if ( instance_index > num_instances )
+      goto Exit;
+
+    if ( instance_index > 0 && mmvar->namedstyle )
+    {
+      FT_Memory     memory = face->root.memory;
+      SFNT_Service  sfnt   = (SFNT_Service)face->sfnt;
+
+      FT_Var_Named_Style*  named_style;
+      FT_String*           style_name;
+
+
+      named_style = mmvar->namedstyle + instance_index - 1;
+
+      error = sfnt->get_name( face,
+                              (FT_UShort)named_style->strid,
+                              &style_name );
+      if ( error )
+        goto Exit;
+
+      /* set (or replace) 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,
+                                 mmvar->num_axis,
+                                 named_style->coords );
+      if ( error )
+        goto Exit;
+    }
+    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;
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
   /*****                     GX VAR PARSING ROUTINES                   *****/
diff --git a/src/truetype/ttgxvar.h b/src/truetype/ttgxvar.h
index 7e81719..a9a1165 100644
--- a/src/truetype/ttgxvar.h
+++ b/src/truetype/ttgxvar.h
@@ -402,6 +402,10 @@ FT_BEGIN_HEADER
                      FT_Fixed*  coords );
 
   FT_LOCAL( FT_Error )
+  TT_Set_Named_Instance( TT_Face  face,
+                         FT_UInt  instance_index );
+
+  FT_LOCAL( FT_Error )
   tt_face_vary_cvt( TT_Face    face,
                     FT_Stream  stream );
 
diff --git a/src/type1/t1driver.c b/src/type1/t1driver.c
index b319f56..06cb26e 100644
--- a/src/type1/t1driver.c
+++ b/src/type1/t1driver.c
@@ -126,7 +126,7 @@
     (FT_Get_MM_Var_Func)    T1_Get_MM_Var,         /* get_mm_var     */
     (FT_Set_Var_Design_Func)T1_Set_Var_Design,     /* set_var_design */
     (FT_Get_Var_Design_Func)T1_Get_Var_Design,     /* get_var_design */
-    (FT_Set_Instance_Func)  NULL,                  /* set_instance   */
+    (FT_Set_Instance_Func)  T1_Reset_MM_Blend,     /* set_instance   */
 
     (FT_Get_Var_Blend_Func) NULL,                  /* get_var_blend  */
     (FT_Done_Blend_Func)    T1_Done_Blend          /* done_blend     */
diff --git a/src/type1/t1load.c b/src/type1/t1load.c
index 8ac3810..9259df6 100644
--- a/src/type1/t1load.c
+++ b/src/type1/t1load.c
@@ -553,6 +553,18 @@
   }
 
 
+  /* MM fonts don't have named instances, so only the design is reset */
+
+  FT_LOCAL_DEF( FT_Error )
+  T1_Reset_MM_Blend( T1_Face  face,
+                     FT_UInt  instance_index )
+  {
+    FT_UNUSED( instance_index );
+
+    return T1_Set_MM_Blend( face, 0, NULL );
+  }
+
+
   /*************************************************************************/
   /*                                                                       */
   /* Just a wrapper around T1_Set_MM_Design to support the different       */
diff --git a/src/type1/t1load.h b/src/type1/t1load.h
index 2d86984..492ba5a 100644
--- a/src/type1/t1load.h
+++ b/src/type1/t1load.h
@@ -90,6 +90,10 @@ FT_BEGIN_HEADER
                     FT_Long*  coords );
 
   FT_LOCAL( FT_Error )
+  T1_Reset_MM_Blend( T1_Face  face,
+                     FT_UInt  instance_index );
+
+  FT_LOCAL( FT_Error )
   T1_Get_Var_Design( T1_Face    face,
                      FT_UInt    num_coords,
                      FT_Fixed*  coords );