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