Merge pull request #2301 from Benau/master
Fix the ugly hack for displaying Chinese in #2110, and then fix #2297
This commit is contained in:
commit
f788ae0f3a
104
lib/irrlicht/include/utfwrapping.h
Normal file
104
lib/irrlicht/include/utfwrapping.h
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright (C) 2015 Ben Au
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//Here a list of characters that don't start or end a line for chinese/japanese/korean
|
||||
//Only commonly use and full width characters are included
|
||||
//You should use full width characters when writing CJK, like using "。"instead of a "."
|
||||
//You can add more characters if needed
|
||||
//For full list please visit http://webapp.docx4java.org/OnlineDemo/ecma376/WordML/kinsoku.html
|
||||
|
||||
bool UtfNoStarting (wchar_t c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 12293: //々
|
||||
return true;
|
||||
case 12297: //〉
|
||||
return true;
|
||||
case 12299: //》
|
||||
return true;
|
||||
case 12301: //」
|
||||
return true;
|
||||
case 65373: //}
|
||||
return true;
|
||||
case 12309: //〕
|
||||
return true;
|
||||
case 65289: //)
|
||||
return true;
|
||||
case 12303: //』
|
||||
return true;
|
||||
case 12305: //】
|
||||
return true;
|
||||
case 12311: //〗
|
||||
return true;
|
||||
case 65281: //!
|
||||
return true;
|
||||
case 65285: //%
|
||||
return true;
|
||||
case 65311: //?
|
||||
return true;
|
||||
case 65344: //`
|
||||
return true;
|
||||
case 65292: //,
|
||||
return true;
|
||||
case 65306: //:
|
||||
return true;
|
||||
case 65307: //;
|
||||
return true;
|
||||
case 65294: //.
|
||||
return true;
|
||||
case 12290: //。
|
||||
return true;
|
||||
case 12289: //、
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool UtfNoEnding (wchar_t c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 12296: //〈
|
||||
return true;
|
||||
case 12298: //《
|
||||
return true;
|
||||
case 12300: //「
|
||||
return true;
|
||||
case 65371: //{
|
||||
return true;
|
||||
case 12308: //〔
|
||||
return true;
|
||||
case 65288: //(
|
||||
return true;
|
||||
case 12302: //『
|
||||
return true;
|
||||
case 12304: //【
|
||||
return true;
|
||||
case 12310: //〖
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Helper function
|
||||
|
||||
bool breakable (wchar_t c)
|
||||
{
|
||||
if ((c > 12287 && c < 40960) || //Common CJK words
|
||||
(c > 44031 && c < 55204) || //Hangul
|
||||
(c > 63743 && c < 64256) || //More Chinese
|
||||
c == 173 || c == L' ' || c == 0) //Soft hyphen and white space
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
} // end namespace core
|
||||
} // end namespace irr
|
@ -10,9 +10,7 @@
|
||||
#include "IGUIFont.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "rect.h"
|
||||
|
||||
#define CJK_START 12287
|
||||
#define CJK_END 40960
|
||||
#include "utfwrapping.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
@ -357,102 +355,77 @@ void CGUIStaticText::breakText()
|
||||
lineBreak = true;
|
||||
c = '\0';
|
||||
}
|
||||
word += c;
|
||||
|
||||
bool isWhitespace = (c == L' ' || c == 0);
|
||||
if ( !isWhitespace )
|
||||
if (word.size())
|
||||
{
|
||||
// part of a word
|
||||
word += c;
|
||||
const s32 wordlgth = font->getDimension(word.c_str()).Width;
|
||||
|
||||
//Check for CJK, show them first if out of range of displaying area
|
||||
if (Text[i] > CJK_START && Text[i] < CJK_END)
|
||||
{
|
||||
const s32 cjklgth = font->getDimension(word.c_str()).Width;
|
||||
if (cjklgth > (elWidth - 23))
|
||||
{
|
||||
BrokenText.push_back(line);
|
||||
length = cjklgth;
|
||||
line = word;
|
||||
word = L"";
|
||||
whitespace = L"";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( isWhitespace || i == (size-1))
|
||||
{
|
||||
if (word.size())
|
||||
{
|
||||
// here comes the next whitespace, look if
|
||||
// we must break the last word to the next line.
|
||||
const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
|
||||
const s32 wordlgth = font->getDimension(word.c_str()).Width;
|
||||
|
||||
if (wordlgth > elWidth)
|
||||
if (length && (length + wordlgth > elWidth))
|
||||
{ // too long to fit inside
|
||||
// break to next line
|
||||
unsigned int where = 1;
|
||||
while (where != line.size()) //Find the first breakable position
|
||||
{
|
||||
// This word is too long to fit in the available space, look for
|
||||
// the Unicode Soft HYphen (SHY / 00AD) character for a place to
|
||||
// break the word at
|
||||
int where = word.findFirst( wchar_t(0x00AD) );
|
||||
if (where != -1)
|
||||
if (UtfNoEnding(Text[i - where]) || //Prevent unsuitable character from displaying
|
||||
UtfNoStarting(Text[i - where]) || //at the position of starting or ending of a line
|
||||
UtfNoStarting(Text[i + 1 - where])) //Handle case which more than one non-newline-starting characters are together
|
||||
{
|
||||
core::stringw first = word.subString(0, where);
|
||||
core::stringw second = word.subString(where, word.size() - where);
|
||||
BrokenText.push_back(line + first + L"-");
|
||||
const s32 secondLength = font->getDimension(second.c_str()).Width;
|
||||
|
||||
length = secondLength;
|
||||
line = second;
|
||||
where++;
|
||||
continue;
|
||||
}
|
||||
if (breakable(Text[i - where]))
|
||||
break;
|
||||
else
|
||||
{
|
||||
// No soft hyphen found, so there's nothing more we can do
|
||||
// break to next line
|
||||
if (length)
|
||||
BrokenText.push_back(line);
|
||||
length = wordlgth;
|
||||
line = word;
|
||||
}
|
||||
where++;
|
||||
}
|
||||
else if (length && (length + wordlgth + whitelgth > elWidth))
|
||||
if (where != line.size())
|
||||
{
|
||||
// break to next line
|
||||
BrokenText.push_back(line);
|
||||
length = wordlgth;
|
||||
line = word;
|
||||
core::stringw first = line.subString(0, line.size() + 1 - where);
|
||||
core::stringw second = line.subString(line.size() + 1 - where , where - 1);
|
||||
if (first.lastChar() == wchar_t(0x00AD))
|
||||
BrokenText.push_back(first + L"-"); //Print the Unicode Soft HYphen (SHY / 00AD) character
|
||||
else
|
||||
BrokenText.push_back(first);
|
||||
const s32 secondLength = font->getDimension(second.c_str()).Width;
|
||||
|
||||
length = secondLength + wordlgth;
|
||||
line = second + word;
|
||||
}
|
||||
else
|
||||
else if (breakable(c) || UtfNoEnding(c) || UtfNoStarting(c)) //Unusual case
|
||||
{
|
||||
BrokenText.push_back(line); //Force breaking to next line too if last word is breakable,
|
||||
line = word; //it happens when someone writes too many non-newline-starting
|
||||
length = wordlgth; //chars in the first line, so we ignore the rules.
|
||||
}
|
||||
// No suitable place to break words, so there's nothing more we can do
|
||||
// break to next line
|
||||
else
|
||||
{
|
||||
// add word to line
|
||||
line += whitespace;
|
||||
line += word;
|
||||
length += whitelgth + wordlgth;
|
||||
length += wordlgth;
|
||||
}
|
||||
|
||||
word = L"";
|
||||
whitespace = L"";
|
||||
}
|
||||
|
||||
if ( isWhitespace )
|
||||
else
|
||||
{
|
||||
whitespace += c;
|
||||
}
|
||||
|
||||
// compute line break
|
||||
if (lineBreak)
|
||||
{
|
||||
line += whitespace;
|
||||
line += word;
|
||||
BrokenText.push_back(line);
|
||||
line = L"";
|
||||
word = L"";
|
||||
whitespace = L"";
|
||||
length = 0;
|
||||
length += wordlgth;
|
||||
}
|
||||
|
||||
word = L"";
|
||||
|
||||
}
|
||||
// compute line break
|
||||
if (lineBreak)
|
||||
{
|
||||
line += word;
|
||||
BrokenText.push_back(line);
|
||||
line = L"";
|
||||
word = L"";
|
||||
length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
line += whitespace;
|
||||
line += word;
|
||||
BrokenText.push_back(line);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user