freetype
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [ft] Different Values from Freetype Face


From: mpsuzuki
Subject: Re: [ft] Different Values from Freetype Face
Date: Fri, 15 Jan 2010 12:44:03 +0900

Dear David and Werner,

I want to ask about the right direction how to handle
preferred family/subfamily names by FreeType2.

Background
----------
OpenType had ever introduced `preferred family' and `preferred
subfamily' entries in name table.

Some legacy font management system could hold only 4 faces
per 1 family (e.g. XXX, XXX-Bold, XXX-Oblique, XXX-BoldOblique),
it was difficult to use family name entry of TrueType name
table to name an intuitive font family (e.g.  XXX-Light,
XXX-Regular, XXX-Book, XXX-Bold, XXX-Heavy etc). In such
case, the font designers were forced to split weight or
style informations to family & subfamily names. As a result,
they could not form an intuitive font family. Typical example
would be `Arial', `Arial Condensed' and `Arial Black' until
Microsoft Windows XP SP2.

When newer font management system could hold many faces per
a family, OpenType spec designers introduced `preferred family'
and `preferred subfamily' to store the family and styles 
regardless with the legacy restriction.

* The newer system prioritizes preferred family & subfamily names.

* The legacy system use original family & subfamily names
  and these preferred names are ignored.

FreeType2 Implementation
------------------------

The initial support of preferred names was already included
in the earliest version of FreeType 1. However, these entries
are not reflected to the format-independent names of FT_Face
object (FT_Face->family_name etc), until the patch by Kornfeld
Eliyahu Peter posted on 2004. After his patch, FreeType2
always prioritizes the preferred family names.

Problem and why it's asked today, not 5 years ago
-------------------------------------------------

Among the fonts bundled to inexpensive office products (e.g.
Microsoft products), it seems that the font families using
preferred family names were not so popular during several
years. But, in these few years, finally even Microsoft products
start to bundle the font using preferred family names.

# OpenType spec notes the preferred family names should
# be used when they are different from original family
# names, but there are many TrueType fonts that have same
# string in both family names, e.g. DejaVu. I'm not sure
# if it is harmful.

Among the softwares using FreeType2, some softwares (e.g.
fontconfig) had been aware of the multiple family names
and handle them equally, but others (e.g. Wine, Qt for X11)
are not aware of, or handle them differently.

As a result, some people using the softwares handling 2
family names differently could be confused by the change
of FT_Face->family_name.

What is expected for back compatibility?
----------------------------------------

I guess some people want to keep to ignore preferred family
names, even if their application has no limitation about
the number of the faces in single family, to avoid the
family name changing issue.

For example, thinking about an application running on Microsoft
Windows that searches the font only by FT_Face->family_name and
its application data refers a font only by FT_Face->family_name.
When its "Arial Black" is updated to new revison that has
preferred family name "Arial", the application cannot find
"Arial Black" anymore.

# Oops, this is slightly different from the problem Andreas
# reported. In his case, he updated FreeType2 from very very
# old FreeType2 without preferred family name prioritization
# to newer one. Maybe such long jump upgrade is out of scope
# of the most FreeType2 developers.

So some people may want a switch to make FreeType2 ignore the
preferred family names (and WWS family names too). What I
can do for them? Following is the list of my several ideas.

1) Propose a hardwire patch to ignore preferred family names.

 1-a) Write a documentation how to do that for freetype2/docs/

 1-b) Insert a cpp macro switch to do that, aslike the switch
      for bytecode interpreter & patented hinting.

2) Add a switch to enable/disable preferred family names in
   run-time.

 2-a) Add the switch only to the APIs taking optional parameters,
      like FT_Open_Face(), and the client should specify the
      switch in each font handle creation.

 2-b) Add the switch to FT_Library handle, to hide the default
      parameters in the font handle creation. It can changes
      the behaviour of popular APIs like FT_New_Face() taking
      no optional parameters.
      
 2-c) Use environmental variable to enable/disable preferred
      family names.

Please give me your comments which is the appropriate way.

Regards,
mpsuzuki


P.S.
Following is my experimental patch to implement 2-a & 2-b.

2-a)

Add `FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY' and
`FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY' tags
to pass FT_Open_Face() etc.

