Localized font name

Kusanagi Kouichi slash at ma.neweb.ne.jp
Thu Jul 29 15:32:56 CDT 2004


Changelog
  * WineEngCreateFontInstance() and WineEngEnumFonts() accept
    localized font name.
  * WineEngEnumFonts() passes localized font name to callback
    if localized name which matches current locale exists.
-------------- next part --------------
--- dlls/gdi/freetype.c.orig	2004-07-23 04:42:31.000000000 +0900
+++ dlls/gdi/freetype.c	2004-07-30 05:10:26.000000000 +0900
@@ -36,6 +36,7 @@
 #include "winerror.h"
 #include "winreg.h"
 #include "wingdi.h"
+#include "winnls.h"
 #include "gdi.h"
 #include "gdi_private.h"
 #include "wine/unicode.h"
@@ -100,6 +101,8 @@ static void *ft_handle = NULL;
 MAKE_FUNCPTR(FT_Vector_Unit);
 MAKE_FUNCPTR(FT_Done_Face);
 MAKE_FUNCPTR(FT_Get_Char_Index);
+MAKE_FUNCPTR(FT_Get_Sfnt_Name);
+MAKE_FUNCPTR(FT_Get_Sfnt_Name_Count);
 MAKE_FUNCPTR(FT_Get_Sfnt_Table);
 MAKE_FUNCPTR(FT_Init_FreeType);
 MAKE_FUNCPTR(FT_Load_Glyph);
@@ -172,6 +175,7 @@ typedef struct tagFace {
     BOOL external; /* TRUE if we should manually add this font to the registry */
     struct tagFace *next;
     struct tagFamily *family;
+    struct tagName *name;
 } Face;
 
 typedef struct tagFamily {
@@ -180,6 +184,13 @@ typedef struct tagFamily {
     struct tagFamily *next;
 } Family;
 
+typedef struct tagName {
+    WORD lang;
+    WCHAR *FamilyName;
+    WCHAR *StyleName;
+    struct tagName *next;
+} Name;
+
 typedef struct {
     GLYPHMETRICS gm;
     INT adv; /* These three hold to widths of the unrotated chars */
@@ -192,6 +203,7 @@ struct tagGdiFont {
     FT_Face ft_face;
     XFORM xform;
     LPWSTR name;
+    LPWSTR style_name;
     int charset;
     BOOL fake_italic;
     BOOL fake_bold;
@@ -493,6 +505,93 @@ static BOOL AddFontFileToList(const char
             (*insertface)->font_version = pHeader ? pHeader->Font_Revision : 0;
             (*insertface)->family = *pfamily;
             (*insertface)->external = (flags & ADDFONT_EXTERNAL_FONT) ? TRUE : FALSE;
+            (*insertface)->name = NULL;
+
+	    for (i = pFT_Get_Sfnt_Name_Count(ft_face); i-- > 0;)
+	    {
+		FT_SfntName name;
+		Name *pname;
+		WCHAR *str;
+		int j;
+		UINT codepage;
+
+		if (pFT_Get_Sfnt_Name(ft_face, i, &name) ||
+		    name.platform_id != 3 ||
+		    (name.name_id != 1 && name.name_id != 2))
+		{
+		    continue;
+		}
+
+		for (pname = (*insertface)->name; pname != NULL; pname = pname->next)
+		{
+		    if (pname->lang == name.language_id)
+		    {
+			break;
+		    }
+		}
+		if (pname == NULL)
+		{
+		    pname = HeapAlloc(GetProcessHeap(), 0, sizeof (Name));
+		    if (pname == NULL)
+		    {
+			continue;
+		    }
+		    pname->lang = name.language_id;
+		    pname->FamilyName = FamilyW;
+		    pname->StyleName = StyleW;
+		    pname->next = (*insertface)->name;
+		    (*insertface)->name = pname;
+		}
+
+		switch (name.encoding_id)
+		{
+		case 1:
+		    len = name.string_len / 2;
+		    str = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR));
+		    if (str == NULL)
+		    {
+			continue;
+		    }
+		    for (j = 0; j < len; ++j)
+		    {
+			str[j] = *name.string++ * 256;
+			str[j] += *name.string++;
+		    }
+		    break;
+		case 2:
+		    codepage = 932;
+		    goto conv;
+		case 3:
+		    codepage = 936;
+		    goto conv;
+		case 4:
+		    codepage = 950;
+		    goto conv;
+		case 5:
+		    codepage = 949;
+		conv:
+		    len = MultiByteToWideChar(codepage, 0, name.string, name.string_len, NULL, 0);
+		    str = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR));
+		    if (str == NULL)
+		    {
+			continue;
+		    }
+		    MultiByteToWideChar(codepage, 0, name.string, name.string_len, str, len);
+		    break;
+		default:
+		    continue;
+		}
+		str[len] = '\0';
+
+		if (name.name_id == 1)
+		{
+		    pname->FamilyName = str;
+		}
+		else
+		{
+		    pname->StyleName = str;
+		}
+	    }
 
             if(FT_IS_SCALABLE(ft_face)) {
                 memset(&(*insertface)->size, 0, sizeof((*insertface)->size));
@@ -604,15 +703,6 @@ static void DumpSubstList(void)
     return;
 }
 
