Commit 9786ee25 authored by Zhiyi Zhang's avatar Zhiyi Zhang Committed by Alexandre Julliard

gdiplus: Search microsoft platform names first in load_ttf_name_id().

Search names in fonts in the order of Microsoft, Mac and finally Unicode platform. This is also the order win32u uses to load font names. Fix Granado Espada Japan (1219160) launcher crashes at start in the Japanese locale. The game ships a font with a broken name record of Mac platform and encoding ID 0 (Roman) but the name string is in code page 10001 (Japanese). This broken name record is placed before the name records for the Microsoft platform so it gets selected first. Then the name string in the name record doesn't get converted correctly to Unicode because of the wrong code page. Thus the EnumFontFamiliesExW() in GdipPrivateAddMemoryFont() fails to find the font and causes game crash.
parent 242ee3d0
...@@ -1385,12 +1385,13 @@ static WCHAR *copy_name_table_string( const tt_name_record *name, const BYTE *da ...@@ -1385,12 +1385,13 @@ static WCHAR *copy_name_table_string( const tt_name_record *name, const BYTE *da
static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id ) static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id )
{ {
static const WORD platform_id_table[] = {TT_PLATFORM_MICROSOFT, TT_PLATFORM_MACINTOSH, TT_PLATFORM_APPLE_UNICODE};
LANGID lang = GetSystemDefaultLangID(); LANGID lang = GetSystemDefaultLangID();
const tt_header *header; const tt_header *header;
const tt_name_table *name_table; const tt_name_table *name_table;
const tt_name_record *name_record; const tt_name_record *name_record_table, *name_record;
DWORD pos, ofs = 0, count; DWORD pos, ofs = 0, count;
int i, res, best_lang = 0, best_index = -1; int i, j, res, best_lang = 0, best_index = -1;
if (sizeof(tt_header) > size) if (sizeof(tt_header) > size)
return NULL; return NULL;
...@@ -1421,26 +1422,33 @@ static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id ) ...@@ -1421,26 +1422,33 @@ static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id )
if (pos > size) if (pos > size)
return NULL; return NULL;
name_table = (const tt_name_table*)&mem[ofs]; name_table = (const tt_name_table*)&mem[ofs];
name_record_table = (const tt_name_record *)&mem[pos];
count = GET_BE_WORD(name_table->count); count = GET_BE_WORD(name_table->count);
if (GET_BE_WORD(name_table->string_offset) >= size - ofs) return NULL; if (GET_BE_WORD(name_table->string_offset) >= size - ofs) return NULL;
ofs += GET_BE_WORD(name_table->string_offset); ofs += GET_BE_WORD(name_table->string_offset);
for (i=0; i<count; i++) for (i = 0; i < ARRAY_SIZE(platform_id_table); i++)
{ {
name_record = (const tt_name_record*)&mem[pos]; for (j = 0; j < count; j++)
pos += sizeof(*name_record); {
if (pos > size) name_record = name_record_table + j;
return NULL; if ((const BYTE *)name_record - mem > size)
return NULL;
if (GET_BE_WORD(name_record->name_id) != id) continue; if (GET_BE_WORD(name_record->platform_id) != platform_id_table[i]) continue;
if (GET_BE_WORD(name_record->offset) >= size - ofs) return NULL; if (GET_BE_WORD(name_record->name_id) != id) continue;
if (GET_BE_WORD(name_record->length) > size - ofs - GET_BE_WORD(name_record->offset)) return NULL; if (GET_BE_WORD(name_record->offset) >= size - ofs) return NULL;
if (GET_BE_WORD(name_record->length) > size - ofs - GET_BE_WORD(name_record->offset)) return NULL;
res = match_name_table_language( name_record, lang ); res = match_name_table_language(name_record, lang);
if (res > best_lang) if (res > best_lang)
{ {
best_lang = res; best_lang = res;
best_index = i; best_index = j;
}
} }
if (best_index != -1)
break;
} }
if (best_lang) if (best_lang)
......
...@@ -1558,7 +1558,6 @@ static void test_GdipPrivateAddMemoryFont(void) ...@@ -1558,7 +1558,6 @@ static void test_GdipPrivateAddMemoryFont(void)
{ {
stat = GdipGetFontCollectionFamilyCount(fonts, &count); stat = GdipGetFontCollectionFamilyCount(fonts, &count);
ok(stat == Ok, "GdipGetFontCollectionFamilyCount failed, error %d\n", stat); ok(stat == Ok, "GdipGetFontCollectionFamilyCount failed, error %d\n", stat);
todo_wine
ok(count == 1, "Expected count 1, got %d\n", count); ok(count == 1, "Expected count 1, got %d\n", count);
} }
else if (i == 1 && stat == FileNotFound) else if (i == 1 && stat == FileNotFound)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment