作者:HU

转载请注明,原文链接:http://www.cnblogs.com/xioapingguo/p/4037414.html 

虽然自从cocos2d-x更新到3.0后,使用freetype,并且增加了丰富文本,但这些文本都需要自己去设置,用起来也不方便,所以动手写了个简单html富文本

可以使用

<size=15></size>//字体大小

<fontname=“Arial”></fontname>//字体,这里必须有这个字体才能使用

<outline=2 color = 0xFFFFFFFF></outline>//描边

<shadow></shadow>//阴影

<link=“”></link>//链接

<img=“”>//图片

<color=0XFFFFFFFF></color>//文字颜色

<u=0xFF000000></u>//下划线

如“<fontname= \"Arial\"  ><shadow>11111</shadow></fontname><u><link=\"www.baidu.com\">abc</link></u><img=\"CloseSelected.png\"><color = 0xFF><size=50>defg</color><outline=2 color=0xFF0000FF>hijk</outline></size>”效果:

cocos2d-x中,简单html富文本显示-LMLPHP

因为兼容了系统UIRichText的功能,所以直接把UIRichText替换了

下面是头文件UIRichText.h

#ifndef __UIRICHTEXT_H__
#define __UIRICHTEXT_H__ #include "ui/UIWidget.h" NS_CC_BEGIN
/*
<size=15></size>
<fontname=“Arial”></fontname>
<outline=2 color = 0xFFFFFFFF></outline>
<shadow></shadow>
<link=“”></link>
<img=“”>
<color=0XFFFFFFFF></color>
<u=0xFF000000></u>
*/
namespace ui { class RichElement : public Ref
{
public:
enum class Type
{
TEXT,
IMAGE,
CUSTOM
};
RichElement(){};
virtual ~RichElement(){};
protected:
Type _type;
CC_SYNTHESIZE(std::string,_tag,Tag);
friend class RichText;
}; class RichElementText : public RichElement
{
public: RichElementText()
{
_type = Type::TEXT;
_color = Color3B::WHITE;
_opacity = ;
_text = "";
_fontSize = ;
_fontName = "";
_textColor = Color4B::WHITE;
_outLine = -;
_outLineColor = Color4B::BLACK;
_shadow = false;
_linkurl = "";
_underLinecolor = Color4B(,,,);
_underLinesize = -;
_touchCallback = nullptr;
}
virtual ~RichElementText(){}; bool init(const std::string& text, const std::string& fontFile, float fontSize);
static RichElementText* create(const std::string& text, const std::string& fontFile, float fontSize); void setTouchCallBack(std::function<void (std::string)> touch,std::string tag);
void setLinkUrl(std::string linkurl);
protected:
CC_SYNTHESIZE(Color3B,_color,Color);
CC_SYNTHESIZE(GLubyte,_opacity,Opacity);
CC_SYNTHESIZE(std::string,_text,Text);
CC_SYNTHESIZE(std::string,_fontName,FontName);
CC_SYNTHESIZE(float,_fontSize,FontSize);
CC_SYNTHESIZE(Color4B,_textColor,TextColor);
CC_SYNTHESIZE(int,_outLine,OutLine);
CC_SYNTHESIZE(Color4B,_outLineColor,OutLineColor);
CC_SYNTHESIZE(bool,_shadow,Shadow);
CC_SYNTHESIZE_READONLY(std::string,_linkurl,LinkUrl);
CC_SYNTHESIZE(Color4B,_underLinecolor,UnderLineColor);
CC_SYNTHESIZE(int,_underLinesize,UnderLineSize);
CC_SYNTHESIZE_READONLY(std::function<void (std::string)>, _touchCallback, TouchCallBack);
//std::function<void (std::string)> _touchCallback;
friend class RichText; private:
void linkCallback(std::string str);
}; class RichElementImage : public RichElement
{
public:
RichElementImage()
{
_type = Type::IMAGE;
_tag = -;
_color = Color3B::WHITE;
_opacity = ;
}
virtual ~RichElementImage(){};
bool init(const std::string& filePath);
static RichElementImage* create(const std::string& filePath);
protected:
CC_SYNTHESIZE(Color3B,_color,Color);
CC_SYNTHESIZE(GLubyte,_opacity,Opacity); std::string _filePath;
Rect _textureRect;
int _textureType;
friend class RichText;
}; class RichElementCustomNode : public RichElement
{
public:
RichElementCustomNode()
{
_type = Type::CUSTOM;
_customNode = nullptr;
};
virtual ~RichElementCustomNode()
{
CC_SAFE_RELEASE(_customNode);
};
bool init(Node* customNode);
static RichElementCustomNode* create(Node* customNode);
protected:
CC_SYNTHESIZE(Color3B,_color,Color);
CC_SYNTHESIZE(GLubyte,_opacity,Opacity); Node* _customNode;
friend class RichText;
}; class RichText : public Widget
{
public:
RichText();
virtual ~RichText();
static RichText* create();
static RichText* create(std::string str,const std::string& fontFile, float fontSize,const Size& size);
bool initWithStr(std::string str,const std::string& fontFile, float fontSize,const Size& size);
void insertElement(RichElement* element, int index);
void pushBackElement(RichElement* element);
void removeElement(int index);
void removeElement(RichElement* element);
virtual void visit(Renderer* renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
void setVerticalSpace(float space);
virtual void setAnchorPoint(const Point& pt);
virtual const Size& getVirtualRendererSize() const override;
void formatText();
virtual void ignoreContentAdaptWithSize(bool ignore);
virtual std::string getDescription() const override; CC_CONSTRUCTOR_ACCESS:
virtual bool init() override;
virtual void onEnter() override;
virtual void onExit() override;
protected:
virtual void initRenderer();
void pushToContainer(Node* renderer);
void handleTextRenderer(const RichElementText& textInfo);
//void handleTextRenderer(const std::string& text, const std::string& fontName, float fontSize, const Color3B& color, GLubyte opacity);
void handleImageRenderer(const std::string& fileParh, const Color3B& color, GLubyte opacity);
void handleCustomRenderer(Node* renderer);
void formarRenderers();
void addNewLine(); bool onTouchBegan(Touch *touch, Event *unusedEvent);
void onTouchEnded(Touch *touch, Event *unusedEvent); CC_SYNTHESIZE(int, _touchPriority, TouchPriority);
protected:
bool _formatTextDirty;
Vector<RichElement*> _richElements;
std::vector<Vector<Node*>*> _elementRenders;
std::map<Node*,std::function<void(std::string)> > _touchDelegate;
float _leftSpaceWidth;
float _verticalSpace;
Node* _elementRenderersContainer;
private:
static float _set_fontSize;
static std::string _set_fontFile;
static int _set_outline;
static Color4B _set_outline_color;
static bool _set_shadow;
static std::string _set_link;
static Color4B _set_textColor;
static bool _set_underline;
static Color4B _set_underline_color; RichElement* createWithSet(const std::string& text);
}; } NS_CC_END #endif /* defined(__UIRichText__) */

下面是Cpp,UIRichText.cpp, 由于3.0对UTF8文本有点问题,下面有几个方法自己实现的,如果3.2下直接使用后面注释掉的就可以了。具体区别对照下原版本的UIRichText.cpp就可以了。

#include "UIRichText.h"

NS_CC_BEGIN

namespace ui {

#define DEFAULT_OUTLINE -1
#define DEFAULT_OUTLINE_COLOR (Color4B(0, 0, 0, 0))
#define DEFAULT_COLOR Color4B::WHITE
#define DEFAULT_UNDERLINE false
#define DEFAULT_UNDERLINE_COLOR (Color4B(0, 0, 0, 0)) int RichText::_set_outline = DEFAULT_OUTLINE;
Color4B RichText::_set_outline_color = DEFAULT_OUTLINE_COLOR;
bool RichText::_set_shadow = false;
bool RichText::_set_underline = DEFAULT_UNDERLINE;
Color4B RichText::_set_underline_color = DEFAULT_UNDERLINE_COLOR;
Color4B RichText::_set_textColor = DEFAULT_COLOR;
std::string RichText::_set_fontFile;
float RichText::_set_fontSize;
std::string RichText::_set_link; static std::string utf8_substr(const std::string& str, unsigned long start, unsigned long leng)
{
if (leng==)
{
return "";
}
unsigned long c, i, ix, q, min=std::string::npos, max=std::string::npos;
for (q=, i=, ix=str.length(); i < ix; i++, q++)
{
if (q==start)
{
min = i;
}
if (q <= start+leng || leng==std::string::npos)
{
max = i;
} c = (unsigned char) str[i]; if (c<=) i+=;
else if ((c & 0xE0) == 0xC0) i+=;
else if ((c & 0xF0) == 0xE0) i+=;
else if ((c & 0xF8) == 0xF0) i+=;
else return "";//invalid utf8
}
if (q <= start+leng || leng == std::string::npos)
{
max = i;
}
if (min==std::string::npos || max==std::string::npos)
{
return "";
}
return str.substr(min,max);
} bool RichElementText::init(const std::string& text, const std::string& fontFile, float fontSize)
{
_text = text;
_fontName = fontFile;
_fontSize = fontSize; return true;
} RichElementText* RichElementText::create(const std::string& text, const std::string& fontFile, float fontSize)
{
RichElementText* htmlElementText = new RichElementText();
if (htmlElementText && htmlElementText->init(text, fontFile, fontSize))
{
htmlElementText->autorelease();
return htmlElementText;
}
CC_SAFE_DELETE(htmlElementText);
return nullptr;
} void RichElementText::setTouchCallBack(std::function<void (std::string)> touch,std::string tag)
{
_touchCallback = touch;
_tag = tag;
} void RichElementText::setLinkUrl(std::string linkurl)
{
_linkurl = linkurl;
setTouchCallBack(std::bind(&RichElementText::linkCallback, this,std::placeholders::_1),linkurl);
} void RichElementText::linkCallback(std::string str)
{
CCLOG("call open url %s",str.c_str());
} bool RichElementImage::init(const std::string& filePath)
{
_filePath = filePath;
return true;
} RichElementImage* RichElementImage::create(const std::string& filePath)
{
RichElementImage* htmlElementImage = new RichElementImage();
if (htmlElementImage && htmlElementImage->init(filePath))
{
htmlElementImage->autorelease();
return htmlElementImage;
}
CC_SAFE_DELETE(htmlElementImage);
return nullptr;
} bool RichElementCustomNode::init(cocos2d::Node *customNode)
{
_customNode = customNode;
_customNode->retain();
return true;
} RichElementCustomNode* RichElementCustomNode::create(cocos2d::Node *customNode)
{
RichElementCustomNode* element = new RichElementCustomNode();
if (element && element->init(customNode))
{
element->autorelease();
return element;
}
CC_SAFE_DELETE(element);
return nullptr;
} RichText::RichText():
_formatTextDirty(true),
_leftSpaceWidth(0.0f),
_verticalSpace(0.0f),
_touchPriority(-),
_elementRenderersContainer(nullptr)
{
_touchDelegate.clear();
} RichText::~RichText()
{
_richElements.clear();
std::map<Node*,std::function<void(std::string)> >::const_iterator it = _touchDelegate.begin();
while (it != _touchDelegate.end())
{
Node* node = it->first;
if (node->getUserData()!=nullptr)
{
delete (std::string*)(node->getUserData());
node->setUserData(nullptr);
}
++it;
} _touchDelegate.clear();
} RichText* RichText::create()
{
RichText* widget = new RichText();
if (widget && widget->init())
{
widget->autorelease();
return widget;
}
CC_SAFE_DELETE(widget);
return nullptr;
} RichText* RichText::create(std::string str,const std::string& fontFile, float fontSize,const Size& size)
{
RichText* widget = new RichText();
if (widget && widget->initWithStr(str,fontFile,fontSize,size))
{
widget->autorelease();
return widget;
}
CC_SAFE_DELETE(widget);
return nullptr;
} bool RichText::init()
{
if (!Widget::init())
{
return false;
} return true;
}
static const char* keywords[] = {"size","fontname","outline","shadow","link","img","color","u"}; static Color4B int2ccc3(unsigned long color)
{
Color4B ret;
ret.r = (color&0xffffffff)>>;
ret.g = (color&0xffffff)>>;
ret.b = (color&0xffff)>>;
ret.a = color&0xff;
return ret;
} RichElement* RichText::createWithSet(const std::string& text)
{
if (text.empty())
{
Node* node = Node::create();
node->setContentSize(Size(getContentSize().width, ));
return RichElementCustomNode::create(node);
}
RichElementText* ret = RichElementText::create(text, _set_fontFile, _set_fontSize);
if (_set_outline>)
{
ret->setOutLine(_set_outline);
ret->setOutLineColor(_set_outline_color);
} ret->setShadow(_set_shadow);
if (!_set_link.empty())
{
ret->setLinkUrl(_set_link);
} CCLOG("%d,%d,%d,%d",_set_textColor.r,_set_textColor.g,_set_textColor.b,_set_textColor.a);
ret->setTextColor(_set_textColor);
if (_set_underline)
{
ret->setUnderLineSize();
if (_set_underline_color.a == )
{
ret->setUnderLineColor(_set_textColor);
}
else
{
ret->setUnderLineColor(_set_underline_color);
}
} return ret;
} bool RichText::initWithStr(std::string str,const std::string& fontFile, float fontSize,const Size& size)
{
if (!Widget::init())
{
return false;
}
ignoreContentAdaptWithSize(false);
//setContentSize(size);
setSize(size); _set_fontSize = fontSize;
_set_fontFile = fontFile;
_set_textColor = DEFAULT_COLOR; std::string s = str;
unsigned long posStart = ;
unsigned long posEnd = ; while (posStart<s.length())
{
bool isEnd = false;
posEnd = s.find("<",posStart); if (posStart!=posEnd)
{
std::string tempStr = s.substr(posStart,posEnd-posStart);
std::string::value_type pos = tempStr.find("\n");

        while (pos != std::string::npos)
        {
          std::string s1 = tempStr.substr(0, pos).c_str();
          if (!s1.empty())
          {
            pushBackElement(createWithSet(s1));
          }
          pushBackElement(createWithSet(""));

          tempStr = tempStr.substr(pos + 1).c_str();
          pos = tempStr.find("\n");
        }

        if (!tempStr.empty())
        {
          pushBackElement(createWithSet(tempStr));
        }

// if (pos!=std::string::npos)
// {
// std::string s1 = tempStr.substr(0,pos).c_str();
// if (!s1.empty())
// {
// pushBackElement(createWithSet(s1));
// }
//
// pushBackElement(createWithSet(""));
// std::string s2 = tempStr.substr(pos+1).c_str();
// if (!s2.empty())
// {
// pushBackElement(createWithSet(s2));
// }
//
// }
// else
// {
// CCLOG("%s",tempStr.c_str());
// pushBackElement(createWithSet(tempStr));
// }

if (posEnd==std::string::npos)
{
break;
} } posStart = posEnd+;
CCLOG("%c",s.at(posStart));
if (s.at(posStart)=='/')
{
isEnd = true;
posStart++;
} int keyIndex = ;
for (keyIndex=; keyIndex<; keyIndex++)
{
if(s.compare(posStart, strlen(keywords[keyIndex]), keywords[keyIndex])==)
{
break;
}
} if (keyIndex<)
{
switch (keyIndex)
{
case :
{
posEnd = s.find(">",posStart);
if (isEnd)
{
CCLOG("size end");
_set_fontSize = fontSize;
}
else
{
posStart = s.find("=",posStart)+;
int size = atoi(s.substr(posStart,posEnd-posStart).c_str());
_set_fontSize = size;
CCLOG("%d",size);
}
}
break;
case :
{
posEnd = s.find(">",posStart);
if (isEnd)
{
_set_fontFile = fontFile;
CCLOG("fontname end");
}
else
{
posStart = s.find("=",posStart)+;
std::string temp = s.substr(posStart,posEnd-posStart);
std::string::value_type p1,p2;
p1 = temp.find("\"")+;
p2 = temp.find("\"",p1);
std::string fontname = temp.substr(p1,p2-p1);
_set_fontFile = fontname;
CCLOG("fontname = %s",fontname.c_str());
}
}
break;
case :
{
posEnd = s.find(">",posStart+);
if (isEnd)
{
CCLOG("outline end");
_set_outline = DEFAULT_OUTLINE;
_set_outline_color = DEFAULT_OUTLINE_COLOR;
}
else
{
posStart = s.find("=",posStart)+;
std::string temp = s.substr(posStart,posEnd-posStart);
int size = atoi(temp.c_str());
_set_outline = size;
CCLOG("outline %d",size);
unsigned long p1 = temp.find("=");
if (p1!=std::string::npos)
{
Color4B c = int2ccc3(strtoul(temp.substr(p1+).c_str(), NULL, ));
_set_outline_color = c;
CCLOG("outline color = %d,%d,%d,%d",c.r,c.g,c.b,c.a);
}
}
}
break;
case :
{
posEnd = s.find(">",posStart);
if (isEnd)
{
CCLOG("shadow end");
_set_shadow = false;
}
else
{
_set_shadow = true;
CCLOG("shadow start");
}
}
break;
case :
{
posEnd = s.find(">",posStart);
if (isEnd)
{
_set_link = "";
CCLOG("link end");
}
else
{
posStart = s.find("=",posStart)+;
std::string temp = s.substr(posStart,posEnd-posStart);
std::string::value_type p1,p2;
p1 = temp.find("\"")+;
p2 = temp.find("\"",p1);
std::string linkstr = temp.substr(p1,p2-p1);
_set_link = linkstr;
CCLOG("link = %s",linkstr.c_str());
}
}
break;
case :
{
posEnd = s.find(">",posStart); posStart = s.find("=",posStart)+; std::string temp = s.substr(posStart,posEnd-posStart);
std::string::value_type p1,p2;
p1 = temp.find("\"")+;
p2 = temp.find("\"",p1);
std::string img = temp.substr(p1,p2-p1);
Sprite* s = Sprite::create(img);
if (s)
{
pushBackElement(RichElementCustomNode::create(s));
} CCLOG("img = %s",img.c_str()); }
break;
case :
{
posEnd = s.find(">",posStart);
if (isEnd)
{
_set_textColor = DEFAULT_COLOR;
CCLOG("color end");
}
else
{
posStart = s.find("=",posStart)+;
Color4B c = int2ccc3(strtoul(s.substr(posStart,posEnd-posStart).c_str(), NULL, ));
_set_textColor = c;
CCLOG("%d,%d,%d,%d",c.r,c.g,c.b,c.a);
} }
break;
case :
{
posEnd = s.find(">",posStart);
if (isEnd)
{
_set_underline = false;
_set_underline_color = DEFAULT_UNDERLINE_COLOR;
CCLOG("underline end");
}
else
{
_set_underline = true;
if (s.substr(posStart,posEnd-posStart).find("=")!=std::string::npos)
{
posStart = s.find("=",posStart)+;
Color4B c = int2ccc3(strtoul(s.substr(posStart,posEnd-posStart).c_str(), NULL, ));
_set_underline_color = c;
CCLOG("%d,%d,%d,%d",c.r,c.g,c.b,c.a);
}
else
{
CCLOG("underline no color");
} }
}
break;
default:
break;
}
} posStart = posEnd+;
} return true;
} void RichText::onEnter()
{
Widget::onEnter(); EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = CC_CALLBACK_2(RichText::onTouchBegan, this);
listener->onTouchEnded = CC_CALLBACK_2(RichText::onTouchEnded, this);
_eventDispatcher->addEventListenerWithFixedPriority(listener, _touchPriority);
} void RichText::onExit()
{
Widget::onExit();
_eventDispatcher->removeAllEventListeners();
} bool RichText::onTouchBegan(Touch *touch, Event *unusedEvent)
{
std::map<Node*,std::function<void(std::string)> >::const_iterator it = _touchDelegate.begin();
while (it != _touchDelegate.end())
{
Node* node = it->first;
if (node->getBoundingBox().containsPoint(node->getParent()->convertTouchToNodeSpace(touch)))
{
return true;
}
++it;
}
return false;
} void RichText::onTouchEnded(Touch *touch, Event *unusedEvent)
{
std::map<Node*,std::function<void(std::string)> >::const_iterator it = _touchDelegate.begin();
while (it != _touchDelegate.end())
{
Node* node = it->first;
if (node->getBoundingBox().containsPoint(node->getParent()->convertTouchToNodeSpace(touch)))
{
if (node->getUserData()!=nullptr)
{
(it->second)(*((std::string*)node->getUserData()));
} return;
}
++it;
}
} void RichText::initRenderer()
{
_elementRenderersContainer = Node::create();
_elementRenderersContainer->setAnchorPoint(Point(0.5f, 0.5f));
addProtectedChild(_elementRenderersContainer, , -);
} void RichText::insertElement(RichElement *element, int index)
{
_richElements.insert(index, element);
_formatTextDirty = true;
} void RichText::pushBackElement(RichElement *element)
{
_richElements.pushBack(element);
_formatTextDirty = true;
} void RichText::removeElement(int index)
{
_richElements.erase(index);
_formatTextDirty = true;
} void RichText::removeElement(RichElement *element)
{
_richElements.eraseObject(element);
_formatTextDirty = true;
} void RichText::formatText()
{
if (_formatTextDirty)
{
_elementRenderersContainer->removeAllChildren();
_elementRenders.clear();
if (_ignoreSize)
{
addNewLine();
for (ssize_t i=; i<_richElements.size(); i++)
{
RichElement* element = _richElements.at(i);
Node* elementRenderer = nullptr;
switch (element->_type)
{
case RichElement::Type::TEXT:
{
Label* elementLabel = nullptr;
RichElementText* elmtText = static_cast<RichElementText*>(element);
if (FileUtils::getInstance()->isFileExist(elmtText->_fontName))
{
elementLabel = Label::createWithTTF(elmtText->_text.c_str(), elmtText->_fontName, elmtText->_fontSize);
}
else
{
elementLabel = Label::createWithSystemFont(elmtText->_text.c_str(), elmtText->_fontName, elmtText->_fontSize);
}
if (elmtText->getOutLine()>)
{
elementLabel->enableOutline(elmtText->getOutLineColor(),elmtText->getOutLine());
}
if (elmtText->getShadow())
{
elementLabel->enableShadow();
}
elementLabel->setTextColor(/*elmtText->getTextColor()*/Color4B::RED);
if (elmtText->getUnderLineSize()>)
{
LayerColor* l = nullptr;
if (elmtText->getUnderLineColor().a == )
{
l = LayerColor::create(elmtText->getTextColor(), elementLabel->getContentSize().width, elmtText->getUnderLineSize());
}
else
{
l = LayerColor::create(elmtText->getUnderLineColor(), elementLabel->getContentSize().width, elmtText->getUnderLineSize());
}
elementLabel->setUserObject(l);
}
if (elmtText->getTouchCallBack())
{
std::string* tag = new std::string(elmtText->getTag());
elementLabel->setUserData(tag);
_touchDelegate[elementLabel] = elmtText->getTouchCallBack();
}
elementRenderer = elementLabel;
elementRenderer->setColor(elmtText->_color);
elementRenderer->setOpacity(elmtText->_opacity);
break;
}
case RichElement::Type::IMAGE:
{
RichElementImage* elmtImage = static_cast<RichElementImage*>(element);
elementRenderer = Sprite::create(elmtImage->_filePath.c_str());
elementRenderer->setColor(elmtImage->_color);
elementRenderer->setOpacity(elmtImage->_opacity);
break;
}
case RichElement::Type::CUSTOM:
{
RichElementCustomNode* elmtCustom = static_cast<RichElementCustomNode*>(element);
elementRenderer = elmtCustom->_customNode;
elementRenderer->setColor(elmtCustom->_color);
elementRenderer->setOpacity(elmtCustom->_opacity);
break;
}
default:
break;
} pushToContainer(elementRenderer);
}
}
else
{
addNewLine();
for (ssize_t i=; i<_richElements.size(); i++)
{ RichElement* element = static_cast<RichElement*>(_richElements.at(i));
switch (element->_type)
{
case RichElement::Type::TEXT:
{
RichElementText* elmtText = static_cast<RichElementText*>(element);
handleTextRenderer(*elmtText);
break;
}
case RichElement::Type::IMAGE:
{
RichElementImage* elmtImage = static_cast<RichElementImage*>(element);
handleImageRenderer(elmtImage->_filePath.c_str(), elmtImage->_color, elmtImage->_opacity);
break;
}
case RichElement::Type::CUSTOM:
{
RichElementCustomNode* elmtCustom = static_cast<RichElementCustomNode*>(element);
handleCustomRenderer(elmtCustom->_customNode);
break;
}
default:
break;
}
}
}
formarRenderers();
_formatTextDirty = false;
}
}
#define UTF8_ASCII(byte) (((unsigned char)(byte)>=0x00)&&((unsigned char)(byte)<=0x7F))
#define UTF8_FIRST(byte) (((unsigned char)(byte)>=0xC0)&&((unsigned char)(byte)<=0xFD))
#define UTF8_OTHER(byte) (((unsigned char)(byte)>=0x80)&&((unsigned char)(byte)<=0xBF))
static int _calcCharCount(const char * pszText,int len)
{
char *p = ;
long count = ; if (!pszText || len <= ) {
return ;
} for(p=(char*)pszText; p<pszText+len; p++) {
if (UTF8_ASCII(*p) || (UTF8_FIRST(*p))) {
count++;
}
} return count;
} void RichText::handleTextRenderer(const RichElementText& textInfo)
{
auto fileExist = FileUtils::getInstance()->isFileExist(textInfo.getFontName());
Label* textRenderer = nullptr;
if (fileExist)
{
textRenderer = Label::createWithTTF(textInfo.getText(), textInfo.getFontName(), textInfo.getFontSize());
}
else
{
textRenderer = Label::createWithSystemFont(textInfo.getText(), textInfo.getFontName(), textInfo.getFontSize());
}
if (textInfo.getOutLine()>)
{
textRenderer->enableOutline(textInfo.getOutLineColor(),textInfo.getOutLine());
}
if (textInfo.getShadow())
{
textRenderer->enableShadow();
} float textRendererWidth = textRenderer->getContentSize().width;
_leftSpaceWidth -= textRendererWidth;
if (_leftSpaceWidth < 0.0f)
{
float overstepPercent = (-_leftSpaceWidth) / textRendererWidth;
std::string curText = textInfo.getText();
size_t stringLength = _calcCharCount(textInfo.getText().c_str(),textInfo.getText().length());//StringUtils::getCharacterCountInUTF8String(textInfo.getText());
int leftLength = stringLength * (1.0f - overstepPercent);
std::string leftWords = utf8_substr(curText,,leftLength);
std::string cutWords = utf8_substr(curText, leftLength, curText.length() - leftLength);
if (leftLength > )
{
Label* leftRenderer = nullptr;
if (fileExist)
{
leftRenderer = Label::createWithTTF(utf8_substr(leftWords, , leftLength), textInfo.getFontName(), textInfo.getFontSize());
}
else
{
leftRenderer = Label::createWithSystemFont(utf8_substr(leftWords, , leftLength), textInfo.getFontName(), textInfo.getFontSize());
}
if (leftRenderer)
{
leftRenderer->setColor(textInfo.getColor());
leftRenderer->setOpacity(textInfo.getOpacity()); if (textInfo.getOutLine()>)
{
leftRenderer->enableOutline(textInfo.getOutLineColor(),textInfo.getOutLine());
}
if (textInfo.getShadow())
{
leftRenderer->enableShadow();
}
leftRenderer->setTextColor(textInfo.getTextColor());
if (textInfo.getUnderLineSize()>)
{
LayerColor* l = nullptr;
if (textInfo.getUnderLineColor().a==)
{
l = LayerColor::create(textInfo.getTextColor(), leftRenderer->getContentSize().width, textInfo.getUnderLineSize());
}
else
{
l = LayerColor::create(textInfo.getUnderLineColor(), leftRenderer->getContentSize().width, textInfo.getUnderLineSize());
}
leftRenderer->setUserObject(l);
}
if (textInfo.getTouchCallBack())
{
std::string* tag = new std::string(textInfo.getTag());
leftRenderer->setUserData(tag);
_touchDelegate[leftRenderer] = textInfo.getTouchCallBack();
}
pushToContainer(leftRenderer);
}
} addNewLine();
RichElementText cutRich = textInfo;
cutRich.setText(cutWords);
handleTextRenderer(cutRich);
}
else
{
textRenderer->setColor(textInfo.getColor());
textRenderer->setOpacity(textInfo.getOpacity()); if (textInfo.getOutLine()>)
{
textRenderer->enableOutline(textInfo.getOutLineColor(),textInfo.getOutLine());
}
if (textInfo.getShadow())
{
textRenderer->enableShadow();
}
textRenderer->setTextColor(textInfo.getTextColor());
if (textInfo.getUnderLineSize()>)
{
LayerColor* l = nullptr;
if (textInfo.getUnderLineColor().a==)
{
l = LayerColor::create(textInfo.getTextColor(), textRenderer->getContentSize().width, textInfo.getUnderLineSize());
}
else
{
l = LayerColor::create(textInfo.getUnderLineColor(), textRenderer->getContentSize().width, textInfo.getUnderLineSize());
}
textRenderer->setUserObject(l);
}
if (textInfo.getTouchCallBack())
{
std::string* tag = new std::string(textInfo.getTag());
textRenderer->setUserData(tag);
_touchDelegate[textRenderer] = textInfo.getTouchCallBack();
}
pushToContainer(textRenderer);
}
} void RichText::handleImageRenderer(const std::string& fileParh, const Color3B &color, GLubyte opacity)
{
Sprite* imageRenderer = Sprite::create(fileParh);
if (imageRenderer==nullptr)
{
return;
} imageRenderer->setColor(color);
imageRenderer->setOpacity(opacity);
handleCustomRenderer(imageRenderer);
} void RichText::handleCustomRenderer(cocos2d::Node *renderer)
{
Size imgSize = renderer->getContentSize();
_leftSpaceWidth -= imgSize.width;
if (_leftSpaceWidth < 0.0f)
{
addNewLine();
pushToContainer(renderer);
_leftSpaceWidth -= imgSize.width;
}
else
{
pushToContainer(renderer);
}
} void RichText::addNewLine()
{
_leftSpaceWidth = _customSize.width;
_elementRenders.push_back(new Vector<Node*>());
} void RichText::formarRenderers()
{
if (_ignoreSize)
{
float newContentSizeWidth = 0.0f;
float newContentSizeHeight = 0.0f; Vector<Node*>* row = (_elementRenders[]);
float nextPosX = 0.0f;
for (ssize_t j=; j<row->size(); j++)
{
Node* l = row->at(j);
l->setAnchorPoint(Point::ZERO);
l->setPosition(Point(nextPosX, 0.0f));
_elementRenderersContainer->addChild(l, ); Node* under = dynamic_cast<Node*>(l->getUserObject());
if (under)
{
under->setPosition(Point(nextPosX,-));
_elementRenderersContainer->addChild(under);
l->setUserObject(nullptr);
} Size iSize = l->getContentSize();
newContentSizeWidth += iSize.width;
newContentSizeHeight = MAX(newContentSizeHeight, iSize.height);
nextPosX += iSize.width;
}
_elementRenderersContainer->setContentSize(Size(newContentSizeWidth, newContentSizeHeight));
}
else
{
float newContentSizeHeight = 0.0f;
float *maxHeights = new float[_elementRenders.size()]; for (size_t i=; i<_elementRenders.size(); i++)
{
Vector<Node*>* row = (_elementRenders[i]);
float maxHeight = 0.0f;
for (ssize_t j=; j<row->size(); j++)
{
Node* l = row->at(j);
maxHeight = MAX(l->getContentSize().height, maxHeight);
}
maxHeights[i] = maxHeight;
newContentSizeHeight += maxHeights[i];
} float nextPosY = _customSize.height;
for (size_t i=; i<_elementRenders.size(); i++)
{
Vector<Node*>* row = (_elementRenders[i]);
float nextPosX = 0.0f;
nextPosY -= (maxHeights[i] + _verticalSpace); for (ssize_t j=; j<row->size(); j++)
{
Node* l = row->at(j);
l->setAnchorPoint(Point::ZERO);
l->setPosition(Point(nextPosX, nextPosY));
_elementRenderersContainer->addChild(l, );
Node* under = dynamic_cast<Node*>(l->getUserObject());
if (under)
{
under->setPosition(Point(nextPosX,nextPosY-));
_elementRenderersContainer->addChild(under);
l->setUserObject(nullptr);
}
nextPosX += l->getContentSize().width;
}
}
_elementRenderersContainer->setContentSize(_contentSize);
delete [] maxHeights;
} size_t length = _elementRenders.size();
for (size_t i = ; i<length; i++)
{
Vector<Node*>* l = _elementRenders[i];
l->clear();
delete l;
}
_elementRenders.clear(); if (_ignoreSize)
{
Size s = getVirtualRendererSize();
this->setContentSize(s);
}
else
{
this->setContentSize(_customSize);
}
updateContentSizeWithTextureSize(_contentSize);
_elementRenderersContainer->setPosition(_contentSize.width / 2.0f, _contentSize.height / 2.0f);
} void RichText::pushToContainer(cocos2d::Node *renderer)
{
if (_elementRenders.size() <= )
{
return;
}
_elementRenders[_elementRenders.size()-]->pushBack(renderer);
} void RichText::visit(Renderer* renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{
if (_enabled)
{
formatText();
Widget::visit(renderer, parentTransform, parentTransformUpdated);
}
} void RichText::setVerticalSpace(float space)
{
_verticalSpace = space;
} void RichText::setAnchorPoint(const Point& pt)
{
Widget::setAnchorPoint(pt);
_elementRenderersContainer->setAnchorPoint(pt);
} const Size& RichText::getVirtualRendererSize() const
{
return _elementRenderersContainer->getContentSize();
} void RichText::ignoreContentAdaptWithSize(bool ignore)
{
if (_ignoreSize != ignore)
{
_formatTextDirty = true;
Widget::ignoreContentAdaptWithSize(ignore);
}
} std::string RichText::getDescription() const
{
return "RichText";
} } NS_CC_END

使用方法,上面的str

    RichText* _richText = RichText::create(str, "fonts/Marker Felt.ttf", , Size(, ));
_richText->setPosition(Vec2(visibleSize.width/ + origin.x, visibleSize.height/ + origin.y));
_richText->setLocalZOrder(); addChild(_richText);
05-11 15:15