Alexandre Julliard : gdi32: Improve font name localization by not requiring a strict language match.
Alexandre Julliard
julliard at winehq.org
Thu Jun 20 15:31:16 CDT 2013
Module: wine
Branch: master
Commit: b05b637c9179b7b01f21f5fd80e46cf405c04419
URL: http://source.winehq.org/git/wine.git/?a=commit;h=b05b637c9179b7b01f21f5fd80e46cf405c04419
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Jun 20 13:36:34 2013 +0200
gdi32: Improve font name localization by not requiring a strict language match.
---
dlls/gdi32/freetype.c | 114 +++++++++++++++++++++++--------------------------
1 files changed, 53 insertions(+), 61 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 62e1608..dc08fc2 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -1173,69 +1173,74 @@ static void LoadSubstList(void)
}
-/*****************************************************************
- * get_name_table_entry
- *
- * Supply the platform, encoding, language and name ids in req
- * and if the name exists the function will fill in the string
- * and string_len members. The string is owned by FreeType so
- * don't free it. Returns TRUE if the name is found else FALSE.
- */
-static BOOL get_name_table_entry(FT_Face ft_face, FT_SfntName *req)
+static int match_name_table_language( const FT_SfntName *name, LANGID lang )
{
- FT_SfntName name;
- FT_UInt num_names, name_index;
+ LANGID name_lang;
- if(FT_IS_SFNT(ft_face))
+ switch (name->platform_id)
{
- num_names = pFT_Get_Sfnt_Name_Count(ft_face);
-
- for(name_index = 0; name_index < num_names; name_index++)
+ case TT_PLATFORM_MICROSOFT:
+ switch (name->encoding_id)
{
- if(!pFT_Get_Sfnt_Name(ft_face, name_index, &name))
- {
- if((name.platform_id == req->platform_id) &&
- ((name.encoding_id == TT_MS_ID_UNICODE_CS) || (name.encoding_id == TT_MS_ID_SYMBOL_CS)) &&
- (name.language_id == req->language_id) &&
- (name.name_id == req->name_id))
- {
- req->string = name.string;
- req->string_len = name.string_len;
- return TRUE;
- }
- }
+ case TT_MS_ID_UNICODE_CS:
+ case TT_MS_ID_SYMBOL_CS:
+ name_lang = name->language_id;
+ break;
+ default:
+ return 0;
}
+ break;
+ default:
+ return 0;
}
- req->string = NULL;
- req->string_len = 0;
- return FALSE;
+ if (name_lang == lang) return 3;
+ if (PRIMARYLANGID( name_lang ) == PRIMARYLANGID( lang )) return 2;
+ if (name_lang == MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT )) return 1;
+ return 0;
}
-static WCHAR *get_face_name(FT_Face ft_face, FT_UShort name_id, FT_UShort language_id)
+static WCHAR *copy_name_table_string( const FT_SfntName *name )
+{
+ WCHAR *ret;
+ int i;
+
+ ret = HeapAlloc( GetProcessHeap(), 0, name->string_len + sizeof(WCHAR) );
+ for (i = 0; i < name->string_len / 2; i++)
+ ret[i] = (name->string[i * 2] << 8) | name->string[i * 2 + 1];
+ ret[i] = 0;
+ return ret;
+}
+
+static WCHAR *get_face_name(FT_Face ft_face, FT_UShort name_id, LANGID language_id)
{
- WCHAR *ret = NULL;
FT_SfntName name;
+ FT_UInt num_names, name_index;
+ int res, best_lang = 0, best_index = -1;
- name.platform_id = TT_PLATFORM_MICROSOFT;
- name.language_id = language_id;
- name.name_id = name_id;
+ if (!FT_IS_SFNT(ft_face)) return NULL;
- if(get_name_table_entry(ft_face, &name))
- {
- FT_UInt i;
+ num_names = pFT_Get_Sfnt_Name_Count( ft_face );
- /* String is not nul terminated and string_len is a byte length. */
- ret = HeapAlloc(GetProcessHeap(), 0, name.string_len + 2);
- for(i = 0; i < name.string_len / 2; i++)
+ for (name_index = 0; name_index < num_names; name_index++)
+ {
+ if (pFT_Get_Sfnt_Name( ft_face, name_index, &name )) continue;
+ if (name.name_id != name_id) continue;
+ res = match_name_table_language( &name, language_id );
+ if (res > best_lang)
{
- WORD *tmp = (WORD *)&name.string[i * 2];
- ret[i] = GET_BE_WORD(*tmp);
+ best_lang = res;
+ best_index = name_index;
}
- ret[i] = 0;
- TRACE("Got localised name %s\n", debugstr_w(ret));
}
- return ret;
+ if (best_index != -1 && !pFT_Get_Sfnt_Name( ft_face, best_index, &name ))
+ {
+ WCHAR *ret = copy_name_table_string( &name );
+ TRACE( "name %u found platform %u lang %04x %s\n",
+ name_id, name.platform_id, name.language_id, debugstr_w( ret ));
+ return ret;
+ }
+ return NULL;
}
static inline BOOL faces_equal( const Face *f1, const Face *f2 )
@@ -1614,7 +1619,7 @@ static WCHAR *prepend_at(WCHAR *family)
static void get_family_names( FT_Face ft_face, WCHAR **name, WCHAR **english, BOOL vertical )
{
- *english = get_face_name( ft_face, TT_NAME_ID_FONT_FAMILY, TT_MS_LANGID_ENGLISH_UNITED_STATES );
+ *english = get_face_name( ft_face, TT_NAME_ID_FONT_FAMILY, MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT) );
if (!*english) *english = towstr( CP_ACP, ft_face->family_name );
*name = get_face_name( ft_face, TT_NAME_ID_FONT_FAMILY, GetSystemDefaultLCID() );
@@ -1777,16 +1782,9 @@ static Face *create_face( FT_Face ft_face, FT_Long face_index, const char *file,
face->refcount = 1;
face->StyleName = get_face_name( ft_face, TT_NAME_ID_FONT_SUBFAMILY, GetSystemDefaultLangID() );
- if (!face->StyleName)
- face->StyleName = get_face_name( ft_face, TT_NAME_ID_FONT_SUBFAMILY, TT_MS_LANGID_ENGLISH_UNITED_STATES );
- if (!face->StyleName)
- {
- face->StyleName = towstr( CP_ACP, ft_face->style_name );
- }
+ if (!face->StyleName) face->StyleName = towstr( CP_ACP, ft_face->style_name );
face->FullName = get_face_name( ft_face, TT_NAME_ID_FULL_NAME, GetSystemDefaultLangID() );
- if (!face->FullName)
- face->FullName = get_face_name( ft_face, TT_NAME_ID_FULL_NAME, TT_MS_LANGID_ENGLISH_UNITED_STATES );
if (flags & ADDFONT_VERTICAL_FONT)
face->FullName = prepend_at( face->FullName );
@@ -6998,8 +6996,6 @@ static BOOL get_outline_text_metrics(GdiFont *font)
style_nameW = get_face_name( ft_face, TT_NAME_ID_FONT_SUBFAMILY, GetSystemDefaultLangID() );
if (!style_nameW)
- style_nameW = get_face_name( ft_face, TT_NAME_ID_FONT_SUBFAMILY, TT_MS_LANGID_ENGLISH_UNITED_STATES );
- if (!style_nameW)
{
FIXME("failed to read style_nameW for font %s!\n", wine_dbgstr_w(font->name));
style_nameW = towstr( CP_ACP, ft_face->style_name );
@@ -7008,8 +7004,6 @@ static BOOL get_outline_text_metrics(GdiFont *font)
face_nameW = get_face_name( ft_face, TT_NAME_ID_FULL_NAME, GetSystemDefaultLangID() );
if (!face_nameW)
- face_nameW = get_face_name( ft_face, TT_NAME_ID_FULL_NAME, TT_MS_LANGID_ENGLISH_UNITED_STATES );
- if (!face_nameW)
{
FIXME("failed to read face_nameW for font %s!\n", wine_dbgstr_w(font->name));
face_nameW = strdupW(font->name);
@@ -7019,8 +7013,6 @@ static BOOL get_outline_text_metrics(GdiFont *font)
full_nameW = get_face_name( ft_face, TT_NAME_ID_UNIQUE_ID, GetSystemDefaultLangID() );
if (!full_nameW)
- full_nameW = get_face_name( ft_face, TT_NAME_ID_UNIQUE_ID, TT_MS_LANGID_ENGLISH_UNITED_STATES );
- if (!full_nameW)
{
WCHAR fake_nameW[] = {'f','a','k','e',' ','n','a','m','e', 0};
FIXME("failed to read full_nameW for font %s!\n", wine_dbgstr_w(font->name));
More information about the wine-cvs
mailing list