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:
auriamg 2015-09-01 19:34:03 -04:00
commit f788ae0f3a
2 changed files with 156 additions and 79 deletions

View 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

View File

@ -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);
}