[Top][All Lists]
[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?