From: Dmitry Timoshkov Subject: [PATCH] gdi32: Add a workaround for A->W text output with Symbol font encoding. Message-Id: <20180622125506.4c1f369b2387cd95fc69c200@baikal.ru> Date: Fri, 22 Jun 2018 12:55:06 +0800 There are 2 ways to output Ansi text: 1. Call DrawTextA/ExtTextOutA, it uses font codepage for unicode translation. 2. hfont = CreateFont("Wingdings", SYMBOL_CHARSET); SendMessageA(hwnd, WM_SETFONT, hfont); SendMessageA(hwnd, WM_SETTEXT, textA); It uses current ANSI codepage for unicode translation. Currently #1 works correctly for Symbol fonts but #2 does not. This patch makes #2 work as well. Since this is a text drawing bug I don't see a way of adding a test case for this behaviour. Signed-off-by: Dmitry Timoshkov --- dlls/gdi32/freetype.c | 48 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 1293e08a73..ba1839af82 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -6303,24 +6303,44 @@ static FT_UInt get_GSUB_vert_glyph(const GdiFont *font, UINT glyph) return GSUB_apply_feature(header, feature, glyph); } +static FT_UInt get_glyph_index_symbol(const GdiFont *font, UINT glyph) +{ + FT_UInt ret; + + if (glyph < 0x100) glyph += 0xf000; + /* there is a number of old pre-Unicode "broken" TTFs, which + do have symbols at U+00XX instead of U+f0XX */ + if (!(ret = pFT_Get_Char_Index(font->ft_face, glyph))) + ret = pFT_Get_Char_Index(font->ft_face, glyph - 0xf000); + + return ret; +} + static FT_UInt get_glyph_index(const GdiFont *font, UINT glyph) { - FT_UInt glyphId; + FT_UInt ret; + WCHAR wc; + char buf; if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) { - WCHAR wc = (WCHAR)glyph; BOOL default_used; BOOL *default_used_pointer; - FT_UInt ret; - char buf; default_used_pointer = NULL; default_used = FALSE; if (codepage_sets_default_used(font->codepage)) default_used_pointer = &default_used; + wc = (WCHAR)glyph; if(!WideCharToMultiByte(font->codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, default_used_pointer) || default_used) { - if (font->codepage == CP_SYMBOL && wc < 0x100) - ret = pFT_Get_Char_Index(font->ft_face, (unsigned char)wc); + if (font->codepage == CP_SYMBOL) + { + ret = get_glyph_index_symbol(font, glyph); + if (!ret) + { + if (WideCharToMultiByte(CP_ACP, 0, &wc, 1, &buf, 1, NULL, NULL)) + ret = get_glyph_index_symbol(font, buf); + } + } else ret = 0; } @@ -6332,15 +6352,17 @@ static FT_UInt get_glyph_index(const GdiFont *font, UINT glyph) if(font->ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL) { - if (glyph < 0x100) glyph += 0xf000; - /* there is a number of old pre-Unicode "broken" TTFs, which - do have symbols at U+00XX instead of U+f0XX */ - if (!(glyphId = pFT_Get_Char_Index(font->ft_face, glyph))) - glyphId = pFT_Get_Char_Index(font->ft_face, glyph-0xf000); + ret = get_glyph_index_symbol(font, glyph); + if (!ret) + { + wc = (WCHAR)glyph; + if (WideCharToMultiByte(CP_ACP, 0, &wc, 1, &buf, 1, NULL, NULL)) + ret = get_glyph_index_symbol(font, (unsigned char)buf); + } + return ret; } - else glyphId = pFT_Get_Char_Index(font->ft_face, glyph); - return glyphId; + return pFT_Get_Char_Index(font->ft_face, glyph); } /* helper for freetype_GetGlyphIndices */ -- 2.16.3