Merge pull request #5302 from Pisces000221/improve-label-chinese

closed #3933 :A string which only contains CJK characters can't make a line-break when it's needed
This commit is contained in:
James Chen 2014-02-10 11:03:03 +08:00
commit eda4c9a420
6 changed files with 169 additions and 7 deletions

View File

@ -107,26 +107,41 @@ bool LabelTextFormatter::multilineText(Label *theLabel)
startOfLine = startOfWord; startOfLine = startOfWord;
isStartOfLine = true; isStartOfLine = true;
} }
// Whitespace. // 1) Whitespace.
if (isspace_unicode(character)) // 2) This character is non-CJK, but the last character is CJK
if (isspace_unicode(character) ||
!last_word.empty() && iscjk_unicode(last_word.back()) && !iscjk_unicode(character))
{ {
last_word.push_back(character); // if current character is white space, put it into the current word
if (isspace_unicode(character)) last_word.push_back(character);
multiline_string.insert(multiline_string.end(), last_word.begin(), last_word.end()); multiline_string.insert(multiline_string.end(), last_word.begin(), last_word.end());
last_word.clear(); last_word.clear();
isStartOfWord = false; isStartOfWord = false;
startOfWord = -1; startOfWord = -1;
// put the CJK character in the last word
// and put the non-CJK(ASCII) character in the current word
if (!isspace_unicode(character)) last_word.push_back(character);
continue; continue;
} }
// CJK characters.
if (iscjk_unicode(character))
{
multiline_string.insert(multiline_string.end(), last_word.begin(), last_word.end());
last_word.clear();
isStartOfWord = false;
startOfWord = -1;
}
float posRight = (info->position.x + info->contentSize.width) * scalsX; float posRight = (info->position.x + info->contentSize.width) * scalsX;
// Out of bounds. // Out of bounds.
if (posRight - startOfLine > lineWidth) if (posRight - startOfLine > lineWidth)
{ {
if (!breakLineWithoutSpace) if (!breakLineWithoutSpace && !iscjk_unicode(character))
{ {
last_word.push_back(character); last_word.push_back(character);
int found = cc_utf8_find_last_not_char(multiline_string, ' '); int found = cc_utf8_find_last_not_char(multiline_string, ' ');
if (found != -1) if (found != -1)
cc_utf8_trim_ws(&multiline_string); cc_utf8_trim_ws(&multiline_string);
@ -145,6 +160,7 @@ bool LabelTextFormatter::multilineText(Label *theLabel)
cc_utf8_trim_ws(&last_word); cc_utf8_trim_ws(&last_word);
last_word.push_back('\n'); last_word.push_back('\n');
multiline_string.insert(multiline_string.end(), last_word.begin(), last_word.end()); multiline_string.insert(multiline_string.end(), last_word.begin(), last_word.end());
last_word.clear(); last_word.clear();
isStartOfWord = false; isStartOfWord = false;
@ -349,4 +365,4 @@ bool LabelTextFormatter::createStringSprites(Label *theLabel)
return true; return true;
} }
NS_CC_END NS_CC_END

View File

@ -171,6 +171,18 @@ bool isspace_unicode(unsigned short ch)
|| ch == 0x205F || ch == 0x3000; || ch == 0x205F || ch == 0x3000;
} }
bool iscjk_unicode(unsigned short ch)
{
return (ch >= 0x4E00 && ch <= 0x9FBF) // CJK Unified Ideographs
|| (ch >= 0x2E80 && ch <= 0x2FDF) // CJK Radicals Supplement & Kangxi Radicals
|| (ch >= 0x2FF0 && ch <= 0x30FF) // Ideographic Description Characters, CJK Symbols and Punctuation & Japanese
|| (ch >= 0x3100 && ch <= 0x31BF) // Korean
|| (ch >= 0xAC00 && ch <= 0xD7AF) // Hangul Syllables
|| (ch >= 0xF900 && ch <= 0xFAFF) // CJK Compatibility Ideographs
|| (ch >= 0xFE30 && ch <= 0xFE4F) // CJK Compatibility Forms
|| (ch >= 0x31C0 && ch <= 0x4DFF); // Other exiensions
}
void cc_utf8_trim_ws(std::vector<unsigned short>* str) void cc_utf8_trim_ws(std::vector<unsigned short>* str)
{ {
int len = static_cast<int>(str->size()); int len = static_cast<int>(str->size());

View File

@ -41,6 +41,17 @@ CC_DLL void cc_utf8_trim_ws(std::vector<unsigned short>* str);
* */ * */
CC_DLL bool isspace_unicode(unsigned short ch); CC_DLL bool isspace_unicode(unsigned short ch);
/**
* Whether the character is a Chinese/Japanese/Korean character.
*
* @param ch the unicode character
* @returns whether the character is a Chinese character.
*
* @see http://www.searchtb.com/2012/04/chinese_encode.html
* @see http://tieba.baidu.com/p/748765987
* */
CC_DLL bool iscjk_unicode(unsigned short ch);
/** /**
* Returns the length of the string in characters. * Returns the length of the string in characters.
* *

View File

@ -63,6 +63,7 @@ static std::function<Layer*()> createFunctions[] =
CL(LabelTTFColor), CL(LabelTTFColor),
CL(LabelTTFFontsTestNew), CL(LabelTTFFontsTestNew),
CL(LabelTTFDynamicAlignment), CL(LabelTTFDynamicAlignment),
CL(LabelTTFCJKWrappingTest),
CL(LabelTTFUnicodeNew), CL(LabelTTFUnicodeNew),
CL(LabelBMFontTestNew), CL(LabelBMFontTestNew),
CL(LabelTTFDistanceField), CL(LabelTTFDistanceField),
@ -1071,6 +1072,56 @@ std::string LabelTTFDynamicAlignment::subtitle() const
return "Uses the new Label with TTF. Testing alignment"; return "Uses the new Label with TTF. Testing alignment";
} }
//
// NewLabelTTF Chinese/Japanese/Korean wrapping test
//
LabelTTFCJKWrappingTest::LabelTTFCJKWrappingTest()
{
auto size = Director::getInstance()->getWinSize();
auto drawNode = DrawNode::create();
drawNode->setAnchorPoint(Point(0, 0));
this->addChild(drawNode);
drawNode->drawSegment(
Point(size.width * 0.1, size.height * 0.8),
Point(size.width * 0.1, 0), 1, Color4F(1, 0, 0, 1));
drawNode->drawSegment(
Point(size.width * 0.85, size.height * 0.8),
Point(size.width * 0.85, 0), 1, Color4F(1, 0, 0, 1));
TTFConfig ttfConfig("fonts/wt021.ttf", 50, GlyphCollection::DYNAMIC);
auto label1 = Label::createWithTTF(ttfConfig,
"你好Cocos2d-x v3的New Label。", TextHAlignment::LEFT, size.width * 0.75);
label1->setColor(Color3B(128, 255, 255));
label1->setPosition(Point(size.width * 0.1, size.height * 0.6));
label1->setAnchorPoint(Point(0, 0.5));
this->addChild(label1);
auto label2 = Label::createWithTTF(ttfConfig,
"早上好Cocos2d-x v3的New Label。", TextHAlignment::LEFT, size.width * 0.75);
label2->setColor(Color3B(255, 128, 255));
label2->setPosition(Point(size.width * 0.1, size.height * 0.4));
label2->setAnchorPoint(Point(0, 0.5));
this->addChild(label2);
auto label3 = Label::createWithTTF(ttfConfig,
"美好的一天啊美好的一天啊美好的一天啊", TextHAlignment::LEFT, size.width * 0.75);
label3->setColor(Color3B(255, 255, 128));
label3->setPosition(Point(size.width * 0.1, size.height * 0.2));
label3->setAnchorPoint(Point(0, 0.5));
this->addChild(label3);
}
std::string LabelTTFCJKWrappingTest::title() const
{
return "New Label + .TTF";
}
std::string LabelTTFCJKWrappingTest::subtitle() const
{
return "New Label with CJK + ASCII characters\n"
"Characters should stay in the correct position";
}
// //
// NewLabelTTF unicode test // NewLabelTTF unicode test
// //

View File

@ -287,6 +287,19 @@ private:
}; };
class LabelTTFCJKWrappingTest : public AtlasDemoNew
{
public:
CREATE_FUNC(LabelTTFCJKWrappingTest);
LabelTTFCJKWrappingTest();
virtual std::string title() const override;
virtual std::string subtitle() const override;
private:
};
class LabelTTFFontsTestNew : public AtlasDemoNew class LabelTTFFontsTestNew : public AtlasDemoNew
{ {
public: public:

View File

@ -1008,6 +1008,64 @@ function LabelTTFDynamicAlignment.setAlignmentRight(pSender)
end end
--------------------------------------------------------
----- LabelTTFCJKWrappingTest
--------------------------------------------------------
local LabelTTFCJKWrappingTest = {}
function LabelTTFCJKWrappingTest.create()
local layer = cc.Layer:create()
Helper.initWithLayer(layer)
Helper.titleLabel:setString("New Label + .TTF")
Helper.subtitleLabel:setString(
"New Label with CJK + ASCII characters\n"
.. "Characters should stay in the correct position")
local size = cc.Director:getInstance():getVisibleSize()
local ttfConfig = {}
ttfConfig.fontFilePath = "fonts/wt021.ttf"
ttfConfig.fontSize = 50
ttfConfig.glyphs = cc.GLYPHCOLLECTION_DYNAMIC
ttfConfig.customGlyphs = nil
ttfConfig.distanceFieldEnabled = true
local drawNode = cc.DrawNode:create()
drawNode:setAnchorPoint(cc.p(0, 0))
layer:addChild(drawNode)
drawNode:drawSegment(
cc.p(size.width * 0.1, size.height * 0.8),
cc.p(size.width * 0.1, 0), 1, cc.c4f(1, 0, 0, 1))
drawNode:drawSegment(
cc.p(size.width * 0.85, size.height * 0.8),
cc.p(size.width * 0.85, 0), 1, cc.c4f(1, 0, 0, 1))
local label1 = cc.Label:createWithTTF(
ttfConfig, "你好Cocos2d-x v3的New Label。",
cc.TEXT_ALIGNMENT_LEFT, size.width * 0.75)
label1:setColor(cc.c3b(128, 255, 255))
label1:setPosition(cc.p(size.width * 0.1, size.height * 0.6))
label1:setAnchorPoint(cc.p(0, 0.5))
layer:addChild(label1)
local label2 = cc.Label:createWithTTF(
ttfConfig, "早上好Cocos2d-x v3的New Label。",
cc.TEXT_ALIGNMENT_LEFT, size.width * 0.75)
label2:setColor(cc.c3b(255, 128, 255))
label2:setPosition(cc.p(size.width * 0.1, size.height * 0.4))
label2:setAnchorPoint(cc.p(0, 0.5))
layer:addChild(label2)
local label3 = cc.Label:createWithTTF(
ttfConfig, "美好的一天啊美好的一天啊美好的一天啊",
cc.TEXT_ALIGNMENT_LEFT, size.width * 0.75)
label3:setColor(cc.c3b(255, 255, 128))
label3:setPosition(cc.p(size.width * 0.1, size.height * 0.2))
label3:setAnchorPoint(cc.p(0, 0.5))
layer:addChild(label3)
return layer
end
-------------------------------------------------------- --------------------------------------------------------
----- LabelTTFFontsTestNew ----- LabelTTFFontsTestNew
-------------------------------------------------------- --------------------------------------------------------
@ -1262,6 +1320,7 @@ function LabelTestNew()
LabelFNTBounds.create, LabelFNTBounds.create,
LabelTTFLongLineWrapping.create, LabelTTFLongLineWrapping.create,
LabelTTFDynamicAlignment.create, LabelTTFDynamicAlignment.create,
LabelTTFCJKWrappingTest.create,
LabelTTFFontsTestNew.create, LabelTTFFontsTestNew.create,
LabelBMFontTestNew.create, LabelBMFontTestNew.create,
LabelTTFDistanceField.create, LabelTTFDistanceField.create,