diff --git a/include/freetype/ftsnames.h b/include/freetype/ftsnames.h
index f20b409..50ee08c 100644
--- a/include/freetype/ftsnames.h
+++ b/include/freetype/ftsnames.h
@@ -160,6 +160,22 @@ FT_BEGIN_HEADER
                     FT_SfntName  *aname );
 
 
+  /***************************************************************************
+   *
+   * @constant:
+   *   FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY
+   *   FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY
+   *
+   * @description:
+   *   A constant used as the tag of @FT_Parameter structures to make
+   *   FT_Open_Face() ignore preferred family & preferred subfamily names
+   *   in `name' table since OpenType version 1.4. For back compatibility
+   *   with legacy systems which has 4-face-per-family restriction.
+   *
+   */
+#define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY     FT_MAKE_TAG( 'i', 'g', 'p', 
'f' )
+#define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY  FT_MAKE_TAG( 'i', 'g', 'p', 
's' )
+
   /* */
 
 
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index cef3cd9..f83e1ba 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -26,6 +26,7 @@
 #include FT_TRUETYPE_IDS_H
 #include FT_TRUETYPE_TAGS_H
 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
+#include FT_SFNT_NAMES_H
 #include "sferrors.h"
 
 #ifdef TT_CONFIG_OPTION_BDF
@@ -527,13 +528,27 @@
 #endif
     FT_Bool       has_outline;
     FT_Bool       is_apple_sbit;
+    FT_Bool       ignore_preferred_family = FALSE;
+    FT_Bool       ignore_preferred_subfamily = FALSE;
 
     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
 
     FT_UNUSED( face_index );
-    FT_UNUSED( num_params );
-    FT_UNUSED( params );
 
+    /* Check parameters */
+    
+    {
+      FT_Int  i;
+
+
+      for ( i = 0; i < num_params; i++ )
+      {
+        if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY )
+          ignore_preferred_family = TRUE;
+        else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY )
+          ignore_preferred_subfamily = TRUE;
+      }
+    }
 
     /* Load tables */
 
@@ -724,27 +739,27 @@
 
     if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 )
     {
-      GET_NAME( PREFERRED_FAMILY, &face->root.family_name );
-      if ( !face->root.family_name )
-        GET_NAME( FONT_FAMILY, &face->root.family_name );
+      GET_NAME( FONT_FAMILY, &face->root.family_name );
+      if ( !face->root.family_name || !ignore_preferred_family )
+        GET_NAME( PREFERRED_FAMILY, &face->root.family_name );
 
-      GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );
-      if ( !face->root.style_name )
-        GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
+      GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
+      if ( !face->root.style_name || !ignore_preferred_subfamily )
+        GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );
     }
     else
     {
       GET_NAME( WWS_FAMILY, &face->root.family_name );
       if ( !face->root.family_name )
-        GET_NAME( PREFERRED_FAMILY, &face->root.family_name );
-      if ( !face->root.family_name )
         GET_NAME( FONT_FAMILY, &face->root.family_name );
+      if ( !face->root.family_name || !ignore_preferred_family )
+        GET_NAME( PREFERRED_FAMILY, &face->root.family_name );
 
       GET_NAME( WWS_SUBFAMILY, &face->root.style_name );
       if ( !face->root.style_name )
-        GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );
-      if ( !face->root.style_name )
         GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
+      if ( !face->root.style_name || !ignore_preferred_subfamily )
+        GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );
     }
 
     /* now set up root fields */

2-b)
In addition to 2-a patch in above, following patch inserts
the default parameters in FT_Library, FT_New_Face() etc pass
these default parameters to FT_Open_Face() etc. The default
parameters can be changed by FT_SetDefaultNewFaceParam_FreeType().

diff --git a/include/freetype/internal/ftobjs.h 
b/include/freetype/internal/ftobjs.h
index 574cf58..307d86d 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -808,6 +808,10 @@ FT_BEGIN_HEADER
   /*    pic_container    :: Contains global structs and tables, instead    */
   /*                        of defining them globallly.                    */
   /*                                                                       */
+  /*    num_new_face_param :: The number of arguments in new_face_arg[]    */
+  /*                                                                       */
+  /*    new_face_param   :: Default arguments to be set for FT_New_Face()  */
+  /*                                                                       */
 
   typedef struct  FT_LibraryRec_
   {
@@ -843,6 +847,9 @@ FT_BEGIN_HEADER
     FT_PIC_Container   pic_container;
 #endif
 
+    FT_Int             num_new_face_param;
+    FT_Parameter*      new_face_param;
+
   } FT_LibraryRec;
 
 
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index c74976a..496a7de 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -4208,6 +4212,9 @@
     library->version_minor = FREETYPE_MINOR;
     library->version_patch = FREETYPE_PATCH;
 
