From: Nikolay Sivov Subject: [PATCH 1/5] dwrite: Accept platform 0 name records if there's nothing, else Message-Id: <56B8605B.30108@gmail.com> Date: Mon, 8 Feb 2016 12:31:07 +0300 --- From 4c9989f5a64ff30ca654870183cb1d03491217a2 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Sat, 6 Feb 2016 02:59:39 +0300 Subject: [PATCH 1/5] dwrite: Accept platform 0 name records if there's nothing else Signed-off-by: Nikolay Sivov --- dlls/dwrite/opentype.c | 111 +++++++++++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 46 deletions(-) diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index 99d24ea..0d3482d 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -1281,20 +1281,69 @@ static void get_name_record_locale(enum OPENTYPE_PLATFORM_ID platform, USHORT la strcpyW(locale, enusW); } break; + case OPENTYPE_PLATFORM_UNICODE: + strcpyW(locale, enusW); + break; default: FIXME("unknown platform %d\n", platform); } } +static BOOL opentype_decode_namerecord(const TT_NAME_V0 *header, BYTE *storage_area, USHORT recid, IDWriteLocalizedStrings *strings) +{ + const TT_NameRecord *record = &header->nameRecord[recid]; + USHORT lang_id, length, offset, encoding, platform; + BOOL ret = FALSE; + + platform = GET_BE_WORD(record->platformID); + lang_id = GET_BE_WORD(record->languageID); + length = GET_BE_WORD(record->length); + offset = GET_BE_WORD(record->offset); + encoding = GET_BE_WORD(record->encodingID); + + if (lang_id < 0x8000) { + WCHAR locale[LOCALE_NAME_MAX_LENGTH]; + WCHAR *name_string; + UINT codepage; + + codepage = get_name_record_codepage(platform, encoding); + get_name_record_locale(platform, lang_id, locale, sizeof(locale)/sizeof(WCHAR)); + + if (codepage) { + DWORD len = MultiByteToWideChar(codepage, 0, (LPSTR)(storage_area + offset), length, NULL, 0); + name_string = heap_alloc(sizeof(WCHAR) * (len+1)); + MultiByteToWideChar(codepage, 0, (LPSTR)(storage_area + offset), length, name_string, len); + name_string[len] = 0; + } + else { + int i; + + length /= sizeof(WCHAR); + name_string = heap_strdupnW((LPWSTR)(storage_area + offset), length); + for (i = 0; i < length; i++) + name_string[i] = GET_BE_WORD(name_string[i]); + } + + TRACE("string %s for locale %s found\n", debugstr_w(name_string), debugstr_w(locale)); + add_localizedstring(strings, locale, name_string); + heap_free(name_string); + ret = TRUE; + } + else + FIXME("handle NAME format 1\n"); + + return ret; +} + static HRESULT opentype_get_font_strings_from_id(const void *table_data, enum OPENTYPE_STRING_ID id, IDWriteLocalizedStrings **strings) { const TT_NAME_V0 *header; BYTE *storage_area = 0; USHORT count = 0; + int i, candidate; WORD format; BOOL exists; HRESULT hr; - int i; if (!table_data) return E_FAIL; @@ -1313,20 +1362,18 @@ static HRESULT opentype_get_font_strings_from_id(const void *table_data, enum OP FIXME("unsupported NAME format %d\n", format); } - storage_area = (LPBYTE)table_data + GET_BE_WORD(header->stringOffset); count = GET_BE_WORD(header->count); exists = FALSE; + candidate = -1; for (i = 0; i < count; i++) { const TT_NameRecord *record = &header->nameRecord[i]; - USHORT lang_id, length, offset, encoding, platform; + USHORT platform; if (GET_BE_WORD(record->nameID) != id) continue; - exists = TRUE; - /* Right now only accept unicode and windows encoded fonts */ platform = GET_BE_WORD(record->platformID); if (platform != OPENTYPE_PLATFORM_UNICODE && @@ -1337,53 +1384,25 @@ static HRESULT opentype_get_font_strings_from_id(const void *table_data, enum OP continue; } - /* Skip such entries for now, as it's not clear which locale is implied when - unicode platform is used. Also fonts tend to duplicate those strings as - WIN platform entries. */ - if (platform == OPENTYPE_PLATFORM_UNICODE) + /* Skip such entries for now, fonts tend to duplicate those strings as + WIN platform entries. If font does not have WIN or MAC entry for this id, we will + use this Unicode platform entry while assuming en-US locale. */ + if (platform == OPENTYPE_PLATFORM_UNICODE) { + candidate = i; continue; - - lang_id = GET_BE_WORD(record->languageID); - length = GET_BE_WORD(record->length); - offset = GET_BE_WORD(record->offset); - encoding = GET_BE_WORD(record->encodingID); - - if (lang_id < 0x8000) { - WCHAR locale[LOCALE_NAME_MAX_LENGTH]; - WCHAR *name_string; - UINT codepage; - - codepage = get_name_record_codepage(platform, encoding); - get_name_record_locale(platform, lang_id, locale, sizeof(locale)/sizeof(WCHAR)); - - if (codepage) { - DWORD len = MultiByteToWideChar(codepage, 0, (LPSTR)(storage_area + offset), length, NULL, 0); - name_string = heap_alloc(sizeof(WCHAR) * (len+1)); - MultiByteToWideChar(codepage, 0, (LPSTR)(storage_area + offset), length, name_string, len); - name_string[len] = 0; - } - else { - int i; - - length /= sizeof(WCHAR); - name_string = heap_strdupnW((LPWSTR)(storage_area + offset), length); - for (i = 0; i < length; i++) - name_string[i] = GET_BE_WORD(name_string[i]); - } - - TRACE("string %s for locale %s found\n", debugstr_w(name_string), debugstr_w(locale)); - add_localizedstring(*strings, locale, name_string); - heap_free(name_string); } - else { - FIXME("handle NAME format 1\n"); + + if (!(exists = opentype_decode_namerecord(header, storage_area, i, *strings))) continue; - } } if (!exists) { - IDWriteLocalizedStrings_Release(*strings); - *strings = NULL; + if (candidate != -1) + exists = opentype_decode_namerecord(header, storage_area, candidate, *strings); + else { + IDWriteLocalizedStrings_Release(*strings); + *strings = NULL; + } } return exists ? S_OK : E_FAIL; -- 2.7.0