Index: base/setup/usetup/muifonts.h =================================================================== --- base/setup/usetup/muifonts.h (revision 67492) +++ base/setup/usetup/muifonts.h (working copy) @@ -80,15 +80,15 @@ { L"Courier", L"FreeMono" }, { L"Courier New", L"FreeMono" }, { L"Fixedsys", L"Fixedsys Excelsior 3.01-L2" }, - { L"Helv", L"Droid Sans Fallback" }, + { L"Helv", L"\x65b0\x7d30\x660e\x9ad4" }, { L"Helvetica", L"Liberation Sans" }, { L"Lucida Console", L"DejaVu Sans Mono" }, - { L"MS Sans Serif", L"Droid Sans Fallback" }, - { L"MS Shell Dlg", L"Droid Sans Fallback" }, - { L"MS Shell Dlg 2", L"Droid Sans Fallback" }, - { L"MS UI Gothic", L"Droid Sans Fallback" }, - { L"MS UI Gothic 2", L"Droid Sans Fallback" }, - { L"Tahoma", L"Droid Sans Fallback" }, + { L"MS Sans Serif", L"\x65b0\x7d30\x660e\x9ad4" }, + { L"MS Shell Dlg", L"\x65b0\x7d30\x660e\x9ad4" }, + { L"MS Shell Dlg 2", L"\x65b0\x7d30\x660e\x9ad4" }, + { L"MS UI Gothic", L"\x65b0\x7d30\x660e\x9ad4" }, + { L"MS UI Gothic 2", L"\x65b0\x7d30\x660e\x9ad4" }, + { L"Tahoma", L"\x65b0\x7d30\x660e\x9ad4" }, { L"Terminal", L"DejaVu Sans Mono" }, { L"Times New Roman", L"Liberation Serif" }, { NULL, NULL } Index: win32ss/gdi/eng/engobjects.h =================================================================== --- win32ss/gdi/eng/engobjects.h (revision 67492) +++ win32ss/gdi/eng/engobjects.h (working copy) @@ -123,6 +123,7 @@ LPWSTR Filename; BYTE Underline; BYTE StrikeOut; + LPWSTR FaceName; } FONTGDI, *PFONTGDI; typedef struct _PATHGDI { Index: win32ss/gdi/ntgdi/freetype.c =================================================================== --- win32ss/gdi/ntgdi/freetype.c (revision 67492) +++ win32ss/gdi/ntgdi/freetype.c (working copy) @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include @@ -330,6 +332,11 @@ ULONG ViewSize = 0; LARGE_INTEGER SectionSize; UNICODE_STRING FontRegPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"); + ULONG SfntNameCount; + ULONG i; + ULONG j; + DECLARE_UNICODE_STRING_SIZE(LocalizedFaceName, 256); + INT HasLocalizedFaceName = 0; /* Open the font file */ @@ -418,23 +425,119 @@ FontGDI->Filename[FileName->Length / sizeof(WCHAR)] = L'\0'; FontGDI->face = Face; - DPRINT("Font loaded: %s (%s)\n", Face->family_name, Face->style_name); - DPRINT("Num glyphs: %d\n", Face->num_glyphs); + DPRINT1("Font loaded: %s (%s)\n", Face->family_name, Face->style_name); + DPRINT1("Num glyphs: %d\n", Face->num_glyphs); + /* Attempt to get localized name */ + SfntNameCount = FT_Get_Sfnt_Name_Count(Face); + for (i = 0; i < SfntNameCount; i++) + { + FT_SfntName SfntName; + Error = FT_Get_Sfnt_Name(Face, i, &SfntName); + if (ERROR) + { + DPRINT1("Error reading sfnt name index %d (error code: %d)\n", i, Error); + continue; + } + // See also https://www.microsoft.com/typography/otspec/name.htm#enc3 + if (SfntName.platform_id != TT_PLATFORM_MICROSOFT) + { + // FIXME: Do we also need to handle names for other platforms? + //DPRINT("Ignoring sfnt name that is not TT_PLATFORM_MICROSOFT\n"); + continue; + } + if (SfntName.encoding_id != TT_MS_ID_UNICODE_CS) + { + // FIXME: Handle other encoding as well? + //DPRINT("FIXME: Ignoring sfnt name that is not TT_MS_ID_UNICODE_CS\n"); + continue; + } + if (SfntName.language_id != 0x0404) /* zh-TW */ + { + // FIXME: Actually check the system language + //DPRINT("FIXME: Ignoring sfnt name that is not 0404 (zh-TW)\n"); + continue; + } + DPRINT("FIXME: Using sfnt name that is 0404 (zh-TW)\n"); + switch (SfntName.name_id) + { + case 1: /* Font Family name */ + if ((LocalizedFaceName.MaximumLength - sizeof(WCHAR)) < SfntName.string_len / 2) + { + DPRINT1("Not enough space in buffer, not copying\n", Status); + continue; + } + LocalizedFaceName.Length = SfntName.string_len; + //wcsncpy(LocalizedFaceName.Buffer, (WCHAR*) SfntName.string, SfntName.string_len); + for (j = 0; j < SfntName.string_len / 2; j++) + { + // Copy and reverse endianness... + LocalizedFaceName.Buffer[j] = (SfntName.string[j * 2] << 8) | SfntName.string[j * 2 + 1]; + } + LocalizedFaceName.Buffer[SfntName.string_len / sizeof(WCHAR)] = 0; + /*DPRINT1("Found localized name: %wZ\n", &LocalizedFaceName); // This actually shows nothing + for (j = 0; j < SfntName.string_len / 2; j++) + { + DPRINT1("Char %d is %04X\n", j, LocalizedFaceName.Buffer[j]); + }*/ + HasLocalizedFaceName = 1; + break; + case 2: /* Font Subfamily name */ + // TODO + break; + // TODO: Handle others? + } + } + /* Add this font resource to the font table */ Entry->Font = FontGDI; Entry->NotEnum = (Characteristics & FR_NOT_ENUM); - RtlInitAnsiString(&AnsiFaceName, (LPSTR)Face->family_name); - Status = RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE); - if (!NT_SUCCESS(Status)) + if (HasLocalizedFaceName) { - ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF); - EngFreeMem(FontGDI); - FT_Done_Face(Face); - ExFreePoolWithTag(Entry, TAG_FONT); - return 0; + FontGDI->FaceName = ExAllocatePool(PagedPool, LocalizedFaceName.Length + sizeof(WCHAR)); + if (FontGDI->FaceName == NULL) + { + ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF); + EngFreeMem(FontGDI); + FT_Done_Face(Face); + ExFreePoolWithTag(Entry, TAG_FONT); + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + //wcscpy(FontGDI->FaceName, LocalizedFaceName.Buffer); + RtlCopyMemory(FontGDI->FaceName, LocalizedFaceName.Buffer, LocalizedFaceName.Length + sizeof(WCHAR)); + DPRINT1("Set localized name: %wZ\n", &Entry->FaceName); + RtlInitUnicodeString(&Entry->FaceName, FontGDI->FaceName); } + if (!HasLocalizedFaceName) + { + RtlInitAnsiString(&AnsiFaceName, (LPSTR)Face->family_name); + Status = RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE); + if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF); + EngFreeMem(FontGDI); + FT_Done_Face(Face); + ExFreePoolWithTag(Entry, TAG_FONT); + return 0; + } + FontGDI->FaceName = ExAllocatePool(PagedPool, Entry->FaceName.Length + sizeof(WCHAR)); + if (FontGDI->FaceName == NULL) + { + ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF); + EngFreeMem(FontGDI); + FT_Done_Face(Face); + ExFreePoolWithTag(Entry, TAG_FONT); + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + //wcscpy(FontGDI->FaceName, Entry->FaceName.Buffer); + RtlCopyMemory(FontGDI->FaceName, Entry->FaceName.Buffer, Entry->FaceName.Length + sizeof(WCHAR)); + DPRINT1("Set family name: %wZ\n", &Entry->FaceName); + RtlFreeUnicodeString(&Entry->FaceName); + RtlInitUnicodeString(&Entry->FaceName, FontGDI->FaceName); + } if (Characteristics & FR_PRIVATE) { @@ -798,7 +901,7 @@ TT_HoriHeader *pHori; TT_Postscript *pPost; FT_Fixed XScale, YScale; - ANSI_STRING FamilyNameA, StyleNameA; + ANSI_STRING /*FamilyNameA,*/ StyleNameA; UNICODE_STRING FamilyNameW, StyleNameW, Regular; FT_WinFNT_HeaderRec Win; FT_Error Error; @@ -807,18 +910,19 @@ Needed = sizeof(OUTLINETEXTMETRICW); - RtlInitAnsiString(&FamilyNameA, FontGDI->face->family_name); + /*RtlInitAnsiString(&FamilyNameA, FontGDI->face->family_name); status = RtlAnsiStringToUnicodeString(&FamilyNameW, &FamilyNameA, TRUE); if (!NT_SUCCESS(status)) { return 0; - } + }*/ + RtlInitUnicodeString(&FamilyNameW, FontGDI->FaceName); RtlInitAnsiString(&StyleNameA, FontGDI->face->style_name); status = RtlAnsiStringToUnicodeString(&StyleNameW, &StyleNameA, TRUE); if (!NT_SUCCESS(status)) { - RtlFreeUnicodeString(&FamilyNameW); + //RtlFreeUnicodeString(&FamilyNameW); return 0; } @@ -846,7 +950,7 @@ if (Size < Needed) { - RtlFreeUnicodeString(&FamilyNameW); + //RtlFreeUnicodeString(&FamilyNameW); RtlFreeUnicodeString(&StyleNameW); return Needed; } @@ -861,7 +965,7 @@ IntUnLockFreeType; DPRINT1("Can't find OS/2 table - not TT font?\n"); RtlFreeUnicodeString(&StyleNameW); - RtlFreeUnicodeString(&FamilyNameW); + //RtlFreeUnicodeString(&FamilyNameW); return 0; } @@ -871,7 +975,7 @@ IntUnLockFreeType; DPRINT1("Can't find HHEA table - not TT font?\n"); RtlFreeUnicodeString(&StyleNameW); - RtlFreeUnicodeString(&FamilyNameW); + //RtlFreeUnicodeString(&FamilyNameW); return 0; } @@ -953,7 +1057,7 @@ wcscat((WCHAR*) Cp, StyleNameW.Buffer); RtlFreeUnicodeString(&StyleNameW); - RtlFreeUnicodeString(&FamilyNameW); + //RtlFreeUnicodeString(&FamilyNameW); return Needed; } @@ -963,10 +1067,10 @@ { PLIST_ENTRY Entry; PFONT_ENTRY CurrentEntry; - ANSI_STRING EntryFaceNameA; + //ANSI_STRING EntryFaceNameA; UNICODE_STRING EntryFaceNameW; FONTGDI *FontGDI; - NTSTATUS status; + //NTSTATUS status; Entry = Head->Flink; while (Entry != Head) @@ -976,12 +1080,13 @@ FontGDI = CurrentEntry->Font; ASSERT(FontGDI); - RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name); + /*RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name); status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE); if (!NT_SUCCESS(status)) { break; - } + }*/ + RtlInitUnicodeString(&EntryFaceNameW, FontGDI->FaceName); if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length) { @@ -991,11 +1096,11 @@ if (0 == RtlCompareUnicodeString(FaceName, &EntryFaceNameW, TRUE)) { - RtlFreeUnicodeString(&EntryFaceNameW); + //RtlFreeUnicodeString(&EntryFaceNameW); return FontGDI; } - RtlFreeUnicodeString(&EntryFaceNameW); + //RtlFreeUnicodeString(&EntryFaceNameW); Entry = Entry->Flink; } @@ -1227,10 +1332,10 @@ { PLIST_ENTRY Entry; PFONT_ENTRY CurrentEntry; - ANSI_STRING EntryFaceNameA; + //ANSI_STRING EntryFaceNameA; UNICODE_STRING EntryFaceNameW; FONTGDI *FontGDI; - NTSTATUS status; + //NTSTATUS status; Entry = Head->Flink; while (Entry != Head) @@ -1240,12 +1345,13 @@ FontGDI = CurrentEntry->Font; ASSERT(FontGDI); - RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name); + /*RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name); status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE); if (!NT_SUCCESS(status)) { return FALSE; - } + }*/ + RtlInitUnicodeString(&EntryFaceNameW, FontGDI->FaceName); if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length) { @@ -1261,7 +1367,7 @@ } (*Count)++; } - RtlFreeUnicodeString(&EntryFaceNameW); + //RtlFreeUnicodeString(&EntryFaceNameW); Entry = Entry->Flink; } @@ -2700,17 +2806,18 @@ static UINT FASTCALL GetFontScore(LOGFONTW *LogFont, PUNICODE_STRING FaceName, PFONTGDI FontGDI) { - ANSI_STRING EntryFaceNameA; + //ANSI_STRING EntryFaceNameA; UNICODE_STRING EntryFaceNameW; unsigned Size; OUTLINETEXTMETRICW *Otm; LONG WeightDiff; - NTSTATUS Status; + //NTSTATUS Status; UINT Score = 1; - RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name); - Status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE); - if (NT_SUCCESS(Status)) + //RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name); + //Status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE); + RtlInitUnicodeString(&EntryFaceNameW, FontGDI->FaceName); + //if (NT_SUCCESS(Status)) { static const UNICODE_STRING MarlettFaceNameW = RTL_CONSTANT_STRING(L"Marlett"); static const UNICODE_STRING SymbolFaceNameW = RTL_CONSTANT_STRING(L"Symbol"); @@ -2748,7 +2855,7 @@ Score = 0; } - RtlFreeUnicodeString(&EntryFaceNameW); + //RtlFreeUnicodeString(&EntryFaceNameW); } Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);