cococos 2 d-xでは、簡単htmlリッチテキスト表示

100921 ワード

著者:HU
転載は明記してください、原文のリンク:http://www.cnblogs.com/xioapingguo/p/4037414.html
 
cococos 2 d-xが3.0に更新されてからfreetypeを使用し、豊富なテキストを追加しましたが、これらのテキストは自分で設定する必要があり、使い勝手も悪いので、簡単なhtmlリッチテキストを書きました.
使用可能
//フォントサイズ
//フォント、ここにはこのフォントが必要です.
//ストローク
//シャドウ
//リンク
//ピクチャ
//文字色
//下線
 
11111abcdefghijk」の効果:
cocos2d-x中,简单html富文本显示
システム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 = 255;

        _text = "";

        _fontSize = 0;

        _fontName = "";

        _textColor = Color4B::WHITE;

        _outLine = -1;

        _outLineColor = Color4B::BLACK;

        _shadow = false;

        _linkurl =  "";

        _underLinecolor = Color4B(0,0,0,0);

        _underLinesize = -1;

        _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 = -1;

        _color = Color3B::WHITE;

        _opacity = 255;

    }

    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はUTF 8テキストに少し問題があるので、以下にいくつかの方法で自分で実現します.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==0)

    {

        return "";

    }

    unsigned long c, i, ix, q, min=std::string::npos, max=std::string::npos;

    for (q=0, i=0, 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<=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 "";//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(-1),

_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)>>24;

    ret.g = (color&0xffffff)>>16;

    ret.b = (color&0xffff)>>8;

    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, 1));

        return RichElementCustomNode::create(node);

    }

    RichElementText* ret = RichElementText::create(text, _set_fontFile, _set_fontSize);

    if (_set_outline>0)

    {

        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(2);

        if (_set_underline_color.a == 0)

        {

            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 = 0;

    unsigned long posEnd = 0;

    

    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("
"); 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+1; CCLOG("%c",s.at(posStart)); if (s.at(posStart)=='/') { isEnd = true; posStart++; } int keyIndex = 0; for (keyIndex=0; keyIndex<8; keyIndex++) { if(s.compare(posStart, strlen(keywords[keyIndex]), keywords[keyIndex])==0) { break; } } if (keyIndex<8) { switch (keyIndex) { case 0: { posEnd = s.find(">",posStart); if (isEnd) { CCLOG("size end"); _set_fontSize = fontSize; } else { posStart = s.find("=",posStart)+1; int size = atoi(s.substr(posStart,posEnd-posStart).c_str()); _set_fontSize = size; CCLOG("%d",size); } } break; case 1: { posEnd = s.find(">",posStart); if (isEnd) { _set_fontFile = fontFile; CCLOG("fontname end"); } else { posStart = s.find("=",posStart)+1; std::string temp = s.substr(posStart,posEnd-posStart); std::string::value_type p1,p2; p1 = temp.find("\"")+1; p2 = temp.find("\"",p1); std::string fontname = temp.substr(p1,p2-p1); _set_fontFile = fontname; CCLOG("fontname = %s",fontname.c_str()); } } break; case 2: { posEnd = s.find(">",posStart+1); if (isEnd) { CCLOG("outline end"); _set_outline = DEFAULT_OUTLINE; _set_outline_color = DEFAULT_OUTLINE_COLOR; } else { posStart = s.find("=",posStart)+1; 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+1).c_str(), NULL, 16)); _set_outline_color = c; CCLOG("outline color = %d,%d,%d,%d",c.r,c.g,c.b,c.a); } } } break; case 3: { posEnd = s.find(">",posStart); if (isEnd) { CCLOG("shadow end"); _set_shadow = false; } else { _set_shadow = true; CCLOG("shadow start"); } } break; case 4: { posEnd = s.find(">",posStart); if (isEnd) { _set_link = ""; CCLOG("link end"); } else { posStart = s.find("=",posStart)+1; std::string temp = s.substr(posStart,posEnd-posStart); std::string::value_type p1,p2; p1 = temp.find("\"")+1; p2 = temp.find("\"",p1); std::string linkstr = temp.substr(p1,p2-p1); _set_link = linkstr; CCLOG("link = %s",linkstr.c_str()); } } break; case 5: { posEnd = s.find(">",posStart); posStart = s.find("=",posStart)+1; std::string temp = s.substr(posStart,posEnd-posStart); std::string::value_type p1,p2; p1 = temp.find("\"")+1; 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 6: { posEnd = s.find(">",posStart); if (isEnd) { _set_textColor = DEFAULT_COLOR; CCLOG("color end"); } else { posStart = s.find("=",posStart)+1; Color4B c = int2ccc3(strtoul(s.substr(posStart,posEnd-posStart).c_str(), NULL, 16)); _set_textColor = c; CCLOG("%d,%d,%d,%d",c.r,c.g,c.b,c.a); } } break; case 7: { 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)+1; Color4B c = int2ccc3(strtoul(s.substr(posStart,posEnd-posStart).c_str(), NULL, 16)); _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+1; } 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, 0, -1); } 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=0; 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()>0) { elementLabel->enableOutline(elmtText->getOutLineColor(),elmtText->getOutLine()); } if (elmtText->getShadow()) { elementLabel->enableShadow(); } elementLabel->setTextColor(/*elmtText->getTextColor()*/Color4B::RED); if (elmtText->getUnderLineSize()>0) { LayerColor* l = nullptr; if (elmtText->getUnderLineColor().a == 0) { 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=0; 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 = 0; long count = 0; if (!pszText || len <= 0) { return 0; } 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()>0) { 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,0,leftLength); std::string cutWords = utf8_substr(curText, leftLength, curText.length() - leftLength); if (leftLength > 0) { Label* leftRenderer = nullptr; if (fileExist) { leftRenderer = Label::createWithTTF(utf8_substr(leftWords, 0, leftLength), textInfo.getFontName(), textInfo.getFontSize()); } else { leftRenderer = Label::createWithSystemFont(utf8_substr(leftWords, 0, leftLength), textInfo.getFontName(), textInfo.getFontSize()); } if (leftRenderer) { leftRenderer->setColor(textInfo.getColor()); leftRenderer->setOpacity(textInfo.getOpacity()); if (textInfo.getOutLine()>0) { leftRenderer->enableOutline(textInfo.getOutLineColor(),textInfo.getOutLine()); } if (textInfo.getShadow()) { leftRenderer->enableShadow(); } leftRenderer->setTextColor(textInfo.getTextColor()); if (textInfo.getUnderLineSize()>0) { LayerColor* l = nullptr; if (textInfo.getUnderLineColor().a==0) { 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()>0) { textRenderer->enableOutline(textInfo.getOutLineColor(),textInfo.getOutLine()); } if (textInfo.getShadow()) { textRenderer->enableShadow(); } textRenderer->setTextColor(textInfo.getTextColor()); if (textInfo.getUnderLineSize()>0) { LayerColor* l = nullptr; if (textInfo.getUnderLineColor().a==0) { 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[0]); float nextPosX = 0.0f; for (ssize_t j=0; j<row->size(); j++) { Node* l = row->at(j); l->setAnchorPoint(Point::ZERO); l->setPosition(Point(nextPosX, 0.0f)); _elementRenderersContainer->addChild(l, 1); Node* under = dynamic_cast<Node*>(l->getUserObject()); if (under) { under->setPosition(Point(nextPosX,-1)); _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=0; i<_elementRenders.size(); i++) { Vector<Node*>* row = (_elementRenders[i]); float maxHeight = 0.0f; for (ssize_t j=0; 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=0; i<_elementRenders.size(); i++) { Vector<Node*>* row = (_elementRenders[i]); float nextPosX = 0.0f; nextPosY -= (maxHeights[i] + _verticalSpace); for (ssize_t j=0; j<row->size(); j++) { Node* l = row->at(j); l->setAnchorPoint(Point::ZERO); l->setPosition(Point(nextPosX, nextPosY)); _elementRenderersContainer->addChild(l, 1); Node* under = dynamic_cast<Node*>(l->getUserObject()); if (under) { under->setPosition(Point(nextPosX,nextPosY-1)); _elementRenderersContainer->addChild(under); l->setUserObject(nullptr); } nextPosX += l->getContentSize().width; } } _elementRenderersContainer->setContentSize(_contentSize); delete [] maxHeights; } size_t length = _elementRenders.size(); for (size_t i = 0; 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() <= 0) { return; } _elementRenders[_elementRenders.size()-1]->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", 30, Size(300, 300));

    _richText->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

    _richText->setLocalZOrder(10);

    

    addChild(_richText);