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
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 ); }
Jinoh Kang (@iamahuman) commented about dlls/gdi32/text.c:
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);
If we're worried about fixme spam, should we just have it be emitted once?
I notice that you've copied charset-font logic from win32u. To prevent unwanted desync, I think we should either test for this logic or find a way to borrow the charset-font logic through some NtGdi*() call in a way that matches Windows.
In general, tests and/or links to documentation, particularly regarding `Symbol`-to-`CP_SYMBOL`, would be appreciated if possible.
https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wmf/0d0b32a... ----- The document shown in this link has a description of SYMBOL_CHARSET。 Once the character set is determined to be SYMBOL_CHARSET, then CP_SYMBOL should also be determined。