-static LPWSTR strdupW(LPWSTR p)
-{
-    LPWSTR ret;
-    DWORD len = (strlenW(p) + 1) * sizeof(WCHAR);
-    ret = HeapAlloc(GetProcessHeap(), 0, len);
-    memcpy(ret, p, len);
-    return ret;
-}
-
 static void split_subst_info(NameCs *nc, LPSTR str)
 {
     CHAR *p = strrchr(str, ',');
@@ -1053,6 +1143,8 @@ BOOL WineEngInit(void)
     LOAD_FUNCPTR(FT_Vector_Unit)
     LOAD_FUNCPTR(FT_Done_Face)
     LOAD_FUNCPTR(FT_Get_Char_Index)
+    LOAD_FUNCPTR(FT_Get_Sfnt_Name)
+    LOAD_FUNCPTR(FT_Get_Sfnt_Name_Count)
     LOAD_FUNCPTR(FT_Get_Sfnt_Table)
     LOAD_FUNCPTR(FT_Init_FreeType)
     LOAD_FUNCPTR(FT_Load_Glyph)
@@ -1339,7 +1431,6 @@ static void free_font(GdiFont font)
 {
     if (font->ft_face) pFT_Done_Face(font->ft_face);
     if (font->potm) HeapFree(GetProcessHeap(), 0, font->potm);
-    if (font->name) HeapFree(GetProcessHeap(), 0, font->name);
     HeapFree(GetProcessHeap(), 0, font->gm);
     HeapFree(GetProcessHeap(), 0, font);
 }
@@ -1507,6 +1598,9 @@ GdiFont WineEngCreateFontInstance(DC *dc
     BOOL bd, it, can_use_bitmap;
     LOGFONTW lf;
     CHARSETINFO csi;
+    WORD lang;
+    WCHAR *family_name;
+    Name *name;
 
     if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL;
     can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE;
@@ -1555,6 +1649,7 @@ GdiFont WineEngCreateFontInstance(DC *dc
 	}
     }
 
+    lang = LANGIDFROMLCID(GetThreadLocale());
     if(lf.lfFaceName[0] != '\0') {
         FontSubst *psub;
 	for(psub = substlist; psub; psub = psub->next)
@@ -1575,7 +1670,17 @@ GdiFont WineEngCreateFontInstance(DC *dc
 	   or if that's unavailable the first charset that the font supports.
 	*/
         for(family = FontList; family; family = family->next) {
-	    if(!strcmpiW(family->FamilyName, lf.lfFaceName))
+	    family_name = family->FamilyName;
+	    for (name = family->FirstFace->name; name != NULL; name = name->next)
+	    {
+		if (name->lang == lang)
+		{
+		    family_name = name->FamilyName;
+		    break;
+		}
+	    }
+	    if (!strcmpiW(family_name, lf.lfFaceName) ||
+		!strcmpiW(family->FamilyName, lf.lfFaceName))
 	        if((csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]) || !csi.fs.fsCsb[0])
                     if(family->FirstFace->scalable || can_use_bitmap)
                         break;
@@ -1695,7 +1800,17 @@ GdiFont WineEngCreateFontInstance(DC *dc
     }
 
     ret->orientation = lf.lfOrientation;
-    ret->name = strdupW(family->FamilyName);
+    ret->name = face->family->FamilyName;
+    ret->style_name = face->StyleName;
+    for (name = face->name; name != NULL; name = name->next)
+    {
+	if (name->lang == lang)
+	{
+	    ret->name = name->FamilyName;
+	    ret->style_name = name->StyleName;
+	    break;
+	}
+    }
     ret->underline = lf.lfUnderline ? 0xff : 0;
     ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
 
@@ -1761,6 +1876,8 @@ BOOL WineEngDestroyFontInstance(HFONT ha
 static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
 			   NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
 {
+    WORD lang;
+    Name *name;
     OUTLINETEXTMETRICW *potm = NULL;
     UINT size;
     TEXTMETRICW tm, *ptm;
@@ -1781,7 +1898,18 @@ static void GetEnumStructs(Face *face, L
         return;
     }
 
-    font->name = strdupW(face->family->FamilyName);
+    lang = LANGIDFROMLCID(GetThreadLocale());
+    font->name = face->family->FamilyName;
+    font->style_name = face->StyleName;
+    for (name = face->name; name != NULL; name = name->next)
+    {
+	if (name->lang == lang)
+	{
+	    font->name = name->FamilyName;
+	    font->style_name = name->StyleName;
+	    break;
+	}
+    }
 
     memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW));
 
@@ -1891,41 +2019,43 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, F
             plf = &lf;
         }
         for(family = FontList; family; family = family->next) {
-	    if(!strcmpiW(plf->lfFaceName, family->FamilyName)) {
-	        for(face = family->FirstFace; face; face = face->next) {
-		    GetEnumStructs(face, &elf, &ntm, &type);
-		    for(i = 0; i < 32; i++) {
-                        if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
-                            elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
-                            strcpyW(elf.elfScript, OEM_DOSW);
-                            i = 32; /* break out of loop */
-                        } else if(!(face->fs.fsCsb[0] & (1L << i)))
-                            continue;
-                        else {
-                            fs.fsCsb[0] = 1L << i;
-                            fs.fsCsb[1] = 0;
-                            if(!TranslateCharsetInfo(fs.fsCsb, &csi,
-                                                     TCI_SRCFONTSIG))
-                                csi.ciCharset = DEFAULT_CHARSET;
-                            if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
-                            if(csi.ciCharset != DEFAULT_CHARSET) {
-                                elf.elfLogFont.lfCharSet =
-                                    ntm.ntmTm.tmCharSet = csi.ciCharset;
-                                if(ElfScriptsW[i])
-                                    strcpyW(elf.elfScript, ElfScriptsW[i]);
-                                else
-                                    FIXME("Unknown elfscript for bit %d\n", i);
-                            }
-                        }
-                        TRACE("enuming face %s full %s style %s charset %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
-                              debugstr_w(elf.elfLogFont.lfFaceName),
-                              debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
-                              csi.ciCharset, type, debugstr_w(elf.elfScript),
-                              elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
-                              ntm.ntmTm.ntmFlags);
-                        ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam);
-                        if(!ret) goto end;
+	    for(face = family->FirstFace; face; face = face->next) {
+		GetEnumStructs(face, &elf, &ntm, &type);
+		if (strcmpiW(plf->lfFaceName, elf.elfLogFont.lfFaceName) &&
+		    strcmpiW(plf->lfFaceName, family->FamilyName)) {
+		    break;
+		}
+		for(i = 0; i < 32; i++) {
+		    if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
+			elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
+			strcpyW(elf.elfScript, OEM_DOSW);
+			i = 32; /* break out of loop */
+		    } else if(!(face->fs.fsCsb[0] & (1L << i)))
+			continue;
+		    else {
+			fs.fsCsb[0] = 1L << i;
+			fs.fsCsb[1] = 0;
+			if(!TranslateCharsetInfo(fs.fsCsb, &csi,
+						 TCI_SRCFONTSIG))
+			    csi.ciCharset = DEFAULT_CHARSET;
+			if(i == 31) csi.ciCharset = SYMBOL_CHARSET;
+			if(csi.ciCharset != DEFAULT_CHARSET) {
+			    elf.elfLogFont.lfCharSet =
+				ntm.ntmTm.tmCharSet = csi.ciCharset;
+			    if(ElfScriptsW[i])
+				strcpyW(elf.elfScript, ElfScriptsW[i]);
+			    else
+				FIXME("Unknown elfscript for bit %d\n", i);
+			}
 		    }
+		    TRACE("enuming face %s full %s style %s charset %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
+			  debugstr_w(elf.elfLogFont.lfFaceName),
+			  debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
+			  csi.ciCharset, type, debugstr_w(elf.elfScript),
+			  elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight,
+			  ntm.ntmTm.ntmFlags);
+		    ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam);
+		    if(!ret) goto end;
 		}
 	    }
 	}
@@ -2555,7 +2685,6 @@ UINT WineEngGetOutlineTextMetrics(GdiFon
     TT_HoriHeader *pHori;
     TT_Postscript *pPost;
     FT_Fixed x_scale, y_scale;
-    WCHAR *family_nameW, *style_nameW;
     static const WCHAR spaceW[] = {' ', '\0'};
     char *cp;
     INT ascent, descent;
@@ -2571,19 +2700,9 @@ UINT WineEngGetOutlineTextMetrics(GdiFon
 	return font->potm->otmSize;
     }
 
-
     needed = sizeof(*potm);
-
     lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
-    family_nameW = strdupW(font->name);
-
-    lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
-      * sizeof(WCHAR);
-    style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty);
-    MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1,
-			style_nameW, lensty);
-
-    /* These names should be read from the TT name table */
+    lensty = (strlenW(font->style_name) + 1) * sizeof(WCHAR);
 
     /* length of otmpFamilyName */
     needed += lenfam;
