shithub: freetype+ttf2subf

Download patch

ref: 78a1e69517ca067224d6e33beffd25e2ec8361d2
parent: 1fc6937f7fa3bd80edbadc1e3c69d21dd9929e74
author: Chris Liddell <[email protected]>
date: Tue Nov 27 17:24:06 EST 2018

[type1,cff] Add FT_{Set,Get}_MM_WeightVector API calls.

For multiple master fonts, common usage (in Postscript) is to modify
the WeightVector of an existing font instance, this addition
supports that use.

* include/freetype/ftmm.h, src/base/ftmm.c (FT_Set_MM_WeightVector,
FT_Get_MM_WeightVector): New API functions.

* include/freetype/internalservices/svmm.h
(FT_Set_MM_WeightVector_Func, FT_Get_MM_WeightVector_Func): New
function types.
(MultiMasters): Add `set_mm_weightvector' and `get_mm_weightvector'
members.
(FT_DEFINE_SERVICE_MULTIMASTERSREC): Updated.

* src/cffcffdrivr.c (cff_set_mm_weightvector,
cff_get_mm_weightvector): New functions.
(cff_service_multi_masters): Register them.

* src/truetype/ttdriver.c (tt_service_gx_multi_masters): Updated.
This driver doesn't use the new interface.

* src/type1/t1load.c (T1_Set_MM_WeightVector,
T1_Get_MM_WeightVector): New functions.
* src/type1/t1driver.c (t1_service_multi_masters): Register them.
* src/type1/t1load.h: Updated.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2018-11-27  Chris Liddell  <[email protected]>
+
+	[type1,cff] Add FT_{Set,Get}_MM_WeightVector API calls.
+
+	For multiple master fonts, common usage (in Postscript) is to modify
+	the WeightVector of an existing font instance, this addition
+	supports that use.
+
+	* include/freetype/ftmm.h, src/base/ftmm.c (FT_Set_MM_WeightVector,
+	FT_Get_MM_WeightVector): New API functions.
+
+	* include/freetype/internalservices/svmm.h
+	(FT_Set_MM_WeightVector_Func, FT_Get_MM_WeightVector_Func): New
+	function types.
+	(MultiMasters): Add `set_mm_weightvector' and `get_mm_weightvector'
+	members.
+	(FT_DEFINE_SERVICE_MULTIMASTERSREC): Updated.
+
+	* src/cffcffdrivr.c (cff_set_mm_weightvector,
+	cff_get_mm_weightvector): New functions.
+	(cff_service_multi_masters): Register them.
+
+	* src/truetype/ttdriver.c (tt_service_gx_multi_masters): Updated.
+	This driver doesn't use the new interface.
+
+	* src/type1/t1load.c (T1_Set_MM_WeightVector,
+	T1_Get_MM_WeightVector): New functions.
+	* src/type1/t1driver.c (t1_service_multi_masters): Register them.
+	* src/type1/t1load.h: Updated.
+
 2018-11-27  Ben Wagner  <[email protected]>
 
 	[cff] Fix compiler warning (#55105).
--- a/include/freetype/ftmm.h
+++ b/include/freetype/ftmm.h
@@ -563,6 +563,98 @@
 
   /**************************************************************************
    *
+   * @function:
+   *   FT_Set_MM_WeightVector
+   *
+   * @description:
+   *   For Adobe MM fonts, choose an interpolated font design by directly
+   *   setting the weight vector.
+   *
+   *   This function can't be used with TrueType GX or OpenType variation
+   *   fonts.
+   *
+   * @inout:
+   *   face ::
+   *     A handle to the source face.
+   *
+   * @input:
+   *   len ::
+   *     The length of the weight vector array.  If it is larger than the
+   *     number of designs, the extra values are ignored.  If it is less than
+   *     the number of designs, the remaining values are set to zero.
+   *
+   *   weightvector ::
+   *     An array representing the weight vector.
+   *
+   * @return:
+   *   FreeType error code.  0~means success.
+   *
+   * @note:
+   *   Adobe Multiple Master fonts limit the number of designs, and thus the
+   *   length of the weight vector to~16.
+   *
+   *   If `len` is zero and `weightvector` is NULL, 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
+   *   not seem to be enforced, so is not enforced here, either.
+   *
+   * @since:
+   *   2.10
+   */
+  FT_EXPORT( FT_Error )
+  FT_Set_MM_WeightVector( FT_Face    face,
+                          FT_UInt    len,
+                          FT_Fixed*  weightvector );
+
+
+  /**************************************************************************
+   *
+   * @function:
+   *   FT_Get_MM_WeightVector
+   *
+   * @description:
+   *   For Adobe MM fonts, retrieve the current weight vector of the font.
+   *
+   *   This function can't be used with TrueType GX or OpenType variation
+   *   fonts.
+   *
+   * @inout:
+   *   face ::
+   *     A handle to the source face.
+   *
+   *   len ::
+   *     A pointer to the size of the array to be filled.  If the size of the
+   *     array is less than the number of designs, `FT_Err_Invalid_Argument`
+   *     is returned, and `len` is set to the required size (the number of
+   *     designs).  If the size of the array is greater than the number of
+   *     designs, the remaining entries are set to~0.  On successful
+   *     completion, `len` is set to the number of designs (i.e., the number
+   *     of values written to the array).
+   *
+   * @utput:
+   *   weightvector ::
+   *     An array to be filled.
+   *
+   * @return:
+   *   FreeType error code.  0~means success.
+   *
+   * @note:
+   *   Adobe Multiple Master fonts limit the number of designs, and thus the
+   *   length of the WeightVector to~16.
+   *
+   * @since:
+   *   2.10
+   */
+  FT_EXPORT( FT_Error )
+  FT_Get_MM_WeightVector( FT_Face    face,
+                          FT_UInt*   len,
+                          FT_Fixed*  weightvector );
+
+
+  /**************************************************************************
+   *
    * @enum:
    *   FT_VAR_AXIS_FLAG_XXX
    *
--- a/include/freetype/internal/services/svmm.h
+++ b/include/freetype/internal/services/svmm.h
@@ -86,47 +86,63 @@
   typedef void
   (*FT_Done_Blend_Func)( FT_Face );
 
+  typedef FT_Error
+  (*FT_Set_MM_WeightVector_Func)( FT_Face    face,
+                                  FT_UInt    len,
+                                  FT_Fixed*  weight_vector );
 
+  typedef FT_Error
+  (*FT_Get_MM_WeightVector_Func)( FT_Face    face,
+                                  FT_UInt*   len,
+                                  FT_Fixed*  weight_vector );
+
+
   FT_DEFINE_SERVICE( MultiMasters )
   {
-    FT_Get_MM_Func          get_mm;
-    FT_Set_MM_Design_Func   set_mm_design;
-    FT_Set_MM_Blend_Func    set_mm_blend;
-    FT_Get_MM_Blend_Func    get_mm_blend;
-    FT_Get_MM_Var_Func      get_mm_var;
-    FT_Set_Var_Design_Func  set_var_design;
-    FT_Get_Var_Design_Func  get_var_design;
-    FT_Set_Instance_Func    set_instance;
+    FT_Get_MM_Func               get_mm;
+    FT_Set_MM_Design_Func        set_mm_design;
+    FT_Set_MM_Blend_Func         set_mm_blend;
+    FT_Get_MM_Blend_Func         get_mm_blend;
+    FT_Get_MM_Var_Func           get_mm_var;
+    FT_Set_Var_Design_Func       set_var_design;
+    FT_Get_Var_Design_Func       get_var_design;
+    FT_Set_Instance_Func         set_instance;
+    FT_Set_MM_WeightVector_Func  set_mm_weightvector;
+    FT_Get_MM_WeightVector_Func  get_mm_weightvector;
 
     /* for internal use; only needed for code sharing between modules */
-    FT_Get_Var_Blend_Func   get_var_blend;
-    FT_Done_Blend_Func      done_blend;
+    FT_Get_Var_Blend_Func  get_var_blend;
+    FT_Done_Blend_Func     done_blend;
   };
 
 