+    library->num_new_face_param = 0;
+    library->new_face_param = NULL;
+
     /* That's ok now */
     *alibrary = library;
 
@@ -4338,6 +4345,10 @@
     ft_pic_container_destroy( library );
 #endif
 
+    /* Destroy default parameters for FT_New_Face() */
+    if ( library->new_face_param )
+      FT_FREE( library->new_face_param );
+
     FT_FREE( library );
     return FT_Err_Ok;
   }


diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index e74f319..1d2ec70 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -1764,6 +1764,29 @@ FT_BEGIN_HEADER
 
   /*************************************************************************/
   /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_SetDefaultNewFaceParam_FreeType                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library            :: A handle to the target library object.       */
+  /*                                                                       */
+  /*    num_new_face_param :: The size of new_face_param[].                */
+  /*                                                                       */
+  /*    new_face_param     :: The parameters to be set in FT_New_Face.     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0~means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_SetDefaultNewFaceParam_FreeType( FT_Library     library,
+                                      FT_Int         num_new_face_param,
+                                      FT_Parameter*  new_face_param );
+
+
+  /*************************************************************************/
+  /*                                                                       */
   /* <Struct>                                                              */
   /*    FT_Open_Args                                                       */
   /*                                                                       */
diff --git a/src/base/ftinit.c b/src/base/ftinit.c
index f94f25a..f6fcb45 100644
--- a/src/base/ftinit.c
+++ b/src/base/ftinit.c
@@ -229,6 +229,41 @@ Exit:
 
 
   /* documentation is in freetype.h */
+  FT_EXPORT( FT_Error )
+  FT_SetDefaultNewFaceParam_FreeType( FT_Library     library,
+                                      FT_Int         num_new_face_param,
+                                      FT_Parameter*  new_face_param )
+  {
+    FT_Memory  memory;
+    FT_Error   error;
+
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    memory = library->memory;
+
+    if ( library->num_new_face_param > 0 )
+      error = FT_REALLOC( library->new_face_param,
+                          sizeof( FT_Parameter ) * library->num_new_face_param,
+                          sizeof( FT_Parameter ) * num_new_face_param );
+    else
+      error = FT_ALLOC( library->new_face_param,
+                        sizeof( FT_Parameter ) * num_new_face_param );
+
+    if ( error )
+      return error;
+
+    library->num_new_face_param = num_new_face_param;
+    ft_memcpy( library->new_face_param,
+               new_face_param,
+               sizeof( FT_Parameter ) * num_new_face_param );
+
+    return FT_Err_Ok;
+  }
+
+
+  /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_Error )
   FT_Done_FreeType( FT_Library  library )

diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index c74976a..496a7de 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -1154,6 +1154,10 @@
     args.pathname = (char*)pathname;
     args.stream   = NULL;
 
+    args.flags      |= FT_OPEN_PARAMS;
+    args.num_params  = library->num_new_face_param;
+    args.params      = library->new_face_param;
+
     return FT_Open_Face( library, &args, face_index, aface );
   }
 

diff --git a/builds/mac/ftmac.c b/builds/mac/ftmac.c
index c974f67..c257e2a 100644
--- a/builds/mac/ftmac.c
+++ b/builds/mac/ftmac.c
@@ -1402,6 +1402,12 @@ typedef short ResourceIndex;
     /* let it fall through to normal loader (.ttf, .otf, etc.) */
     args.flags    = FT_OPEN_PATHNAME;
     args.pathname = (char*)pathname;
+
+    /* Set default parameters for FT_New_Face() */
+    args.flags      |= FT_OPEN_PARAMS;
+    args.num_params  = library->num_new_face_param;
+    args.params      = library->new_face_param;
+
     return FT_Open_Face( library, &args, face_index, aface );
   }
 
@@ -1455,6 +1461,12 @@ typedef short ResourceIndex;
     /* fallback to datafork font */
     args.flags    = FT_OPEN_PATHNAME;
     args.pathname = (char*)pathname;
