fix(platform): decode GDI ANSI text with the font charset's code page
TextOutA / GetTextExtentPoint32A in the Win32 GDI shim always decoded with CP_ACP (1252), so the server notices drawn by uiTip.TipBoard / BigBoard (CTextBar, a GB2312_CHARSET font in the 936 locale) showed GBK bytes as Latin-1 mojibake. Windows GDI decodes ANSI calls with the code page of the selected font's charset; the shim now keeps lfCharSet on the font and does the same. port.text_bar checks TextOutA of GBK bytes against TextOutW of the Unicode text, and the extent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
58a3d01027
commit
78d14776b8
@@ -62,6 +62,7 @@ struct HFONT__ : GdiObject
|
||||
int descent = 0;
|
||||
bool italic = false;
|
||||
bool antialiased = false;
|
||||
BYTE charset = ANSI_CHARSET;
|
||||
};
|
||||
|
||||
struct HDC__
|
||||
@@ -293,6 +294,7 @@ HFONT CreateFontIndirect(const LOGFONT* lplf)
|
||||
for (const char* name : kLinked)
|
||||
if (FT_Face linked = open_named(name); linked && linked != face) font->fallbacks.push_back(linked);
|
||||
font->italic = lplf->lfItalic != 0;
|
||||
font->charset = lplf->lfCharSet;
|
||||
font->antialiased = lplf->lfQuality == ANTIALIASED_QUALITY;
|
||||
|
||||
const TT_OS2* os2 = static_cast<const TT_OS2*>(FT_Get_Sfnt_Table(face, FT_SFNT_OS2));
|
||||
@@ -447,24 +449,48 @@ BOOL TextOutW(HDC hdc, int x, int y, LPCWSTR lpString, int c)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// The ANSI GDI calls decode the bytes with the code page of the selected font's charset (CTextBar selects
|
||||
// GetCharsetFromCodePage of the locale, e.g. GB2312_CHARSET for a 936 locale); ANSI/DEFAULT fall back to CP_ACP.
|
||||
static UINT dc_code_page(HDC hdc)
|
||||
{
|
||||
switch (dc_font(hdc)->charset) {
|
||||
case SHIFTJIS_CHARSET: return 932;
|
||||
case HANGUL_CHARSET: return 949;
|
||||
case GB2312_CHARSET: return 936;
|
||||
case CHINESEBIG5_CHARSET: return 950;
|
||||
case GREEK_CHARSET: return 1253;
|
||||
case TURKISH_CHARSET: return 1254;
|
||||
case VIETNAMESE_CHARSET: return 1258;
|
||||
case HEBREW_CHARSET: return 1255;
|
||||
case ARABIC_CHARSET: return 1256;
|
||||
case BALTIC_CHARSET: return 1257;
|
||||
case RUSSIAN_CHARSET: return 1251;
|
||||
case THAI_CHARSET: return 874;
|
||||
case EASTEUROPE_CHARSET: return 1250;
|
||||
default: return CP_ACP;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL TextOutA(HDC hdc, int x, int y, LPCSTR lpString, int c)
|
||||
{
|
||||
const int n = MultiByteToWideChar(CP_ACP, 0, lpString, c, nullptr, 0);
|
||||
const UINT cp = dc_code_page(hdc);
|
||||
const int n = MultiByteToWideChar(cp, 0, lpString, c, nullptr, 0);
|
||||
if (n <= 0) return c == 0;
|
||||
std::vector<WCHAR> wide(static_cast<size_t>(n));
|
||||
MultiByteToWideChar(CP_ACP, 0, lpString, c, wide.data(), n);
|
||||
MultiByteToWideChar(cp, 0, lpString, c, wide.data(), n);
|
||||
return TextOutW(hdc, x, y, wide.data(), n);
|
||||
}
|
||||
|
||||
BOOL GetTextExtentPoint32A(HDC hdc, LPCSTR lpString, int c, LPSIZE psizl)
|
||||
{
|
||||
const int n = MultiByteToWideChar(CP_ACP, 0, lpString, c, nullptr, 0);
|
||||
const UINT cp = dc_code_page(hdc);
|
||||
const int n = MultiByteToWideChar(cp, 0, lpString, c, nullptr, 0);
|
||||
if (n <= 0)
|
||||
{
|
||||
if (c != 0 || !psizl) return FALSE;
|
||||
return GetTextExtentPoint32W(hdc, nullptr, 0, psizl);
|
||||
}
|
||||
std::vector<WCHAR> wide(static_cast<size_t>(n));
|
||||
MultiByteToWideChar(CP_ACP, 0, lpString, c, wide.data(), n);
|
||||
MultiByteToWideChar(cp, 0, lpString, c, wide.data(), n);
|
||||
return GetTextExtentPoint32W(hdc, wide.data(), n, psizl);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user