-#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_,          \
-                                           get_mm_,         \
-                                           set_mm_design_,  \
-                                           set_mm_blend_,   \
-                                           get_mm_blend_,   \
-                                           get_mm_var_,     \
-                                           set_var_design_, \
-                                           get_var_design_, \
-                                           set_instance_,   \
-                                           get_var_blend_,  \
-                                           done_blend_ )    \
-  static const FT_Service_MultiMastersRec  class_ =         \
-  {                                                         \
-    get_mm_,                                                \
-    set_mm_design_,                                         \
-    set_mm_blend_,                                          \
-    get_mm_blend_,                                          \
-    get_mm_var_,                                            \
-    set_var_design_,                                        \
-    get_var_design_,                                        \
-    set_instance_,                                          \
-    get_var_blend_,                                         \
-    done_blend_                                             \
+#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_,            \
+                                           get_mm_,           \
+                                           set_mm_design_,    \
+                                           set_mm_blend_,     \
+                                           get_mm_blend_,     \
+                                           get_mm_var_,       \
+                                           set_var_design_,   \
+                                           get_var_design_,   \
+                                           set_instance_,     \
+                                           set_weightvector_, \
+                                           get_weightvector_, \
+                                           get_var_blend_,    \
+                                           done_blend_ )      \
+  static const FT_Service_MultiMastersRec  class_ =           \
+  {                                                           \
+    get_mm_,                                                  \
+    set_mm_design_,                                           \
+    set_mm_blend_,                                            \
+    get_mm_blend_,                                            \
+    get_mm_var_,                                              \
+    set_var_design_,                                          \
+    get_var_design_,                                          \
+    set_instance_,                                            \
+    set_weightvector_,                                        \
+    get_weightvector_,                                        \
+    get_var_blend_,                                           \
+    done_blend_                                               \
   };
 
   /* */