@@ -2761,32 +2880,29 @@ UINT WineEngGetOutlineTextMetrics(GdiFon
     /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
     cp = (char*)font->potm + sizeof(*font->potm);
     font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
-    strcpyW((WCHAR*)cp, family_nameW);
+    strcpyW((WCHAR*)cp, font->name);
     cp += lenfam;
     font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
-    strcpyW((WCHAR*)cp, style_nameW);
+    strcpyW((WCHAR*)cp, font->style_name);
     cp += lensty;
     font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
-    strcpyW((WCHAR*)cp, family_nameW);
+    strcpyW((WCHAR*)cp, font->name);
     if(strcasecmp(ft_face->style_name, "regular")) {
         strcatW((WCHAR*)cp, spaceW);
-	strcatW((WCHAR*)cp, style_nameW);
+	strcatW((WCHAR*)cp, font->style_name);
 	cp += lenfam + lensty;
     } else
         cp += lenfam;
     font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
-    strcpyW((WCHAR*)cp, family_nameW);
+    strcpyW((WCHAR*)cp, font->name);
     strcatW((WCHAR*)cp, spaceW);
-    strcatW((WCHAR*)cp, style_nameW);
+    strcatW((WCHAR*)cp, font->style_name);
     ret = needed;
 
     if(potm && needed <= cbSize)
         memcpy(potm, font->potm, font->potm->otmSize);
 
 end:
-    HeapFree(GetProcessHeap(), 0, style_nameW);
-    HeapFree(GetProcessHeap(), 0, family_nameW);
-
     return ret;
 }
 


More information about the wine-patches mailing list