+
+    /* Set default parameters for FT_New_Face() */
+    args.flags      |= FT_OPEN_PARAMS;
+    args.num_params  = library->num_new_face_param;
+    args.params      = library->new_face_param;
+
     return FT_Open_Face( library, &args, face_index, aface );
 
 #endif /* HAVE_FSREF */
@@ -1512,6 +1524,12 @@ typedef short ResourceIndex;
     /* fallback to datafork font */
     args.flags    = FT_OPEN_PATHNAME;
     args.pathname = (char*)pathname;
+
+    /* Set default parameters for FT_New_Face() */
+    args.flags      |= FT_OPEN_PARAMS;
+    args.num_params  = library->num_new_face_param;
+    args.params      = library->new_face_param;
+
     return FT_Open_Face( library, &args, face_index, aface );
 
 #else
diff --git a/src/base/ftmac.c b/src/base/ftmac.c
index 63f927d..f53938d 100644
--- a/src/base/ftmac.c
+++ b/src/base/ftmac.c
@@ -973,6 +973,12 @@
     /* let it fall through to normal loader (.ttf, .otf, etc.) */
     args.flags    = FT_OPEN_PATHNAME;
     args.pathname = (char*)pathname;
+
+    /* Set default parameters for FT_New_Face() */
+    args.flags      |= FT_OPEN_PARAMS;
+    args.num_params  = library->num_new_face_param;
+    args.params      = library->new_face_param;
+
     return FT_Open_Face( library, &args, face_index, aface );
   }
 
@@ -1014,6 +1020,12 @@
     /* fallback to datafork font */
     args.flags    = FT_OPEN_PATHNAME;
     args.pathname = (char*)pathname;
+
+    /* Set default parameters for FT_New_Face() */
+    args.flags      |= FT_OPEN_PARAMS;
+    args.num_params  = library->num_new_face_param;
+    args.params      = library->new_face_param;
+
     return FT_Open_Face( library, &args, face_index, aface );
   }
 





On Thu, 7 Jan 2010 20:28:38 +0900
address@hidden wrote:

>Hi,
>
>Could you post sample program, or the result of "ftdump -n"
>(in freetype2-demos) for your font? In my case, the result
>of ftdump is same with your former case.
>
>There is 1 face in this file.
>
>----- Face number: 0 -----
>
>font name entries
>   family:     Arial Black
>   style:      Regular
>   postscript: Arial-Black
>
>font type entries
>   FreeType driver: truetype
>   sfnt wrapped:    yes
>   type:            scalable
>   direction:       horizontal
>   fixed width:     no
>   glyph names:     yes
>   EM size:         2048
>   global BBox:     (-397,-628):(3456,2219)
>   ascent:          2254
>   descent:         -634
>   text height:     2888
>   glyph count: 669
>
>font string entries
>   copyright       [Macintosh]:
>      "Digitized data copyright The Monotype Corporation 1991-1995. All rights 
> reserved. Arial is a trademark of The Monotype Corporation which may be 
> registered in certain jurisdictions."
>   font family     [Macintosh]:
>      "Arial Black"
>   font subfamily  [Macintosh]:
>      "Regular"
>   unique ID       [Macintosh]:
>      "Monotype - Arial Black Regular"
>   full name       [Macintosh]:
>      "Arial Black"
>   version string  [Macintosh]:
>      "Version 2.35"
>   PostScript name [Macintosh]:
>      "Arial-Black"
>...
>
>Regards,
>mpsuzuki
>
>On Thu, 7 Jan 2010 10:56:25 +0000
>"Andreas Heinrich" <address@hidden> wrote:
>>I'm used an older (2003) Freetype Version until now.
>>Because of Unicode i changed to a newer Version (2007).
>> 
>>I load a Font via FT_New_Face into FT_Face...
>> 
>>In former FreeType.dll i get for some Fonts different Values for 
>>FT_Face.family_name and
>>FT_Face.style_name in comparison with the new version.
>> 
>>For example the font ariblk.ttf from windows: 
>> 
>>former : 
>>FT_Face.family_name  : Arial Black
>>FT_Face.style_name   : Regular
>> 
>>now : 
>>FT_Face.family_name  : Arial 
>>FT_Face.style_name   : Black
>>
>>For my application these changes are extremly distracting. Why these 
>>parameters changed?
>>Is it possible to get the old parameters with the newer Version?




reply via email to

[Prev in Thread] Current Thread [Next in Thread]