--- a/src/base/ftmm.c
+++ b/src/base/ftmm.c
@@ -202,6 +202,67 @@
   /* documentation is in ftmm.h */
 
   FT_EXPORT_DEF( FT_Error )
+  FT_Set_MM_WeightVector( FT_Face    face,
+                          FT_UInt    len,
+                          FT_Fixed*  weightvector )
+  {
+    FT_Error                 error;
+    FT_Service_MultiMasters  service;
+
+
+    /* check of `face' delayed to `ft_face_get_mm_service' */
+
+    if ( len && !weightvector )
+      return FT_THROW( Invalid_Argument );
+
+    error = ft_face_get_mm_service( face, &service );
+    if ( !error )
+    {
+      error = FT_ERR( Invalid_Argument );
+      if ( service->set_mm_weightvector )
+        error = service->set_mm_weightvector( face, len, weightvector );
+    }
+
+    /* enforce recomputation of auto-hinting data */
+    if ( !error && face->autohint.finalizer )
+    {
+      face->autohint.finalizer( face->autohint.data );
+      face->autohint.data = NULL;
+    }
+
+    return error;
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Get_MM_WeightVector( FT_Face    face,
+                          FT_UInt*   len,
+                          FT_Fixed*  weightvector )
+  {
+    FT_Error                 error;
+    FT_Service_MultiMasters  service;
+
+
+    /* check of `face' delayed to `ft_face_get_mm_service' */
+
+    if ( len && !weightvector )
+      return FT_THROW( Invalid_Argument );
+
+    error = ft_face_get_mm_service( face, &service );
+    if ( !error )
+    {
+      error = FT_ERR( Invalid_Argument );
+      if ( service->get_mm_weightvector )
+        error = service->get_mm_weightvector( face, len, weightvector );
+    }
+
+    return error;
+  }
+
+
+  /* documentation is in ftmm.h */
+
+  FT_EXPORT_DEF( FT_Error )
   FT_Set_Var_Design_Coordinates( FT_Face    face,
                                  FT_UInt    num_coords,
                                  FT_Fixed*  coords )
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -868,6 +868,30 @@
 
 
   static FT_Error
+  cff_set_mm_weightvector( CFF_Face   face,
+                           FT_UInt    len,
+                           FT_Fixed*  weightvector )
+  {
+    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+
+    return mm->set_mm_weightvector( FT_FACE( face ), len, weightvector );
+  }
+
+
+  static FT_Error
+  cff_get_mm_weightvector( CFF_Face   face,
+                           FT_UInt*   len,
+                           FT_Fixed*  weightvector )
+  {
+    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+
+    return mm->get_mm_weightvector( FT_FACE( face ), len, weightvector );
+  }
+
+
+  static FT_Error
   cff_get_mm_var( CFF_Face     face,
                   FT_MM_Var*  *master )
   {
@@ -916,17 +940,19 @@
   FT_DEFINE_SERVICE_MULTIMASTERSREC(
     cff_service_multi_masters,
 
-    (FT_Get_MM_Func)        NULL,                   /* get_mm         */
-    (FT_Set_MM_Design_Func) NULL,                   /* set_mm_design  */
-    (FT_Set_MM_Blend_Func)  cff_set_mm_blend,       /* set_mm_blend   */
-    (FT_Get_MM_Blend_Func)  cff_get_mm_blend,       /* get_mm_blend   */
-    (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)  cff_set_instance,       /* set_instance   */
+    (FT_Get_MM_Func)             NULL,                    /* get_mm              */
+    (FT_Set_MM_Design_Func)      NULL,                    /* set_mm_design       */
+    (FT_Set_MM_Blend_Func)       cff_set_mm_blend,        /* set_mm_blend        */
+    (FT_Get_MM_Blend_Func)       cff_get_mm_blend,        /* get_mm_blend        */
+    (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)       cff_set_instance,        /* set_instance        */
+    (FT_Set_MM_WeightVector_Func)cff_set_mm_weightvector, /* set_mm_weightvector */
+    (FT_Get_MM_WeightVector_Func)cff_get_mm_weightvector, /* get_mm_weightvector */
 
-    (FT_Get_Var_Blend_Func) cff_get_var_blend,      /* get_var_blend  */
-    (FT_Done_Blend_Func)    cff_done_blend          /* done_blend     */
+    (FT_Get_Var_Blend_Func)      cff_get_var_blend,       /* get_var_blend       */
+    (FT_Done_Blend_Func)         cff_done_blend           /* done_blend          */
   )
 
 
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -498,17 +498,19 @@
   FT_DEFINE_SERVICE_MULTIMASTERSREC(
     tt_service_gx_multi_masters,
 
-    (FT_Get_MM_Func)        NULL,                   /* get_mm         */
-    (FT_Set_MM_Design_Func) NULL,                   /* set_mm_design  */
-    (FT_Set_MM_Blend_Func)  TT_Set_MM_Blend,        /* set_mm_blend   */
-    (FT_Get_MM_Blend_Func)  TT_Get_MM_Blend,        /* get_mm_blend   */
-    (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)  TT_Set_Named_Instance,  /* set_instance   */
+    (FT_Get_MM_Func)             NULL,                  /* get_mm              */
+    (FT_Set_MM_Design_Func)      NULL,                  /* set_mm_design       */
+    (FT_Set_MM_Blend_Func)       TT_Set_MM_Blend,       /* set_mm_blend        */
+    (FT_Get_MM_Blend_Func)       TT_Get_MM_Blend,       /* get_mm_blend        */
+    (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)       TT_Set_Named_Instance, /* set_instance        */
+    (FT_Set_MM_WeightVector_Func)NULL,                  /* set_mm_weightvector */
+    (FT_Get_MM_WeightVector_Func)NULL,                  /* get_mm_weightvector */
 
-    (FT_Get_Var_Blend_Func) tt_get_var_blend,       /* get_var_blend  */
-    (FT_Done_Blend_Func)    tt_done_blend           /* done_blend     */
+    (FT_Get_Var_Blend_Func)      tt_get_var_blend,      /* get_var_blend       */
+    (FT_Done_Blend_Func)         tt_done_blend          /* done_blend          */
   )
 
   FT_DEFINE_SERVICE_METRICSVARIATIONSREC(
--- a/src/type1/t1driver.c
+++ b/src/type1/t1driver.c
@@ -122,17 +122,19 @@
 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
   static const FT_Service_MultiMastersRec  t1_service_multi_masters =
   {
-    (FT_Get_MM_Func)        T1_Get_Multi_Master,   /* get_mm         */
-    (FT_Set_MM_Design_Func) T1_Set_MM_Design,      /* set_mm_design  */
-    (FT_Set_MM_Blend_Func)  T1_Set_MM_Blend,       /* set_mm_blend   */
-    (FT_Get_MM_Blend_Func)  T1_Get_MM_Blend,       /* get_mm_blend   */
-    (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)  T1_Reset_MM_Blend,     /* set_instance   */
+    (FT_Get_MM_Func)             T1_Get_Multi_Master,    /* get_mm              */
+    (FT_Set_MM_Design_Func)      T1_Set_MM_Design,       /* set_mm_design       */
+    (FT_Set_MM_Blend_Func)       T1_Set_MM_Blend,        /* set_mm_blend        */
+    (FT_Get_MM_Blend_Func)       T1_Get_MM_Blend,        /* get_mm_blend        */
+    (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)       T1_Reset_MM_Blend,      /* set_instance        */
+    (FT_Set_MM_WeightVector_Func)T1_Set_MM_WeightVector, /* set_mm_weightvector */
+    (FT_Get_MM_WeightVector_Func)T1_Get_MM_WeightVector, /* get_mm_weightvector */
 
-    (FT_Get_Var_Blend_Func) NULL,                  /* get_var_blend  */
-    (FT_Done_Blend_Func)    T1_Done_Blend          /* done_blend     */
+    (FT_Get_Var_Blend_Func)      NULL,                   /* get_var_blend       */
+    (FT_Done_Blend_Func)         T1_Done_Blend           /* done_blend          */
   };
 #endif
 
--- a/src/type1/t1load.c
+++ b/src/type1/t1load.c
@@ -481,6 +481,75 @@
 
 
   FT_LOCAL_DEF( FT_Error )
+  T1_Set_MM_WeightVector( T1_Face    face,
+                          FT_UInt    len,
+                          FT_Fixed*  weightvector )
+  {
+    PS_Blend  blend = face->blend;
+    FT_UInt   i, n;
+
+
+    if ( !blend )
+     return FT_THROW( Invalid_Argument );
+
+    if ( !len && !weightvector )
+    {
+      for ( i = 0; i < blend->num_designs; i++ )
+        blend->weight_vector[i] = blend->default_weight_vector[i];
+    }
+    else
+    {
+      if ( !weightvector )
+        return FT_THROW( Invalid_Argument );
+
+      n = len < blend->num_designs ? len : blend->num_designs;
+
+      for ( i = 0; i < n; i++ )
+        blend->weight_vector[i] = weightvector[i];
+
+      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;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  T1_Get_MM_WeightVector( T1_Face    face,
+                          FT_UInt*   len,
+                          FT_Fixed*  weightvector )
+  {
+    PS_Blend  blend = face->blend;
+    FT_UInt   i;
+
+
+    if ( !blend )
+      return FT_THROW( Invalid_Argument );
+
+    if ( *len < blend->num_designs )
+    {
+      *len = blend->num_designs;
+      return FT_THROW( Invalid_Argument );
+    }
+
+    for ( i = 0; i < blend->num_designs; i++ )
+      weightvector[i] = blend->weight_vector[i];
+    for ( ; i < *len; i++ )
+      weightvector[i] = (FT_Fixed)0;
+
+    *len = blend->num_designs;
+
+    return FT_Err_Ok;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
   T1_Set_MM_Design( T1_Face   face,
                     FT_UInt   num_coords,
                     FT_Long*  coords )
--- a/src/type1/t1load.h
+++ b/src/type1/t1load.h
@@ -106,6 +106,16 @@
   FT_LOCAL( void )
   T1_Done_Blend( T1_Face  face );
 
+  FT_LOCAL( FT_Error )
+  T1_Set_MM_WeightVector( T1_Face    face,
+                          FT_UInt    len,
+                          FT_Fixed*  weightvector );
+
+  FT_LOCAL( FT_Error )
+  T1_Get_MM_WeightVector( T1_Face    face,
+                          FT_UInt*   len,
+                          FT_Fixed*  weightvector );
+
 #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */