From: chenjiangyi chenjiangyi@uniontech.com
Log: get_dc_attr always failed for meta dc,so GdiGetCodePage always return CP_ACP. And GetTextCharset is similar to this situation. Finally, leading to an error result of text_mbtowc call by ExtTextOutA and an error result of METADC_ExtTextOut.
Signed-off-by: chenjiangyi chenjiangyi@uniontech.com Change-Id: Icb6a8d57848935bc5c1b3913c155148af43eca0d --- dlls/gdi32/gdi_private.h | 1 + dlls/gdi32/metadc.c | 37 +++++++++++++++++++++++++++++++++ dlls/gdi32/text.c | 45 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+)
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 8fa5c06e014..0696de8c753 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -94,6 +94,7 @@ BOOL METADC_ExtTextOut( HDC hdc, INT x, INT y, UINT flags, const RECT *rect, BOOL METADC_FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush ); BOOL METADC_FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush, INT x, INT y ); INT METADC_GetDeviceCaps( HDC hdc, INT cap ); +UINT METADC_GetTextCharset( HDC hdc ); BOOL METADC_IntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bottom ); BOOL METADC_InvertRgn( HDC hdc, HRGN hrgn ); BOOL METADC_LineTo( HDC hdc, INT x, INT y ); diff --git a/dlls/gdi32/metadc.c b/dlls/gdi32/metadc.c index dbfa311b711..3e4b4a4eb2b 100644 --- a/dlls/gdi32/metadc.c +++ b/dlls/gdi32/metadc.c @@ -1269,6 +1269,43 @@ BOOL METADC_ExtEscape( HDC hdc, INT escape, INT input_size, const void *input, return ret; }
+static inline WCHAR facename_tolower( WCHAR c ) +{ + if (c >= 'A' && c <= 'Z') return c - 'A' + 'a'; + else if (c > 127) return RtlDowncaseUnicodeChar( c ); + else return c; +} + +static inline int facename_compare( const WCHAR *str1, const WCHAR *str2, SIZE_T len ) +{ + while (len--) + { + WCHAR c1 = facename_tolower( *str1++ ), c2 = facename_tolower( *str2++ ); + if (c1 != c2) return c1 - c2; + else if (!c1) return 0; + } + return 0; +} + +UINT METADC_GetTextCharset( HDC hdc ) +{ + UINT ret = DEFAULT_CHARSET; + struct metadc *metadc; + static const WCHAR symbolW[] = {'S','y','m','b','o','l',0}; + + if(!(metadc = get_metadc_ptr( hdc ))) return ret; + if(metadc->font) + { + LOGFONTW lf; + NtGdiExtGetObjectW( metadc->font, sizeof(lf), &lf ); + if (!facename_compare( lf.lfFaceName, symbolW, -1 )) + lf.lfCharSet = SYMBOL_CHARSET; + return lf.lfCharSet; + } + + return ret; +} + INT METADC_GetDeviceCaps( HDC hdc, INT cap ) { if (!get_metadc_ptr( hdc )) return 0; diff --git a/dlls/gdi32/text.c b/dlls/gdi32/text.c index ff548306dc3..e7a92fc05f5 100644 --- a/dlls/gdi32/text.c +++ b/dlls/gdi32/text.c @@ -830,7 +830,51 @@ static void logfontex_WtoA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA */ DWORD WINAPI GdiGetCodePage( HDC hdc ) { + CHARSETINFO csi; DC_ATTR *dc_attr = get_dc_attr( hdc ); + + if(is_meta_dc(hdc)) + { + UINT charset = METADC_GetTextCharset(hdc); + UINT cp = CP_ACP; + if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET )) + cp = csi.ciACP; + else + { + switch(charset) + { + case OEM_CHARSET: + cp = GetOEMCP(); + break; + case DEFAULT_CHARSET: + cp = GetACP(); + break; + + case VISCII_CHARSET: + case TCVN_CHARSET: + case KOI8_CHARSET: + case ISO3_CHARSET: + case ISO4_CHARSET: + case ISO10_CHARSET: + case CELTIC_CHARSET: + /* FIXME: These have no place here, but because x11drv + enumerates fonts with these (made up) charsets some apps + might use them and then the FIXME below would become + annoying. Now we could pick the intended codepage for + each of these, but since it's broken anyway we'll just + use CP_ACP and hope it'll go away... + */ + cp = CP_ACP; + break; + + default: + FIXME("Can't find codepage for charset %d\n", charset); + break; + } + } + return cp; + } + return dc_attr ? dc_attr->font_code_page : CP_ACP; }
@@ -2086,6 +2130,7 @@ BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, SIZE *aspect_ratio ) */ UINT WINAPI GetTextCharset( HDC hdc ) { + if(is_meta_dc(hdc)) return METADC_GetTextCharset(hdc); /* MSDN docs say this is equivalent */ return NtGdiGetTextCharsetInfo( hdc, NULL, 0 ); }