关于字符编码的知识,请参考前辈的博客:字符串和编码格式
这里使用的是cocos2dx的2.2.3版本,底层的RictText换行机制不能满足中文换行,需要改动。由于在3.x的版本已经优化了,而且以后的项目也会转到3.x的版本,所以这里只是做一个记录,对底层换行机制的思想做一个分析,仅供学习用。
RichText的换行原理:
以文本换行为例(图片同样的道理),先用一个不带换行的label,算出该label的总长度L,然后和程序设定的宽w比较,w<L则一行足以,否则按w在L中比例来截取原字符串,作为第一行,剩余部分递归处理。看代码:
-
<span style="font-size:14px;">void RichText::handleTextRenderer(const char *text, const char *fontName, float fontSize, const ccColor3B &color, GLubyte opacity)
-
{
-
-
CCLabelTTF* textRenderer = CCLabelTTF::create(text, fontName, fontSize);
-
-
float textRendererWidth = textRenderer->getContentSize().width;
-
-
_leftSpaceWidth -= textRendererWidth;
-
if (_leftSpaceWidth < 0.0f)
-
{
-
-
float overstepPercent = (-_leftSpaceWidth) / textRendererWidth;
-
std::string curText = text;
-
-
int stringLength = curText.length();
-
-
int leftLength = stringLength * (1.0f - overstepPercent);
-
-
std::string leftWords = curText.substr(0, leftLength);
-
std::string cutWords = curText.substr(leftLength, curText.length()-1);
-
-
if (leftLength > 0)
-
{
-
CCLabelTTF* leftRenderer = CCLabelTTF::create(leftWords.substr(0, leftLength).c_str(), fontName, fontSize);
-
leftRenderer->setColor(color);
-
leftRenderer->setOpacity(opacity);
-
pushToContainer(leftRenderer);
-
}
-
-
-
addNewLine();
-
handleTextRenderer(cutWords.c_str(), fontName, fontSize, color, opacity);
-
}
-
else
-
{
-
textRenderer->setColor(color);
-
textRenderer->setOpacity(opacity);
-
pushToContainer(textRenderer);
-
}</span>
这里的重点是截取字串的方式,自带的substr不能很好的处理多字节字符的截取,中文会出现乱码,所以用自己写的函数实现,这个函数在网上能找到,但仍然有问题,我做了一些修改,将原来的substr改为自定义的“utf8_substr”函数:
-
<span style="font-size:14px;">
-
-
-
-
-
static std::string utf8_substr(const std::string& str, unsigned long start, unsigned long leng)
-
{
-
if (leng==0)
-
{
-
return "";
-
}
-
unsigned long c, i, strLen, minIdx=std::string::npos, actualLength=std::string::npos;
-
-
long startOffset,lenOffset;
-
for (i=0, strLen=str.length(); i <= strLen; i++)
-
{
-
-
if (i <= start)
-
{
-
minIdx = i;
-
startOffset = start - minIdx;
-
}
-
-
if (i <= start+leng)
-
{
-
lenOffset = start+leng - i;
-
actualLength = leng + abs(startOffset) - abs(lenOffset);
-
}
-
-
-
c = (unsigned char) str[i];
-
if (c<=127) i+=0;
-
else if ((c & 0xE0) == 0xC0) i+=1;
-
else if ((c & 0xF0) == 0xE0) i+=2;
-
else if ((c & 0xF8) == 0xF0) i+=3;
-
else return "";
-
}
-
if (minIdx==std::string::npos || actualLength==std::string::npos)
-
{
-
return "";
-
}
-
-
return str.substr(minIdx,actualLength);
-
}
-
</span>
字符编码表:
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx
10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx
10xxxxxx 10xxxxxx
将上面的utf8_substr函数添加到RichText.cpp中,替换类中用到substr的地方即可。
cocos2d-x改底层之RichText富文本换行
原文:http://blog.csdn.net/ys5773477/article/details/46508617