( I only test with Windows and VC)
The Unicode module of SFML can't deal with multibyte ANSI string properly(at least Chinese), and after some tests, here's my conclusion:
1. On Windows using VC compiler, the simplist way to display chinese is using 'L' with string literal, like:
if(!zhfont.LoadFromFile("simkai.ttf", 30, sf::Unicode::Text(L"ok你好hi"))) return -1;
sf::String msg(sf::Unicode::Text(L"ok你好hi"), zhfont, 18);
Because VC compiler convert the L"xx" string to wide string(const wchar_t [], UTF-16), and then SFML handles correctly. It works, but is not portable.
2. We may save the text in UTF-8 file, and load it. Pass the text as "const unsigned char *" or "const Uint8 *" type to sf::Unicode::Text, like:
std::string s;
std::ifstream fin("msg");
std::getline(fin, s);
fin.close();
// now use sf::Unicode::Text((const unsigned char *)s.c_str())
3. The reason lies in the function Unicode::UTF32ToANSI and Unicode::ANSIToUTF32 in "include\SFML\System\Unicode.inl". The C++ facet code seems not work, and the mbtowc() code can't deal with multibyte ansi string correctly, so I modified it:
#pragma warning(disable: 4996)
////////////////////////////////////////////////////////////
/// Generic function to convert an UTF-32 characters range
/// to an ANSI characters range, using the given locale
////////////////////////////////////////////////////////////
template <typename In, typename Out>
inline Out WCSToANSI(In Begin, In End, Out Output, char Replacement)
{
//wctomb(NULL, 0);
char bytes[6];
while (Begin < End)
{
int n=wctomb(bytes, static_cast<wchar_t>(*Begin++));
if ( n >= 0) {
for(int i=0; i < n; ++i) { *Output++ = bytes[i]; }
} else if (Replacement) {
*Output++ = Replacement;
}
}
return Output;
}
template <typename In, typename Out>
inline Out Unicode::UTF32ToANSI(In Begin, In End, Out Output, char Replacement)
{
switch(sizeof(wchar_t)) {
case 4: WCSToANSI(Begin, End, Output, Replacement); break;
case 2: {
Unicode::UTF16String s;
s.reserve((End-Begin)*2+1);
Unicode::UTF32ToUTF16(Begin, End, std::back_inserter(s), Replacement);
WCSToANSI(s.begin(), s.end(), Output, Replacement);
break;
}
default: break;
}
return Output;
}
////////////////////////////////////////////////////////////
/// Generic function to convert an ANSI characters range
/// to an UTF-32 characters range, using the given locale
////////////////////////////////////////////////////////////
template <typename In, typename Out>
inline Out ANSIToWCS(In Begin, In End, Out Output)
{
//mbtowc(NULL, NULL, 6);
wchar_t wc;
char *bytes = new char[End - Begin];
for(int i=0; i< End-Begin; ++i) { bytes[i] = *(Begin+i); }
const char *p = bytes;
while (p < bytes+(End-Begin))
{
int n = mbtowc(&wc, p, MB_CUR_MAX);
if(n>0) {
p += n;
*Output++ = (wc);
}
}
delete[] bytes;
return Output;
}
template <typename In, typename Out>
inline Out Unicode::ANSIToUTF32(In Begin, In End, Out Output)
{
switch(sizeof(wchar_t)) {
case 4: ANSIToWCS(Begin, End, Output); break;
case 2: {
Unicode::UTF16String s;
s.reserve(End-Begin+1);
ANSIToWCS(Begin, End, std::back_inserter(s));
Unicode::UTF16ToUTF32(s.begin(), s.end(), Output, 0);
break;
}
default: break;
}
return Output;
}
NOTE: I removed the ‘Locale’ param, you may add it to fast test
NOTE: be sure to call
setlocale(LC_ALL, "");
at the start of main().
Not tested much, just work on my machine, hope this can help somebody