最近做聊天系统,遇到棘手的问题,就是字体要支持多颜色、换行、表情(图片)、超链接!我们不会从OpenGL底层来做这个工作,因为那样工作量非常大,不现实,考虑在已有的cocos2d-x接口上进行处理,来组合出我们需要富文本。因Android IOS 似乎都支持 freetype2,所以就优先考虑了。
freetype2:http://download.savannah.gnu.org/releases/freetype/
扩展库:https://github.com/happykevins/cocos2dx-ext
2.1 配置freetype2
2.2.创建工程,添加文件,如下:
工程根目录:
class文件夹:
vs2010工程目录:
HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "cocos-ext.h" #include <renren-ext.h> USING_NS_CC; USING_NS_CC_EXT; class HelloWorld : public cocos2d::CCLayer { public: // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::CCScene* scene(); // a selector callback void menuCloseCallback(CCObject* pSender); // implement the "static node()" method manually CREATE_FUNC(HelloWorld); bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); void ccTouchMoved(CCTouch* pTouch, CCEvent* pEvent); // HTML events void onHTMLClicked( IRichNode* root, IRichElement* ele, int _id); void onHTMLMoved( IRichNode* root, IRichElement* ele, int _id, const CCPoint& location, const CCPoint& delta); }; #endif // __HELLOWORLD_SCENE_H__HelloWorldScene.cpp
static CCHTMLLabel* s_htmlLabel = NULL; std::string tt; // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !CCLayer::init() ) { return false; } CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); ///////////////////////////// // 2. add a menu item with "X" image, which is clicked to quit the program // you may modify it. // add a "close" icon to exit the progress. it's an autorelease object CCMenuItemImage *pCloseItem = CCMenuItemImage::create( "CloseNormal.png", "CloseSelected.png", this, menu_selector(HelloWorld::menuCloseCallback)); pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 , origin.y + pCloseItem->getContentSize().height/2)); // create menu, it's an autorelease object CCMenu* pMenu = CCMenu::create(pCloseItem, NULL); pMenu->setPosition(CCPointZero); this->addChild(pMenu, 1); using namespace dfont; CCLayerColor* l = CCLayerColor::create(ccc4(0xb0, 0xb0, 0xb0, 0xff)); l->setContentSize(this->getContentSize()); this->addChild(l); //控件文字样式(尺寸、对齐方式、字体等等) // font1 FontCatalog* font_catalog = NULL; font_catalog = FontFactory::instance()->create_font( "font1", "simhei.ttf", 0xffffffff, 32, e_plain, 0.0f, 0xffffffff, 0); // font2 font_catalog = FontFactory::instance()->create_font( "font2", "simkai.ttf", 0xffffffff, 24, e_shadow, 1.0f, 0xff000000, 0); font_catalog->add_hackfont("htmltest/Marker Felt.ttf", latin_charset(), -1); // font3 font_catalog = FontFactory::instance()->create_font( "font3", "simli.ttf", 0xffffffff, 20, e_border, 1.0f, 0xff000000, 0); font_catalog->add_hackfont("simhei.ttf", latin_charset(), 5); CCSize vsize = CCDirector::sharedDirector()->getVisibleSize(); CCString* str_utf8 = CCString::createWithContentsOfFile("html.htm"); CCHTMLLabel* htmllabel = CCHTMLLabel::createWithString(str_utf8->getCString(), CCSize(vsize.width*0.8f, vsize.height), "default"); htmllabel->setAnchorPoint(ccp(0.5f,0.5f)); htmllabel->setPosition(ccp(vsize.width*0.5f, vsize.height*0.5f)); addChild(htmllabel); s_htmlLabel = htmllabel; //创建超链接 htmllabel->registerListener(this, &HelloWorld::onHTMLClicked, &HelloWorld::onHTMLMoved ); FontFactory::instance()->dump_textures(); return true; } void HelloWorld::onHTMLClicked( IRichNode* root, IRichElement* ele, int _id) { CCLog("[On Clicked] id=%d", _id); if ( !s_htmlLabel ) { return; } else if ( _id == 1002 ) // close { s_htmlLabel->setVisible(false); } else if ( _id == 2000 ) //reload { CCString* str_utf8 = CCString::createWithContentsOfFile("html.htm"); s_htmlLabel->setString(str_utf8->getCString()); } } void HelloWorld::onHTMLMoved( IRichNode* root, IRichElement* ele, int _id, const CCPoint& location, const CCPoint& delta) { CCLog("[On Moved] id=%d", _id); if ( !s_htmlLabel ) { return; } else if ( _id == 1001 ) { s_htmlLabel->setPosition(ccpAdd(delta, s_htmlLabel->getPosition())); } } bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) { return true; } void HelloWorld::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) { }
点击超链接:
控制台显示: