mirror of https://github.com/axmolengine/axmol.git
issue #3629:new label support customize the effects such as Shadow[blur is unsupported], Outline
This commit is contained in:
parent
c3c3e12ee6
commit
23501b40aa
|
@ -28,11 +28,11 @@
|
||||||
#include "ccUTF8.h"
|
#include "ccUTF8.h"
|
||||||
#include "CCDirector.h"
|
#include "CCDirector.h"
|
||||||
|
|
||||||
#define PAGE_WIDTH 1024
|
|
||||||
#define PAGE_HEIGHT 1024
|
|
||||||
|
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
|
|
||||||
|
const int FontAtlas::CacheTextureWidth = 1024;
|
||||||
|
const int FontAtlas::CacheTextureHeight = 1024;
|
||||||
|
|
||||||
FontAtlas::FontAtlas(Font &theFont) :
|
FontAtlas::FontAtlas(Font &theFont) :
|
||||||
_font(&theFont),
|
_font(&theFont),
|
||||||
_currentPageData(nullptr)
|
_currentPageData(nullptr)
|
||||||
|
@ -44,28 +44,26 @@ _currentPageData(nullptr)
|
||||||
{
|
{
|
||||||
_currentPageLineHeight = _font->getFontMaxHeight();
|
_currentPageLineHeight = _font->getFontMaxHeight();
|
||||||
_commonLineHeight = _currentPageLineHeight * 0.8f;
|
_commonLineHeight = _currentPageLineHeight * 0.8f;
|
||||||
Texture2D * tex = new Texture2D;
|
auto texture = new Texture2D;
|
||||||
_currentPage = 0;
|
_currentPage = 0;
|
||||||
_currentPageOrigX = 0;
|
_currentPageOrigX = 0;
|
||||||
_currentPageOrigY = 0;
|
_currentPageOrigY = 0;
|
||||||
_letterPadding = 0;
|
_letterPadding = 0;
|
||||||
|
|
||||||
_makeDistanceMap = fontTTf->isDistanceFieldEnabled();
|
if(fontTTf->isDistanceFieldEnabled())
|
||||||
if(_makeDistanceMap)
|
|
||||||
{
|
{
|
||||||
_commonLineHeight += 2 * FontFreeType::DistanceMapSpread;
|
|
||||||
_letterPadding += 2 * FontFreeType::DistanceMapSpread;
|
_letterPadding += 2 * FontFreeType::DistanceMapSpread;
|
||||||
}
|
}
|
||||||
_currentPageDataSize = (PAGE_WIDTH * PAGE_HEIGHT * 1);
|
_currentPageDataSize = CacheTextureWidth * CacheTextureHeight;
|
||||||
|
if(fontTTf->getOutlineSize() > 0)
|
||||||
|
{
|
||||||
|
_currentPageDataSize *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
_currentPageData = new unsigned char[_currentPageDataSize];
|
_currentPageData = new unsigned char[_currentPageDataSize];
|
||||||
memset(_currentPageData, 0, _currentPageDataSize);
|
memset(_currentPageData, 0, _currentPageDataSize);
|
||||||
addTexture(*tex,0);
|
addTexture(*texture,0);
|
||||||
tex->release();
|
texture->release();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_makeDistanceMap = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,29 +110,75 @@ bool FontAtlas::prepareLetterDefinitions(unsigned short *utf16String)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
FontFreeType* fontTTf = (FontFreeType*)_font;
|
FontFreeType* fontTTf = (FontFreeType*)_font;
|
||||||
|
|
||||||
std::unordered_map<unsigned short, FontLetterDefinition> fontDefs;
|
|
||||||
int length = cc_wcslen(utf16String);
|
int length = cc_wcslen(utf16String);
|
||||||
|
|
||||||
float offsetAdjust = _letterPadding / 2;
|
float offsetAdjust = _letterPadding / 2;
|
||||||
//find out new letter
|
int bitmapWidth;
|
||||||
|
int bitmapHeight;
|
||||||
|
Rect tempRect;
|
||||||
|
FontLetterDefinition tempDef;
|
||||||
|
|
||||||
|
auto contentSize = Size(CacheTextureWidth,CacheTextureHeight);
|
||||||
|
auto scaleFactor = CC_CONTENT_SCALE_FACTOR();
|
||||||
|
auto pixelFormat = fontTTf->getOutlineSize() > 0 ? Texture2D::PixelFormat::AI88 : Texture2D::PixelFormat::A8;
|
||||||
|
|
||||||
|
bool existNewLetter = false;
|
||||||
for (int i = 0; i < length; ++i)
|
for (int i = 0; i < length; ++i)
|
||||||
{
|
{
|
||||||
auto outIterator = _fontLetterDefinitions.find(utf16String[i]);
|
auto outIterator = _fontLetterDefinitions.find(utf16String[i]);
|
||||||
|
|
||||||
if (outIterator == _fontLetterDefinitions.end())
|
if (outIterator == _fontLetterDefinitions.end())
|
||||||
{
|
{
|
||||||
auto outIterator2 = fontDefs.find(utf16String[i]);
|
existNewLetter = true;
|
||||||
if(outIterator2 != fontDefs.end())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Rect tempRect;
|
auto bitmap = fontTTf->getGlyphBitmap(utf16String[i],bitmapWidth,bitmapHeight,tempRect,tempDef.xAdvance);
|
||||||
|
if (bitmap)
|
||||||
FontLetterDefinition tempDef;
|
|
||||||
|
|
||||||
if (!fontTTf->getBBOXFotChar(utf16String[i], tempRect,tempDef.xAdvance))
|
|
||||||
{
|
{
|
||||||
tempDef.validDefinition = false;
|
tempDef.validDefinition = true;
|
||||||
|
tempDef.letteCharUTF16 = utf16String[i];
|
||||||
|
tempDef.width = tempRect.size.width + _letterPadding;
|
||||||
|
tempDef.height = tempRect.size.height + _letterPadding;
|
||||||
|
tempDef.offsetX = tempRect.origin.x + offsetAdjust;
|
||||||
|
tempDef.offsetY = _commonLineHeight + tempRect.origin.y - offsetAdjust;
|
||||||
|
|
||||||
|
if (_currentPageOrigX + tempDef.width > CacheTextureWidth)
|
||||||
|
{
|
||||||
|
_currentPageOrigY += _currentPageLineHeight;
|
||||||
|
_currentPageOrigX = 0;
|
||||||
|
if(_currentPageOrigY + _currentPageLineHeight >= CacheTextureHeight)
|
||||||
|
{
|
||||||
|
_atlasTextures[_currentPage]->initWithData(_currentPageData, _currentPageDataSize, pixelFormat, CacheTextureWidth, CacheTextureHeight, contentSize );
|
||||||
|
_currentPageOrigY = 0;
|
||||||
|
|
||||||
|
delete []_currentPageData;
|
||||||
|
_currentPageData = new unsigned char[_currentPageDataSize];
|
||||||
|
if(_currentPageData == nullptr)
|
||||||
|
return false;
|
||||||
|
memset(_currentPageData, 0, _currentPageDataSize);
|
||||||
|
_currentPage++;
|
||||||
|
auto tex = new Texture2D;
|
||||||
|
addTexture(*tex,_currentPage);
|
||||||
|
tex->release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fontTTf->renderCharAt(_currentPageData,_currentPageOrigX,_currentPageOrigY,bitmap,bitmapWidth,bitmapHeight);
|
||||||
|
|
||||||
|
tempDef.U = _currentPageOrigX;
|
||||||
|
tempDef.V = _currentPageOrigY;
|
||||||
|
tempDef.textureID = _currentPage;
|
||||||
|
_currentPageOrigX += tempDef.width + 1;
|
||||||
|
// take from pixels to points
|
||||||
|
tempDef.width = tempDef.width / scaleFactor;
|
||||||
|
tempDef.height = tempDef.height / scaleFactor;
|
||||||
|
tempDef.U = tempDef.U / scaleFactor;
|
||||||
|
tempDef.V = tempDef.V / scaleFactor;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(tempDef.xAdvance)
|
||||||
|
tempDef.validDefinition = true;
|
||||||
|
else
|
||||||
|
tempDef.validDefinition = false;
|
||||||
|
|
||||||
tempDef.letteCharUTF16 = utf16String[i];
|
tempDef.letteCharUTF16 = utf16String[i];
|
||||||
tempDef.width = 0;
|
tempDef.width = 0;
|
||||||
tempDef.height = 0;
|
tempDef.height = 0;
|
||||||
|
@ -143,72 +187,17 @@ bool FontAtlas::prepareLetterDefinitions(unsigned short *utf16String)
|
||||||
tempDef.offsetX = 0;
|
tempDef.offsetX = 0;
|
||||||
tempDef.offsetY = 0;
|
tempDef.offsetY = 0;
|
||||||
tempDef.textureID = 0;
|
tempDef.textureID = 0;
|
||||||
tempDef.xAdvance = 0;
|
_currentPageOrigX += 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
_fontLetterDefinitions[tempDef.letteCharUTF16] = tempDef;
|
||||||
tempDef.validDefinition = true;
|
|
||||||
tempDef.letteCharUTF16 = utf16String[i];
|
|
||||||
tempDef.width = tempRect.size.width + _letterPadding;
|
|
||||||
tempDef.height = tempRect.size.height + _letterPadding;
|
|
||||||
tempDef.offsetX = tempRect.origin.x + offsetAdjust;
|
|
||||||
tempDef.offsetY = _commonLineHeight + tempRect.origin.y - offsetAdjust;
|
|
||||||
}
|
|
||||||
fontDefs[utf16String[i]] = tempDef;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Size _pageContentSize = Size(PAGE_WIDTH,PAGE_HEIGHT);
|
if(existNewLetter)
|
||||||
float scaleFactor = CC_CONTENT_SCALE_FACTOR();
|
|
||||||
float glyphWidth;
|
|
||||||
Texture2D::PixelFormat pixelFormat = Texture2D::PixelFormat::A8;
|
|
||||||
|
|
||||||
|
|
||||||
for(auto it = fontDefs.begin(); it != fontDefs.end(); it++)
|
|
||||||
{
|
{
|
||||||
if(it->second.validDefinition)
|
_atlasTextures[_currentPage]->initWithData(_currentPageData, _currentPageDataSize, pixelFormat, CacheTextureWidth, CacheTextureHeight, contentSize );
|
||||||
{
|
|
||||||
glyphWidth = it->second.width;
|
|
||||||
|
|
||||||
if (_currentPageOrigX + glyphWidth > PAGE_WIDTH)
|
|
||||||
{
|
|
||||||
_currentPageOrigY += _currentPageLineHeight;
|
|
||||||
_currentPageOrigX = 0;
|
|
||||||
if(_currentPageOrigY + _currentPageLineHeight >= PAGE_HEIGHT)
|
|
||||||
{
|
|
||||||
_atlasTextures[_currentPage]->initWithData(_currentPageData, _currentPageDataSize, pixelFormat, PAGE_WIDTH, PAGE_HEIGHT, _pageContentSize );
|
|
||||||
_currentPageOrigY = 0;
|
|
||||||
|
|
||||||
delete []_currentPageData;
|
|
||||||
_currentPageData = new unsigned char[_currentPageDataSize];
|
|
||||||
if(_currentPageData == nullptr)
|
|
||||||
return false;
|
|
||||||
memset(_currentPageData, 0, _currentPageDataSize);
|
|
||||||
_currentPage++;
|
|
||||||
Texture2D* tex = new Texture2D;
|
|
||||||
addTexture(*tex,_currentPage);
|
|
||||||
tex->release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fontTTf->renderCharAt(it->second.letteCharUTF16,_currentPageOrigX,_currentPageOrigY,_currentPageData,PAGE_WIDTH);
|
|
||||||
|
|
||||||
it->second.U = _currentPageOrigX;
|
|
||||||
it->second.V = _currentPageOrigY;
|
|
||||||
it->second.textureID = _currentPage;
|
|
||||||
// take from pixels to points
|
|
||||||
it->second.width = it->second.width / scaleFactor;
|
|
||||||
it->second.height = it->second.height / scaleFactor;
|
|
||||||
it->second.U = it->second.U / scaleFactor;
|
|
||||||
it->second.V = it->second.V / scaleFactor;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
glyphWidth = 0;
|
|
||||||
|
|
||||||
_fontLetterDefinitions[it->second.letteCharUTF16] = it->second;
|
|
||||||
_currentPageOrigX += glyphWidth + 1;
|
|
||||||
}
|
}
|
||||||
if(fontDefs.size() > 0)
|
|
||||||
_atlasTextures[_currentPage]->initWithData(_currentPageData, _currentPageDataSize, pixelFormat, PAGE_WIDTH, PAGE_HEIGHT, _pageContentSize );
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,8 @@ struct FontLetterDefinition
|
||||||
class CC_DLL FontAtlas : public Ref
|
class CC_DLL FontAtlas : public Ref
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static const int CacheTextureWidth;
|
||||||
|
static const int CacheTextureHeight;
|
||||||
/**
|
/**
|
||||||
* @js ctor
|
* @js ctor
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -35,17 +35,32 @@ NS_CC_BEGIN
|
||||||
|
|
||||||
std::unordered_map<std::string, FontAtlas *> FontAtlasCache::_atlasMap;
|
std::unordered_map<std::string, FontAtlas *> FontAtlasCache::_atlasMap;
|
||||||
|
|
||||||
FontAtlas * FontAtlasCache::getFontAtlasTTF(const std::string& fontFileName, int size, GlyphCollection glyphs, const char *customGlyphs, bool useDistanceField)
|
FontAtlas * FontAtlasCache::getFontAtlasTTF(const TTFConfig & config)
|
||||||
{
|
{
|
||||||
std::string atlasName = generateFontName(fontFileName, size, glyphs, useDistanceField);
|
bool useDistanceField = config.distanceFieldEnabled;
|
||||||
|
if(config.outlineSize > 0)
|
||||||
|
{
|
||||||
|
useDistanceField = false;
|
||||||
|
}
|
||||||
|
int fontSize = config.fontSize;
|
||||||
|
if (useDistanceField)
|
||||||
|
{
|
||||||
|
fontSize = Label::DefultFontSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string atlasName = generateFontName(config.fontFilePath, fontSize, GlyphCollection::DYNAMIC, useDistanceField);
|
||||||
|
atlasName.append("_outline_");
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << config.outlineSize;
|
||||||
|
atlasName.append(ss.str());
|
||||||
|
|
||||||
FontAtlas *tempAtlas = _atlasMap[atlasName];
|
FontAtlas *tempAtlas = _atlasMap[atlasName];
|
||||||
|
|
||||||
if ( !tempAtlas )
|
if ( !tempAtlas )
|
||||||
{
|
{
|
||||||
FontFreeType *font = FontFreeType::create(fontFileName, size, glyphs, customGlyphs);
|
FontFreeType *font = FontFreeType::create(config.fontFilePath, fontSize, config.glyphs, config.customGlyphs,useDistanceField,config.outlineSize);
|
||||||
if (font)
|
if (font)
|
||||||
{
|
{
|
||||||
font->setDistanceFieldEnabled(useDistanceField);
|
|
||||||
tempAtlas = font->createFontAtlas();
|
tempAtlas = font->createFontAtlas();
|
||||||
if (tempAtlas)
|
if (tempAtlas)
|
||||||
_atlasMap[atlasName] = tempAtlas;
|
_atlasMap[atlasName] = tempAtlas;
|
||||||
|
|
|
@ -37,7 +37,7 @@ NS_CC_BEGIN
|
||||||
class CC_DLL FontAtlasCache
|
class CC_DLL FontAtlasCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static FontAtlas * getFontAtlasTTF(const std::string& fontFileName, int size, GlyphCollection glyphs, const char *customGlyphs = 0, bool useDistanceField = false);
|
static FontAtlas * getFontAtlasTTF(const TTFConfig & config);
|
||||||
static FontAtlas * getFontAtlasFNT(const std::string& fontFileName, const Point& imageOffset = Point::ZERO);
|
static FontAtlas * getFontAtlasFNT(const std::string& fontFileName, const Point& imageOffset = Point::ZERO);
|
||||||
|
|
||||||
static FontAtlas * getFontAtlasCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap);
|
static FontAtlas * getFontAtlasCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap);
|
||||||
|
|
|
@ -30,6 +30,7 @@ THE SOFTWARE.
|
||||||
#include "CCFontFreeType.h"
|
#include "CCFontFreeType.h"
|
||||||
#include "platform/CCFileUtils.h"
|
#include "platform/CCFileUtils.h"
|
||||||
#include "edtaa3func.h"
|
#include "edtaa3func.h"
|
||||||
|
#include FT_BBOX_H
|
||||||
|
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
|
|
||||||
|
@ -38,9 +39,9 @@ FT_Library FontFreeType::_FTlibrary;
|
||||||
bool FontFreeType::_FTInitialized = false;
|
bool FontFreeType::_FTInitialized = false;
|
||||||
const int FontFreeType::DistanceMapSpread = 3;
|
const int FontFreeType::DistanceMapSpread = 3;
|
||||||
|
|
||||||
FontFreeType * FontFreeType::create(const std::string &fontName, int fontSize, GlyphCollection glyphs, const char *customGlyphs)
|
FontFreeType * FontFreeType::create(const std::string &fontName, int fontSize, GlyphCollection glyphs, const char *customGlyphs,bool distanceFieldEnabled /* = false */,int outline /* = 0 */)
|
||||||
{
|
{
|
||||||
FontFreeType *tempFont = new FontFreeType();
|
FontFreeType *tempFont = new FontFreeType(distanceFieldEnabled,outline);
|
||||||
|
|
||||||
if (!tempFont)
|
if (!tempFont)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -84,10 +85,21 @@ FT_Library FontFreeType::getFTLibrary()
|
||||||
return _FTlibrary;
|
return _FTlibrary;
|
||||||
}
|
}
|
||||||
|
|
||||||
FontFreeType::FontFreeType()
|
FontFreeType::FontFreeType(bool distanceFieldEnabled /* = false */,int outline /* = 0 */)
|
||||||
: _fontRef(nullptr)
|
: _fontRef(nullptr)
|
||||||
,_distanceFieldEnabled(false)
|
,_distanceFieldEnabled(distanceFieldEnabled)
|
||||||
|
,_outlineSize(outline)
|
||||||
|
,_stroker(nullptr)
|
||||||
{
|
{
|
||||||
|
if (_outlineSize > 0)
|
||||||
|
{
|
||||||
|
FT_Stroker_New(FontFreeType::getFTLibrary(), &_stroker);
|
||||||
|
FT_Stroker_Set(_stroker,
|
||||||
|
(int)(_outlineSize * 64),
|
||||||
|
FT_STROKER_LINECAP_ROUND,
|
||||||
|
FT_STROKER_LINEJOIN_ROUND,
|
||||||
|
0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FontFreeType::createFontObject(const std::string &fontName, int fontSize)
|
bool FontFreeType::createFontObject(const std::string &fontName, int fontSize)
|
||||||
|
@ -125,6 +137,10 @@ bool FontFreeType::createFontObject(const std::string &fontName, int fontSize)
|
||||||
|
|
||||||
FontFreeType::~FontFreeType()
|
FontFreeType::~FontFreeType()
|
||||||
{
|
{
|
||||||
|
if (_stroker)
|
||||||
|
{
|
||||||
|
FT_Stroker_Done(_stroker);
|
||||||
|
}
|
||||||
if (_fontRef)
|
if (_fontRef)
|
||||||
{
|
{
|
||||||
FT_Done_Face(_fontRef);
|
FT_Done_Face(_fontRef);
|
||||||
|
@ -144,41 +160,6 @@ FontAtlas * FontFreeType::createFontAtlas()
|
||||||
return atlas;
|
return atlas;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FontFreeType::getBBOXFotChar(unsigned short theChar, Rect &outRect, int &xAdvance) const
|
|
||||||
{
|
|
||||||
if (!_fontRef)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// get the ID to the char we need
|
|
||||||
int glyph_index = FT_Get_Char_Index(_fontRef, theChar);
|
|
||||||
|
|
||||||
if (!glyph_index)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// load glyph infos
|
|
||||||
if (_distanceFieldEnabled)
|
|
||||||
{
|
|
||||||
if (FT_Load_Glyph(_fontRef, glyph_index, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (FT_Load_Glyph(_fontRef, glyph_index, FT_LOAD_DEFAULT))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// store result in the passed rectangle
|
|
||||||
outRect.origin.x = _fontRef->glyph->metrics.horiBearingX >> 6;
|
|
||||||
outRect.origin.y = - (_fontRef->glyph->metrics.horiBearingY >> 6);
|
|
||||||
outRect.size.width = (_fontRef->glyph->metrics.width >> 6);
|
|
||||||
outRect.size.height = (_fontRef->glyph->metrics.height >> 6);
|
|
||||||
|
|
||||||
xAdvance = (static_cast<int>(_fontRef->glyph->metrics.horiAdvance >> 6));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int * FontFreeType::getHorizontalKerningForTextUTF16(unsigned short *text, int &outNumLetters) const
|
int * FontFreeType::getHorizontalKerningForTextUTF16(unsigned short *text, int &outNumLetters) const
|
||||||
{
|
{
|
||||||
if (!text)
|
if (!text)
|
||||||
|
@ -239,27 +220,162 @@ int FontFreeType::getFontMaxHeight() const
|
||||||
return (static_cast<int>(_fontRef->size->metrics.height >> 6));
|
return (static_cast<int>(_fontRef->size->metrics.height >> 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char * FontFreeType::getGlyphBitmap(unsigned short theChar, int &outWidth, int &outHeight) const
|
unsigned char* FontFreeType::getGlyphBitmap(unsigned short theChar, int &outWidth, int &outHeight, Rect &outRect,int &xAdvance)
|
||||||
{
|
{
|
||||||
if (!_fontRef)
|
bool invalidChar = true;
|
||||||
return 0;
|
unsigned char * ret = nullptr;
|
||||||
|
|
||||||
if (_distanceFieldEnabled)
|
do
|
||||||
{
|
{
|
||||||
if (FT_Load_Char(_fontRef,theChar,FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT))
|
if (!_fontRef)
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
|
auto glyphIndex = FT_Get_Char_Index(_fontRef, theChar);
|
||||||
|
if(!glyphIndex)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (_distanceFieldEnabled)
|
||||||
|
{
|
||||||
|
if (FT_Load_Glyph(_fontRef,glyphIndex,FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (FT_Load_Glyph(_fontRef,glyphIndex,FT_LOAD_RENDER))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
outRect.origin.x = _fontRef->glyph->metrics.horiBearingX >> 6;
|
||||||
|
outRect.origin.y = - (_fontRef->glyph->metrics.horiBearingY >> 6);
|
||||||
|
outRect.size.width = (_fontRef->glyph->metrics.width >> 6);
|
||||||
|
outRect.size.height = (_fontRef->glyph->metrics.height >> 6);
|
||||||
|
|
||||||
|
xAdvance = (static_cast<int>(_fontRef->glyph->metrics.horiAdvance >> 6));
|
||||||
|
|
||||||
|
outWidth = _fontRef->glyph->bitmap.width;
|
||||||
|
outHeight = _fontRef->glyph->bitmap.rows;
|
||||||
|
ret = _fontRef->glyph->bitmap.buffer;
|
||||||
|
|
||||||
|
if (_outlineSize > 0)
|
||||||
|
{
|
||||||
|
auto copyBitmap = new unsigned char[outWidth * outHeight];
|
||||||
|
memcpy(copyBitmap,ret,outWidth * outHeight * sizeof(unsigned char));
|
||||||
|
|
||||||
|
int bitmapWidth;
|
||||||
|
int bitmapHeight;
|
||||||
|
FT_BBox bbox;
|
||||||
|
auto outlineBitmap = getGlyphBitmapWithOutline(theChar,bbox);
|
||||||
|
if(outlineBitmap == nullptr)
|
||||||
|
{
|
||||||
|
ret = nullptr;
|
||||||
|
delete [] copyBitmap;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmapWidth = (bbox.xMax - bbox.xMin)>>6;
|
||||||
|
bitmapHeight = (bbox.yMax - bbox.yMin)>>6;
|
||||||
|
|
||||||
|
int index;
|
||||||
|
auto blendImage = new unsigned char[bitmapWidth * bitmapHeight * 2];
|
||||||
|
memset(blendImage, 0, bitmapWidth * bitmapHeight * 2);
|
||||||
|
for (int x = 0; x < bitmapWidth; ++x)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < bitmapHeight; ++y)
|
||||||
|
{
|
||||||
|
index = x + ( y * bitmapWidth );
|
||||||
|
blendImage[2 * index] = outlineBitmap[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxX = outWidth + _outlineSize;
|
||||||
|
int maxY = outHeight + _outlineSize;
|
||||||
|
for (int x = _outlineSize; x < maxX; ++x)
|
||||||
|
{
|
||||||
|
for (int y = _outlineSize; y < maxY; ++y)
|
||||||
|
{
|
||||||
|
index = x + ( y * bitmapWidth );
|
||||||
|
|
||||||
|
blendImage[2 * index + 1] = copyBitmap[outWidth * (y - _outlineSize) + x - _outlineSize];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outRect.origin.x = bbox.xMin >> 6;
|
||||||
|
outRect.origin.y = - (bbox.yMax >> 6);
|
||||||
|
|
||||||
|
xAdvance += bitmapWidth - outRect.size.width;
|
||||||
|
|
||||||
|
outRect.size.width = bitmapWidth;
|
||||||
|
outRect.size.height = bitmapHeight;
|
||||||
|
outWidth = bitmapWidth;
|
||||||
|
outHeight = bitmapHeight;
|
||||||
|
|
||||||
|
delete [] outlineBitmap;
|
||||||
|
delete [] copyBitmap;
|
||||||
|
ret = blendImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidChar = false;
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
if (invalidChar)
|
||||||
|
{
|
||||||
|
outRect.size.width = 0;
|
||||||
|
outRect.size.height = 0;
|
||||||
|
xAdvance = 0;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (FT_Load_Char(_fontRef,theChar,FT_LOAD_RENDER))
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
outWidth = _fontRef->glyph->bitmap.width;
|
|
||||||
outHeight = _fontRef->glyph->bitmap.rows;
|
unsigned char * FontFreeType::getGlyphBitmapWithOutline(unsigned short theChar, FT_BBox &bbox)
|
||||||
|
{
|
||||||
// return the pointer to the bitmap
|
unsigned char* ret = nullptr;
|
||||||
return _fontRef->glyph->bitmap.buffer;
|
|
||||||
|
FT_UInt gindex = FT_Get_Char_Index(_fontRef, theChar);
|
||||||
|
if (FT_Load_Glyph(_fontRef, gindex, FT_LOAD_NO_BITMAP) == 0)
|
||||||
|
{
|
||||||
|
if (_fontRef->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
|
||||||
|
{
|
||||||
|
FT_Glyph glyph;
|
||||||
|
if (FT_Get_Glyph(_fontRef->glyph, &glyph) == 0)
|
||||||
|
{
|
||||||
|
FT_Glyph_StrokeBorder(&glyph, _stroker, 0, 1);
|
||||||
|
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
|
||||||
|
{
|
||||||
|
FT_Outline *outline = &reinterpret_cast<FT_OutlineGlyph>(glyph)->outline;
|
||||||
|
FT_Glyph_Get_CBox(glyph,FT_GLYPH_BBOX_GRIDFIT,&bbox);
|
||||||
|
int width = (bbox.xMax - bbox.xMin)>>6;
|
||||||
|
int rows = (bbox.yMax - bbox.yMin)>>6;
|
||||||
|
|
||||||
|
FT_Bitmap bmp;
|
||||||
|
bmp.buffer = new unsigned char[width * rows];
|
||||||
|
memset(bmp.buffer, 0, width * rows);
|
||||||
|
bmp.width = width;
|
||||||
|
bmp.rows = rows;
|
||||||
|
bmp.pitch = width;
|
||||||
|
bmp.pixel_mode = FT_PIXEL_MODE_GRAY;
|
||||||
|
bmp.num_grays = 256;
|
||||||
|
|
||||||
|
FT_Raster_Params params;
|
||||||
|
memset(¶ms, 0, sizeof (params));
|
||||||
|
params.source = outline;
|
||||||
|
params.target = &bmp;
|
||||||
|
params.flags = FT_RASTER_FLAG_AA;
|
||||||
|
FT_Outline_Translate(outline,-bbox.xMin,-bbox.yMin);
|
||||||
|
FT_Outline_Render(_FTlibrary, outline, ¶ms);
|
||||||
|
|
||||||
|
ret = bmp.buffer;
|
||||||
|
}
|
||||||
|
FT_Done_Glyph(glyph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char * makeDistanceMap( unsigned char *img, unsigned int width, unsigned int height)
|
unsigned char * makeDistanceMap( unsigned char *img, unsigned int width, unsigned int height)
|
||||||
|
@ -343,47 +459,33 @@ unsigned char * makeDistanceMap( unsigned char *img, unsigned int width, unsigne
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontFreeType::setDistanceFieldEnabled(bool distanceFieldEnabled)
|
void FontFreeType::renderCharAt(unsigned char *dest,int posX, int posY, unsigned char* bitmap,int bitmapWidth,int bitmapHeight)
|
||||||
{
|
{
|
||||||
_distanceFieldEnabled = distanceFieldEnabled;
|
int iX = posX;
|
||||||
}
|
int iY = posY;
|
||||||
|
|
||||||
bool FontFreeType::renderCharAt(unsigned short int charToRender, int posX, int posY, unsigned char *destMemory, int destSize)
|
|
||||||
{
|
|
||||||
unsigned char *sourceBitmap = 0;
|
|
||||||
int sourceWidth = 0;
|
|
||||||
int sourceHeight = 0;
|
|
||||||
|
|
||||||
sourceBitmap = getGlyphBitmap(charToRender, sourceWidth, sourceHeight);
|
|
||||||
|
|
||||||
if (!sourceBitmap)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (_distanceFieldEnabled)
|
if (_distanceFieldEnabled)
|
||||||
{
|
{
|
||||||
unsigned char * out = makeDistanceMap(sourceBitmap,sourceWidth,sourceHeight);
|
auto distanceMap = makeDistanceMap(bitmap,bitmapWidth,bitmapHeight);
|
||||||
|
|
||||||
int iX = posX;
|
bitmapWidth += 2 * DistanceMapSpread;
|
||||||
int iY = posY;
|
bitmapHeight += 2 * DistanceMapSpread;
|
||||||
|
|
||||||
sourceWidth += 2 * DistanceMapSpread;
|
for (int y = 0; y < bitmapHeight; ++y)
|
||||||
sourceHeight += 2 * DistanceMapSpread;
|
|
||||||
|
|
||||||
for (int y = 0; y < sourceHeight; ++y)
|
|
||||||
{
|
{
|
||||||
int bitmap_y = y * sourceWidth;
|
int bitmap_y = y * bitmapWidth;
|
||||||
|
|
||||||
for (int x = 0; x < sourceWidth; ++x)
|
for (int x = 0; x < bitmapWidth; ++x)
|
||||||
{
|
{
|
||||||
/* Dual channel 16-bit output (more complicated, but good precision and range) */
|
/* Dual channel 16-bit output (more complicated, but good precision and range) */
|
||||||
/*int index = (iX + ( iY * destSize )) * 3;
|
/*int index = (iX + ( iY * destSize )) * 3;
|
||||||
int index2 = (bitmap_y + x)*3;
|
int index2 = (bitmap_y + x)*3;
|
||||||
destMemory[index] = out[index2];
|
dest[index] = out[index2];
|
||||||
destMemory[index + 1] = out[index2 + 1];
|
dest[index + 1] = out[index2 + 1];
|
||||||
destMemory[index + 2] = out[index2 + 2];*/
|
dest[index + 2] = out[index2 + 2];*/
|
||||||
|
|
||||||
//Single channel 8-bit output
|
//Single channel 8-bit output
|
||||||
destMemory[iX + ( iY * destSize )] = out[bitmap_y + x];
|
dest[iX + ( iY * FontAtlas::CacheTextureWidth )] = distanceMap[bitmap_y + x];
|
||||||
|
|
||||||
iX += 1;
|
iX += 1;
|
||||||
}
|
}
|
||||||
|
@ -391,33 +493,50 @@ bool FontFreeType::renderCharAt(unsigned short int charToRender, int posX, int p
|
||||||
iX = posX;
|
iX = posX;
|
||||||
iY += 1;
|
iY += 1;
|
||||||
}
|
}
|
||||||
free(out);
|
free(distanceMap);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
else if(_outlineSize > 0)
|
||||||
int iX = posX;
|
|
||||||
int iY = posY;
|
|
||||||
|
|
||||||
for (int y = 0; y < sourceHeight; ++y)
|
|
||||||
{
|
{
|
||||||
int bitmap_y = y * sourceWidth;
|
unsigned char tempChar;
|
||||||
|
for (int y = 0; y < bitmapHeight; ++y)
|
||||||
for (int x = 0; x < sourceWidth; ++x)
|
|
||||||
{
|
{
|
||||||
unsigned char cTemp = sourceBitmap[bitmap_y + x];
|
int bitmap_y = y * bitmapWidth;
|
||||||
|
|
||||||
// the final pixel
|
for (int x = 0; x < bitmapWidth; ++x)
|
||||||
destMemory[(iX + ( iY * destSize ) )] = cTemp;
|
{
|
||||||
|
tempChar = bitmap[(bitmap_y + x) * 2];
|
||||||
|
dest[(iX + ( iY * FontAtlas::CacheTextureWidth ) ) * 2] = tempChar;
|
||||||
|
tempChar = bitmap[(bitmap_y + x) * 2 + 1];
|
||||||
|
dest[(iX + ( iY * FontAtlas::CacheTextureWidth ) ) * 2 + 1] = tempChar;
|
||||||
|
|
||||||
iX += 1;
|
iX += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
iX = posX;
|
||||||
|
iY += 1;
|
||||||
}
|
}
|
||||||
|
delete [] bitmap;
|
||||||
iX = posX;
|
|
||||||
iY += 1;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int y = 0; y < bitmapHeight; ++y)
|
||||||
|
{
|
||||||
|
int bitmap_y = y * bitmapWidth;
|
||||||
|
|
||||||
//everything good
|
for (int x = 0; x < bitmapWidth; ++x)
|
||||||
return true;
|
{
|
||||||
|
unsigned char cTemp = bitmap[bitmap_y + x];
|
||||||
|
|
||||||
|
// the final pixel
|
||||||
|
dest[(iX + ( iY * FontAtlas::CacheTextureWidth ) )] = cTemp;
|
||||||
|
|
||||||
|
iX += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
iX = posX;
|
||||||
|
iY += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_CC_END
|
NS_CC_END
|
|
@ -33,6 +33,7 @@
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
|
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_STROKER_H
|
||||||
|
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
|
|
||||||
|
@ -41,25 +42,24 @@ class CC_DLL FontFreeType : public Font
|
||||||
public:
|
public:
|
||||||
static const int DistanceMapSpread;
|
static const int DistanceMapSpread;
|
||||||
|
|
||||||
static FontFreeType * create(const std::string &fontName, int fontSize, GlyphCollection glyphs, const char *customGlyphs);
|
static FontFreeType * create(const std::string &fontName, int fontSize, GlyphCollection glyphs, const char *customGlyphs,bool distanceFieldEnabled = false,int outline = 0);
|
||||||
|
|
||||||
static void shutdownFreeType();
|
static void shutdownFreeType();
|
||||||
|
|
||||||
void setDistanceFieldEnabled(bool distanceFieldEnabled);
|
|
||||||
bool isDistanceFieldEnabled() const { return _distanceFieldEnabled;}
|
bool isDistanceFieldEnabled() const { return _distanceFieldEnabled;}
|
||||||
bool renderCharAt(unsigned short int charToRender, int posX, int posY, unsigned char *destMemory, int destSize);
|
int getOutlineSize() const { return _outlineSize; }
|
||||||
|
void renderCharAt(unsigned char *dest,int posX, int posY, unsigned char* bitmap,int bitmapWidth,int bitmapHeight);
|
||||||
|
|
||||||
virtual FontAtlas * createFontAtlas() override;
|
virtual FontAtlas * createFontAtlas() override;
|
||||||
virtual int * getHorizontalKerningForTextUTF16(unsigned short *text, int &outNumLetters) const override;
|
virtual int * getHorizontalKerningForTextUTF16(unsigned short *text, int &outNumLetters) const override;
|
||||||
|
|
||||||
unsigned char * getGlyphBitmap(unsigned short theChar, int &outWidth, int &outHeight) const override;
|
unsigned char * getGlyphBitmap(unsigned short theChar, int &outWidth, int &outHeight, Rect &outRect,int &xAdvance);
|
||||||
virtual int getFontMaxHeight() const override;
|
|
||||||
|
|
||||||
bool getBBOXFotChar(unsigned short theChar, Rect &outRect,int &xAdvance) const;
|
virtual int getFontMaxHeight() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
FontFreeType();
|
FontFreeType(bool distanceFieldEnabled = false,int outline = 0);
|
||||||
virtual ~FontFreeType();
|
virtual ~FontFreeType();
|
||||||
bool createFontObject(const std::string &fontName, int fontSize);
|
bool createFontObject(const std::string &fontName, int fontSize);
|
||||||
|
|
||||||
|
@ -69,13 +69,16 @@ private:
|
||||||
FT_Library getFTLibrary();
|
FT_Library getFTLibrary();
|
||||||
|
|
||||||
int getHorizontalKerningForChars(unsigned short firstChar, unsigned short secondChar) const;
|
int getHorizontalKerningForChars(unsigned short firstChar, unsigned short secondChar) const;
|
||||||
|
unsigned char * getGlyphBitmapWithOutline(unsigned short theChar, FT_BBox &bbox);
|
||||||
|
|
||||||
static FT_Library _FTlibrary;
|
static FT_Library _FTlibrary;
|
||||||
static bool _FTInitialized;
|
static bool _FTInitialized;
|
||||||
FT_Face _fontRef;
|
FT_Face _fontRef;
|
||||||
|
FT_Stroker _stroker;
|
||||||
std::string _fontName;
|
std::string _fontName;
|
||||||
Data _ttfData;
|
Data _ttfData;
|
||||||
bool _distanceFieldEnabled;
|
bool _distanceFieldEnabled;
|
||||||
|
int _outlineSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_CC_END
|
NS_CC_END
|
||||||
|
|
|
@ -34,10 +34,10 @@
|
||||||
#include "renderer/CCRenderer.h"
|
#include "renderer/CCRenderer.h"
|
||||||
#include "CCFont.h"
|
#include "CCFont.h"
|
||||||
|
|
||||||
#define DISTANCEFIELD_ATLAS_FONTSIZE 50
|
|
||||||
|
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
|
|
||||||
|
const int Label::DefultFontSize = 50;
|
||||||
|
|
||||||
Label* Label::create()
|
Label* Label::create()
|
||||||
{
|
{
|
||||||
Label *ret = new Label();
|
Label *ret = new Label();
|
||||||
|
@ -56,11 +56,9 @@ Label* Label::createWithTTF(const TTFConfig& ttfConfig, const std::string& text,
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (ret->setTTFConfig(ttfConfig))
|
if (ret->setTTFConfig(ttfConfig))
|
||||||
{
|
{
|
||||||
if(ttfConfig.distanceFieldEnabled)
|
|
||||||
ret->setFontScale(1.0f * ttfConfig.fontSize / DISTANCEFIELD_ATLAS_FONTSIZE);
|
|
||||||
ret->setMaxLineWidth(lineSize);
|
ret->setMaxLineWidth(lineSize);
|
||||||
ret->setString(text);
|
ret->setString(text);
|
||||||
ret->autorelease();
|
ret->autorelease();
|
||||||
|
@ -203,6 +201,7 @@ Label::Label(FontAtlas *atlas, TextHAlignment alignment, bool useDistanceField,b
|
||||||
, _fontScale(1.0f)
|
, _fontScale(1.0f)
|
||||||
, _uniformEffectColor(0)
|
, _uniformEffectColor(0)
|
||||||
,_currNumLines(-1)
|
,_currNumLines(-1)
|
||||||
|
,_fontConfig(TTFConfig(""))
|
||||||
{
|
{
|
||||||
_cascadeColorEnabled = true;
|
_cascadeColorEnabled = true;
|
||||||
_batchNodes.push_back(this);
|
_batchNodes.push_back(this);
|
||||||
|
@ -213,7 +212,7 @@ Label::~Label()
|
||||||
delete [] _currentUTF16String;
|
delete [] _currentUTF16String;
|
||||||
delete [] _originalUTF16String;
|
delete [] _originalUTF16String;
|
||||||
delete [] _horizontalKernings;
|
delete [] _horizontalKernings;
|
||||||
|
|
||||||
if (_fontAtlas)
|
if (_fontAtlas)
|
||||||
FontAtlasCache::releaseFontAtlas(_fontAtlas);
|
FontAtlasCache::releaseFontAtlas(_fontAtlas);
|
||||||
|
|
||||||
|
@ -225,25 +224,49 @@ bool Label::init()
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
if(_fontAtlas)
|
if(_fontAtlas)
|
||||||
{
|
{
|
||||||
|
ret = SpriteBatchNode::initWithTexture(&_fontAtlas->getTexture(0), 30);
|
||||||
if (_reusedLetter == nullptr)
|
if (_reusedLetter == nullptr)
|
||||||
{
|
{
|
||||||
_reusedLetter = Sprite::createWithTexture(&_fontAtlas->getTexture(0));
|
_reusedLetter = Sprite::createWithTexture(&_fontAtlas->getTexture(0));
|
||||||
_reusedLetter->setOpacityModifyRGB(_isOpacityModifyRGB);
|
_reusedLetter->setOpacityModifyRGB(_isOpacityModifyRGB);
|
||||||
_reusedLetter->retain();
|
_reusedLetter->retain();
|
||||||
_reusedLetter->setAnchorPoint(Point::ANCHOR_TOP_LEFT);
|
_reusedLetter->setAnchorPoint(Point::ANCHOR_TOP_LEFT);
|
||||||
|
_reusedLetter->setBatchNode(this);
|
||||||
}
|
}
|
||||||
ret = SpriteBatchNode::initWithTexture(&_fontAtlas->getTexture(0), 30);
|
|
||||||
}
|
}
|
||||||
if (_useDistanceField)
|
_currLabelEffect = LabelEffect::NORMAL;
|
||||||
setLabelEffect(LabelEffect::NORMAL,Color3B::BLACK);
|
initProgram();
|
||||||
else if(_useA8Shader)
|
|
||||||
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_A8_COLOR));
|
|
||||||
else
|
|
||||||
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR));
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Label::initProgram()
|
||||||
|
{
|
||||||
|
switch (_currLabelEffect)
|
||||||
|
{
|
||||||
|
case cocos2d::LabelEffect::NORMAL:
|
||||||
|
case cocos2d::LabelEffect::SHADOW:
|
||||||
|
if (_useDistanceField)
|
||||||
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_NORMAL));
|
||||||
|
else if (_useA8Shader)
|
||||||
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_A8_COLOR));
|
||||||
|
else
|
||||||
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR));
|
||||||
|
|
||||||
|
break;
|
||||||
|
case cocos2d::LabelEffect::OUTLINE:
|
||||||
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_OUTLINE));
|
||||||
|
break;
|
||||||
|
case cocos2d::LabelEffect::GLOW:
|
||||||
|
if (_useDistanceField)
|
||||||
|
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_GLOW));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_uniformEffectColor = glGetUniformLocation(_shaderProgram->getProgram(), "v_effectColor");
|
||||||
|
}
|
||||||
|
|
||||||
bool Label::initWithFontAtlas(FontAtlas* atlas,bool distanceFieldEnabled /* = false */, bool useA8Shader /* = false */)
|
bool Label::initWithFontAtlas(FontAtlas* atlas,bool distanceFieldEnabled /* = false */, bool useA8Shader /* = false */)
|
||||||
{
|
{
|
||||||
FontAtlas *oldAtlas = _fontAtlas;
|
FontAtlas *oldAtlas = _fontAtlas;
|
||||||
|
@ -287,16 +310,32 @@ bool Label::initWithFontAtlas(FontAtlas* atlas,bool distanceFieldEnabled /* = fa
|
||||||
|
|
||||||
bool Label::setTTFConfig(const TTFConfig& ttfConfig)
|
bool Label::setTTFConfig(const TTFConfig& ttfConfig)
|
||||||
{
|
{
|
||||||
FontAtlas *newAtlas = nullptr;
|
FontAtlas *newAtlas = FontAtlasCache::getFontAtlasTTF(ttfConfig);
|
||||||
if(ttfConfig.distanceFieldEnabled)
|
|
||||||
newAtlas = FontAtlasCache::getFontAtlasTTF(ttfConfig.fontFilePath, DISTANCEFIELD_ATLAS_FONTSIZE, ttfConfig.glyphs, ttfConfig.customGlyphs,true);
|
|
||||||
else
|
|
||||||
newAtlas = FontAtlasCache::getFontAtlasTTF(ttfConfig.fontFilePath, ttfConfig.fontSize, ttfConfig.glyphs, ttfConfig.customGlyphs,false);
|
|
||||||
|
|
||||||
if (!newAtlas)
|
if (!newAtlas)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return initWithFontAtlas(newAtlas,ttfConfig.distanceFieldEnabled,true);
|
if (initWithFontAtlas(newAtlas,ttfConfig.distanceFieldEnabled,true))
|
||||||
|
{
|
||||||
|
_fontConfig = ttfConfig;
|
||||||
|
if (ttfConfig.outlineSize > 0)
|
||||||
|
{
|
||||||
|
_fontConfig.distanceFieldEnabled = false;
|
||||||
|
_useDistanceField = false;
|
||||||
|
_useA8Shader = false;
|
||||||
|
_currLabelEffect = LabelEffect::OUTLINE;
|
||||||
|
initProgram();
|
||||||
|
}
|
||||||
|
else if(ttfConfig.distanceFieldEnabled)
|
||||||
|
{
|
||||||
|
this->setFontScale(1.0f * ttfConfig.fontSize / DefultFontSize);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Label::setBMFontFilePath(const std::string& bmfontFilePath, const Point& imageOffset /* = Point::ZERO */)
|
bool Label::setBMFontFilePath(const std::string& bmfontFilePath, const Point& imageOffset /* = Point::ZERO */)
|
||||||
|
@ -313,14 +352,14 @@ void Label::setString(const std::string& text)
|
||||||
{
|
{
|
||||||
if (!_fontAtlas || _commonLineHeight <= 0)
|
if (!_fontAtlas || _commonLineHeight <= 0)
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
unsigned short* utf16String = cc_utf8_to_utf16(text.c_str());
|
unsigned short* utf16String = cc_utf8_to_utf16(text.c_str());
|
||||||
if(!utf16String)
|
if(!utf16String)
|
||||||
return ;
|
return ;
|
||||||
_originalUTF8String = text;
|
_originalUTF8String = text;
|
||||||
setCurrentString(utf16String);
|
setCurrentString(utf16String);
|
||||||
setOriginalString(utf16String);
|
setOriginalString(utf16String);
|
||||||
|
|
||||||
// align text
|
// align text
|
||||||
alignText();
|
alignText();
|
||||||
}
|
}
|
||||||
|
@ -332,7 +371,7 @@ void Label::setAlignment(TextHAlignment alignment)
|
||||||
{
|
{
|
||||||
// store
|
// store
|
||||||
_alignment = alignment;
|
_alignment = alignment;
|
||||||
|
|
||||||
if (_currentUTF16String)
|
if (_currentUTF16String)
|
||||||
{
|
{
|
||||||
// reset the string
|
// reset the string
|
||||||
|
@ -350,7 +389,7 @@ void Label::setMaxLineWidth(float width)
|
||||||
{
|
{
|
||||||
// store
|
// store
|
||||||
_maxLineWidth = width;
|
_maxLineWidth = width;
|
||||||
|
|
||||||
if (_currentUTF16String)
|
if (_currentUTF16String)
|
||||||
{
|
{
|
||||||
// reset the string
|
// reset the string
|
||||||
|
@ -368,7 +407,7 @@ void Label::setLineBreakWithoutSpace(bool breakWithoutSpace)
|
||||||
{
|
{
|
||||||
// store
|
// store
|
||||||
_lineBreakWithoutSpaces = breakWithoutSpace;
|
_lineBreakWithoutSpaces = breakWithoutSpace;
|
||||||
|
|
||||||
// need to align text again
|
// need to align text again
|
||||||
if(_currentUTF16String)
|
if(_currentUTF16String)
|
||||||
{
|
{
|
||||||
|
@ -456,10 +495,10 @@ void Label::alignText()
|
||||||
LabelTextFormatter::createStringSprites(this);
|
LabelTextFormatter::createStringSprites(this);
|
||||||
if(_maxLineWidth > 0 && _contentSize.width > _maxLineWidth && LabelTextFormatter::multilineText(this) )
|
if(_maxLineWidth > 0 && _contentSize.width > _maxLineWidth && LabelTextFormatter::multilineText(this) )
|
||||||
LabelTextFormatter::createStringSprites(this);
|
LabelTextFormatter::createStringSprites(this);
|
||||||
|
|
||||||
if(_currNumLines > 1 && _alignment != TextHAlignment::LEFT)
|
if(_currNumLines > 1 && _alignment != TextHAlignment::LEFT)
|
||||||
LabelTextFormatter::alignText(this);
|
LabelTextFormatter::alignText(this);
|
||||||
|
|
||||||
int strLen = cc_wcslen(_currentUTF16String);
|
int strLen = cc_wcslen(_currentUTF16String);
|
||||||
Rect uvRect;
|
Rect uvRect;
|
||||||
Sprite* letterSprite;
|
Sprite* letterSprite;
|
||||||
|
@ -484,7 +523,7 @@ void Label::alignText()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
for (int ctr = 0; ctr < strLen; ++ctr)
|
for (int ctr = 0; ctr < strLen; ++ctr)
|
||||||
{
|
{
|
||||||
|
@ -507,10 +546,10 @@ bool Label::computeHorizontalKernings(unsigned short int *stringToRender)
|
||||||
delete [] _horizontalKernings;
|
delete [] _horizontalKernings;
|
||||||
_horizontalKernings = 0;
|
_horizontalKernings = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int letterCount = 0;
|
int letterCount = 0;
|
||||||
_horizontalKernings = _fontAtlas->getFont()->getHorizontalKerningForTextUTF16(stringToRender, letterCount);
|
_horizontalKernings = _fontAtlas->getFont()->getHorizontalKerningForTextUTF16(stringToRender, letterCount);
|
||||||
|
|
||||||
if(!_horizontalKernings)
|
if(!_horizontalKernings)
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
|
@ -523,13 +562,13 @@ bool Label::setOriginalString(unsigned short *stringToSet)
|
||||||
{
|
{
|
||||||
delete [] _originalUTF16String;
|
delete [] _originalUTF16String;
|
||||||
}
|
}
|
||||||
|
|
||||||
int newStringLenght = cc_wcslen(stringToSet);
|
int newStringLenght = cc_wcslen(stringToSet);
|
||||||
_originalUTF16String = new unsigned short int [newStringLenght + 1];
|
_originalUTF16String = new unsigned short int [newStringLenght + 1];
|
||||||
memset(_originalUTF16String, 0, (newStringLenght + 1) * 2);
|
memset(_originalUTF16String, 0, (newStringLenght + 1) * 2);
|
||||||
memcpy(_originalUTF16String, stringToSet, (newStringLenght * 2));
|
memcpy(_originalUTF16String, stringToSet, (newStringLenght * 2));
|
||||||
_originalUTF16String[newStringLenght] = 0;
|
_originalUTF16String[newStringLenght] = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,7 +579,7 @@ bool Label::setCurrentString(unsigned short *stringToSet)
|
||||||
{
|
{
|
||||||
delete [] _currentUTF16String;
|
delete [] _currentUTF16String;
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentUTF16String = stringToSet;
|
_currentUTF16String = stringToSet;
|
||||||
computeStringNumLines();
|
computeStringNumLines();
|
||||||
// compute the advances
|
// compute the advances
|
||||||
|
@ -551,19 +590,19 @@ void Label::resetCurrentString()
|
||||||
{
|
{
|
||||||
if ((!_currentUTF16String) && (!_originalUTF16String))
|
if ((!_currentUTF16String) && (!_originalUTF16String))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// set the new string
|
// set the new string
|
||||||
if (_currentUTF16String)
|
if (_currentUTF16String)
|
||||||
{
|
{
|
||||||
delete [] _currentUTF16String;
|
delete [] _currentUTF16String;
|
||||||
_currentUTF16String = 0;
|
_currentUTF16String = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int stringLenght = cc_wcslen(_originalUTF16String);
|
int stringLenght = cc_wcslen(_originalUTF16String);
|
||||||
_currentUTF16String = new unsigned short int [stringLenght + 1];
|
_currentUTF16String = new unsigned short int [stringLenght + 1];
|
||||||
memcpy(_currentUTF16String, _originalUTF16String, stringLenght * 2);
|
memcpy(_currentUTF16String, _originalUTF16String, stringLenght * 2);
|
||||||
_currentUTF16String[stringLenght] = 0;
|
_currentUTF16String[stringLenght] = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Label::updateSpriteWithLetterDefinition(const FontLetterDefinition &theDefinition, Texture2D *theTexture)
|
void Label::updateSpriteWithLetterDefinition(const FontLetterDefinition &theDefinition, Texture2D *theTexture)
|
||||||
|
@ -603,7 +642,7 @@ bool Label::recordPlaceholderInfo(int spriteIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
_lettersInfo[spriteIndex].def.validDefinition = false;
|
_lettersInfo[spriteIndex].def.validDefinition = false;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,31 +653,68 @@ void Label::addChild(Node * child, int zOrder/* =0 */, int tag/* =0 */)
|
||||||
|
|
||||||
void Label::setLabelEffect(LabelEffect effect,const Color3B& effectColor)
|
void Label::setLabelEffect(LabelEffect effect,const Color3B& effectColor)
|
||||||
{
|
{
|
||||||
if(_useDistanceField == false)
|
switch (effect)
|
||||||
return;
|
|
||||||
|
|
||||||
_currLabelEffect = effect;
|
|
||||||
_effectColor = effectColor;
|
|
||||||
|
|
||||||
switch (_currLabelEffect)
|
|
||||||
{
|
{
|
||||||
case cocos2d::LabelEffect::NORMAL:
|
case cocos2d::LabelEffect::NORMAL:
|
||||||
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_NORMAL));
|
disableEffect();
|
||||||
break;
|
break;
|
||||||
case cocos2d::LabelEffect::OUTLINE:
|
case cocos2d::LabelEffect::OUTLINE:
|
||||||
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_OUTLINE));
|
enableOutline(Color4B(effectColor));
|
||||||
break;
|
break;
|
||||||
case cocos2d::LabelEffect::SHADOW:
|
case cocos2d::LabelEffect::SHADOW:
|
||||||
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_SHADOW));
|
enableShadow(effectColor);
|
||||||
break;
|
break;
|
||||||
case cocos2d::LabelEffect::GLOW:
|
case cocos2d::LabelEffect::GLOW:
|
||||||
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_GLOW));
|
enableGlow(effectColor);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_uniformEffectColor = glGetUniformLocation(_shaderProgram->getProgram(), "v_effectColor");
|
void Label::enableGlow(const Color3B& glowColor)
|
||||||
|
{
|
||||||
|
if(_useDistanceField == false)
|
||||||
|
return;
|
||||||
|
_currLabelEffect = LabelEffect::GLOW;
|
||||||
|
_effectColor = glowColor;
|
||||||
|
initProgram();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::enableOutline(const Color4B& outlineColor,int outlineSize /* = 1 */)
|
||||||
|
{
|
||||||
|
_outlineColor = outlineColor;
|
||||||
|
if (outlineSize > 0)
|
||||||
|
{
|
||||||
|
_currLabelEffect = LabelEffect::OUTLINE;
|
||||||
|
if (_fontConfig.outlineSize != outlineSize)
|
||||||
|
{
|
||||||
|
_fontConfig.outlineSize = outlineSize;
|
||||||
|
setTTFConfig(_fontConfig);
|
||||||
|
}
|
||||||
|
initProgram();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::enableShadow(const Color3B& shadowColor /* = Color3B::BLACK */,const Size &offset /* = Size(2 ,-2)*/, float opacity /* = 0.75f */, int blurRadius /* = 0 */)
|
||||||
|
{
|
||||||
|
_shadowOpacity = opacity;
|
||||||
|
_effectColor = shadowColor;
|
||||||
|
_shadowOffset = offset;
|
||||||
|
//todo:support blur for shadow
|
||||||
|
_shadowBlurRadius = 0;
|
||||||
|
_currLabelEffect = LabelEffect::SHADOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::disableEffect()
|
||||||
|
{
|
||||||
|
if (_currLabelEffect == LabelEffect::OUTLINE)
|
||||||
|
{
|
||||||
|
_fontConfig.outlineSize = 0;
|
||||||
|
setTTFConfig(_fontConfig);
|
||||||
|
}
|
||||||
|
_currLabelEffect = LabelEffect::NORMAL;
|
||||||
|
initProgram();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Label::setFontScale(float fontScale)
|
void Label::setFontScale(float fontScale)
|
||||||
|
@ -657,28 +733,79 @@ void Label::onDraw()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CC_NODE_DRAW_SETUP();
|
_shaderProgram->use();
|
||||||
|
GL::blendFunc( _blendFunc.src, _blendFunc.dst );
|
||||||
|
bool trans = false;
|
||||||
|
|
||||||
if (_useDistanceField && _currLabelEffect != LabelEffect::NORMAL)
|
if (_currLabelEffect == LabelEffect::OUTLINE)
|
||||||
|
{
|
||||||
|
_shaderProgram->setUniformLocationWith4f(_uniformEffectColor, _outlineColor.r/255.0f,_outlineColor.g/255.0f,_outlineColor.b/255.0f,_outlineColor.a/255.0f);
|
||||||
|
}
|
||||||
|
else if (_currLabelEffect == LabelEffect::GLOW)
|
||||||
{
|
{
|
||||||
_shaderProgram->setUniformLocationWith3f(_uniformEffectColor, _effectColor.r/255.0f,_effectColor.g/255.0f,_effectColor.b/255.0f);
|
_shaderProgram->setUniformLocationWith3f(_uniformEffectColor, _effectColor.r/255.0f,_effectColor.g/255.0f,_effectColor.b/255.0f);
|
||||||
}
|
}
|
||||||
|
else if(_currLabelEffect == LabelEffect::SHADOW && _shadowBlurRadius <= 0)
|
||||||
for(const auto &child: _children)
|
|
||||||
{
|
{
|
||||||
child->updateTransform();
|
trans = true;
|
||||||
|
drawShadowWithoutBlur();
|
||||||
}
|
}
|
||||||
|
|
||||||
GL::blendFunc( _blendFunc.src, _blendFunc.dst );
|
_shaderProgram->setUniformsForBuiltins(_modelViewTransform);
|
||||||
|
|
||||||
|
for(const auto &child: _children)
|
||||||
|
{
|
||||||
|
if(child->getTag() >= 0)
|
||||||
|
child->updateTransform();
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& batchNode:_batchNodes)
|
for (const auto& batchNode:_batchNodes)
|
||||||
{
|
{
|
||||||
batchNode->getTextureAtlas()->drawQuads();
|
batchNode->getTextureAtlas()->drawQuads();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (trans)
|
||||||
|
{
|
||||||
|
kmGLPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
CC_PROFILER_STOP("Label - draw");
|
CC_PROFILER_STOP("Label - draw");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Label::drawShadowWithoutBlur()
|
||||||
|
{
|
||||||
|
_position.x += _shadowOffset.width;
|
||||||
|
_position.y += _shadowOffset.height;
|
||||||
|
_transformDirty = _inverseDirty = true;
|
||||||
|
Color3B oldColor = _realColor;
|
||||||
|
GLubyte oldOPacity = _displayedOpacity;
|
||||||
|
_displayedOpacity = _shadowOpacity * _displayedOpacity;
|
||||||
|
setColor(_effectColor);
|
||||||
|
|
||||||
|
_modelViewTransform = transform(_parentTransform);
|
||||||
|
kmGLPushMatrix();
|
||||||
|
kmGLLoadMatrix(&_modelViewTransform);
|
||||||
|
|
||||||
|
_shaderProgram->setUniformsForBuiltins(_modelViewTransform);
|
||||||
|
for(const auto &child: _children)
|
||||||
|
{
|
||||||
|
child->updateTransform();
|
||||||
|
}
|
||||||
|
for (const auto& batchNode:_batchNodes)
|
||||||
|
{
|
||||||
|
batchNode->getTextureAtlas()->drawQuads();
|
||||||
|
}
|
||||||
|
|
||||||
|
_position.x -= _shadowOffset.width;
|
||||||
|
_position.y -= _shadowOffset.height;
|
||||||
|
_transformDirty = _inverseDirty = true;
|
||||||
|
_displayedOpacity = oldOPacity;
|
||||||
|
setColor(oldColor);
|
||||||
|
_modelViewTransform = transform(_parentTransform);
|
||||||
|
kmGLLoadMatrix(&_modelViewTransform);
|
||||||
|
//kmGLPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
void Label::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
|
void Label::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
|
||||||
{
|
{
|
||||||
_customCommand.init(_globalZOrder);
|
_customCommand.init(_globalZOrder);
|
||||||
|
@ -692,34 +819,42 @@ void Label::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parent
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_currLabelEffect == LabelEffect::SHADOW && _shadowBlurRadius <= 0)
|
||||||
|
{
|
||||||
|
_parentTransform = parentTransform;
|
||||||
|
draw(renderer, _modelViewTransform, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool dirty = parentTransformUpdated || _transformUpdated;
|
||||||
|
|
||||||
|
if(dirty)
|
||||||
|
_modelViewTransform = transform(parentTransform);
|
||||||
|
_transformUpdated = false;
|
||||||
|
|
||||||
|
// IMPORTANT:
|
||||||
|
// To ease the migration to v3.0, we still support the kmGL stack,
|
||||||
|
// but it is deprecated and your code should not rely on it
|
||||||
|
kmGLPushMatrix();
|
||||||
|
kmGLLoadMatrix(&_modelViewTransform);
|
||||||
|
|
||||||
|
draw(renderer, _modelViewTransform, dirty);
|
||||||
|
|
||||||
|
kmGLPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
bool dirty = parentTransformUpdated || _transformUpdated;
|
|
||||||
if(dirty)
|
|
||||||
_modelViewTransform = transform(parentTransform);
|
|
||||||
_transformUpdated = false;
|
|
||||||
|
|
||||||
// IMPORTANT:
|
|
||||||
// To ease the migration to v3.0, we still support the kmGL stack,
|
|
||||||
// but it is deprecated and your code should not rely on it
|
|
||||||
kmGLPushMatrix();
|
|
||||||
kmGLLoadMatrix(&_modelViewTransform);
|
|
||||||
|
|
||||||
draw(renderer, _modelViewTransform, dirty);
|
|
||||||
|
|
||||||
kmGLPopMatrix();
|
|
||||||
|
|
||||||
setOrderOfArrival(0);
|
setOrderOfArrival(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
///// PROTOCOL STUFF
|
///// PROTOCOL STUFF
|
||||||
|
|
||||||
Sprite * Label::getLetter(int lettetIndex)
|
Sprite * Label::getLetter(int lettetIndex)
|
||||||
{
|
{
|
||||||
if (lettetIndex < getStringLenght())
|
if (lettetIndex < getStringLenght())
|
||||||
{
|
{
|
||||||
if(_lettersInfo[lettetIndex].def.validDefinition == false)
|
if(_lettersInfo[lettetIndex].def.validDefinition == false)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Sprite* sp = static_cast<Sprite*>(this->getChildByTag(lettetIndex));
|
Sprite* sp = static_cast<Sprite*>(this->getChildByTag(lettetIndex));
|
||||||
|
|
||||||
if (!sp)
|
if (!sp)
|
||||||
|
@ -735,12 +870,12 @@ Sprite * Label::getLetter(int lettetIndex)
|
||||||
sp->setAnchorPoint(Point::ANCHOR_MIDDLE);
|
sp->setAnchorPoint(Point::ANCHOR_MIDDLE);
|
||||||
sp->setPosition(Point(_lettersInfo[lettetIndex].position.x+uvRect.size.width/2,_lettersInfo[lettetIndex].position.y-uvRect.size.height/2));
|
sp->setPosition(Point(_lettersInfo[lettetIndex].position.x+uvRect.size.width/2,_lettersInfo[lettetIndex].position.y-uvRect.size.height/2));
|
||||||
sp->setOpacity(_realOpacity);
|
sp->setOpacity(_realOpacity);
|
||||||
|
|
||||||
this->addSpriteWithoutQuad(sp, lettetIndex, lettetIndex);
|
this->addSpriteWithoutQuad(sp, lettetIndex, lettetIndex);
|
||||||
}
|
}
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,14 +893,14 @@ int Label::getStringNumLines() const
|
||||||
void Label::computeStringNumLines()
|
void Label::computeStringNumLines()
|
||||||
{
|
{
|
||||||
int quantityOfLines = 1;
|
int quantityOfLines = 1;
|
||||||
|
|
||||||
unsigned int stringLen = _currentUTF16String ? cc_wcslen(_currentUTF16String) : -1;
|
unsigned int stringLen = _currentUTF16String ? cc_wcslen(_currentUTF16String) : -1;
|
||||||
if (stringLen < 1)
|
if (stringLen < 1)
|
||||||
{
|
{
|
||||||
_currNumLines = stringLen;
|
_currNumLines = stringLen;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// count number of lines
|
// count number of lines
|
||||||
for (unsigned int i = 0; i < stringLen - 1; ++i)
|
for (unsigned int i = 0; i < stringLen - 1; ++i)
|
||||||
{
|
{
|
||||||
|
@ -774,7 +909,7 @@ void Label::computeStringNumLines()
|
||||||
quantityOfLines++;
|
quantityOfLines++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_currNumLines = quantityOfLines;
|
_currNumLines = quantityOfLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,8 +935,6 @@ bool Label::breakLineWithoutSpace() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// RGBA protocol
|
// RGBA protocol
|
||||||
|
|
||||||
|
|
||||||
bool Label::isOpacityModifyRGB() const
|
bool Label::isOpacityModifyRGB() const
|
||||||
{
|
{
|
||||||
return _isOpacityModifyRGB;
|
return _isOpacityModifyRGB;
|
||||||
|
@ -810,7 +943,7 @@ bool Label::isOpacityModifyRGB() const
|
||||||
void Label::setOpacityModifyRGB(bool isOpacityModifyRGB)
|
void Label::setOpacityModifyRGB(bool isOpacityModifyRGB)
|
||||||
{
|
{
|
||||||
_isOpacityModifyRGB = isOpacityModifyRGB;
|
_isOpacityModifyRGB = isOpacityModifyRGB;
|
||||||
|
|
||||||
for(const auto& child: _children) {
|
for(const auto& child: _children) {
|
||||||
child->setOpacityModifyRGB(_isOpacityModifyRGB);
|
child->setOpacityModifyRGB(_isOpacityModifyRGB);
|
||||||
}
|
}
|
||||||
|
@ -820,7 +953,7 @@ void Label::setOpacityModifyRGB(bool isOpacityModifyRGB)
|
||||||
|
|
||||||
void Label::setColor(const Color3B& color)
|
void Label::setColor(const Color3B& color)
|
||||||
{
|
{
|
||||||
_reusedLetter->setColor(color);
|
_reusedLetter->setColor(color);
|
||||||
SpriteBatchNode::setColor(color);
|
SpriteBatchNode::setColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,20 +57,29 @@ typedef struct _ttfConfig
|
||||||
GlyphCollection glyphs;
|
GlyphCollection glyphs;
|
||||||
const char *customGlyphs;
|
const char *customGlyphs;
|
||||||
bool distanceFieldEnabled;
|
bool distanceFieldEnabled;
|
||||||
|
int outlineSize;
|
||||||
|
|
||||||
_ttfConfig(const char* filePath,int size = 36, const GlyphCollection& glyphCollection = GlyphCollection::NEHE,
|
_ttfConfig(const char* filePath = "",int size = 36, const GlyphCollection& glyphCollection = GlyphCollection::NEHE,
|
||||||
const char *customGlyphCollection = nullptr,bool useDistanceField = false)
|
const char *customGlyphCollection = nullptr,bool useDistanceField = false,int outline = 0)
|
||||||
:fontFilePath(filePath)
|
:fontFilePath(filePath)
|
||||||
,fontSize(size)
|
,fontSize(size)
|
||||||
,glyphs(glyphCollection)
|
,glyphs(glyphCollection)
|
||||||
,customGlyphs(customGlyphCollection)
|
,customGlyphs(customGlyphCollection)
|
||||||
,distanceFieldEnabled(useDistanceField)
|
,distanceFieldEnabled(useDistanceField)
|
||||||
{}
|
,outlineSize(outline)
|
||||||
|
{
|
||||||
|
if(outline > 0)
|
||||||
|
{
|
||||||
|
distanceFieldEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}TTFConfig;
|
}TTFConfig;
|
||||||
|
|
||||||
class CC_DLL Label : public SpriteBatchNode, public LabelProtocol
|
class CC_DLL Label : public SpriteBatchNode, public LabelProtocol
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static const int DefultFontSize;
|
||||||
|
|
||||||
static Label* create();
|
static Label* create();
|
||||||
|
|
||||||
CC_DEPRECATED_ATTRIBUTE static Label* createWithTTF(const std::string& label, const std::string& fontFilePath, int fontSize, int lineSize = 0, TextHAlignment alignment = TextHAlignment::LEFT, GlyphCollection glyphs = GlyphCollection::NEHE, const char *customGlyphs = 0, bool useDistanceField = false);
|
CC_DEPRECATED_ATTRIBUTE static Label* createWithTTF(const std::string& label, const std::string& fontFilePath, int fontSize, int lineSize = 0, TextHAlignment alignment = TextHAlignment::LEFT, GlyphCollection glyphs = GlyphCollection::NEHE, const char *customGlyphs = 0, bool useDistanceField = false);
|
||||||
|
@ -82,18 +91,33 @@ public:
|
||||||
static Label * createWithCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap);
|
static Label * createWithCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap);
|
||||||
static Label * createWithCharMap(const std::string& plistFile);
|
static Label * createWithCharMap(const std::string& plistFile);
|
||||||
|
|
||||||
bool setTTFConfig(const TTFConfig& ttfConfig);
|
virtual bool setTTFConfig(const TTFConfig& ttfConfig);
|
||||||
|
|
||||||
bool setBMFontFilePath(const std::string& bmfontFilePath, const Point& imageOffset = Point::ZERO);
|
virtual bool setBMFontFilePath(const std::string& bmfontFilePath, const Point& imageOffset = Point::ZERO);
|
||||||
|
|
||||||
bool setCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap);
|
virtual bool setCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap);
|
||||||
bool setCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap);
|
virtual bool setCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap);
|
||||||
bool setCharMap(const std::string& plistFile);
|
virtual bool setCharMap(const std::string& plistFile);
|
||||||
|
|
||||||
virtual void setString(const std::string& text) override;
|
virtual void setString(const std::string& text) override;
|
||||||
|
|
||||||
//only support for TTF
|
CC_DEPRECATED_ATTRIBUTE void setLabelEffect(LabelEffect effect,const Color3B& effectColor);
|
||||||
void setLabelEffect(LabelEffect effect,const Color3B& effectColor);
|
|
||||||
|
/**
|
||||||
|
* Enable shadow for the label
|
||||||
|
*
|
||||||
|
* @todo support blur for shadow effect
|
||||||
|
*/
|
||||||
|
virtual void enableShadow(const Color3B& shadowColor = Color3B::BLACK,const Size &offset = Size(2,-2), float opacity = 0.75f, int blurRadius = 0);
|
||||||
|
|
||||||
|
/** only support for TTF */
|
||||||
|
virtual void enableOutline(const Color4B& outlineColor,int outlineSize = -1);
|
||||||
|
|
||||||
|
/** only support for TTF */
|
||||||
|
virtual void enableGlow(const Color3B& glowColor);
|
||||||
|
|
||||||
|
/** disable shadow/outline/glow rendering */
|
||||||
|
virtual void disableEffect();
|
||||||
|
|
||||||
virtual void setAlignment(TextHAlignment alignment);
|
virtual void setAlignment(TextHAlignment alignment);
|
||||||
CC_DEPRECATED_ATTRIBUTE void setWidth(float width) { setMaxLineWidth(width);}
|
CC_DEPRECATED_ATTRIBUTE void setWidth(float width) { setMaxLineWidth(width);}
|
||||||
|
@ -112,29 +136,29 @@ public:
|
||||||
virtual Sprite * getLetter(int lettetIndex);
|
virtual Sprite * getLetter(int lettetIndex);
|
||||||
|
|
||||||
// font related stuff
|
// font related stuff
|
||||||
virtual int getCommonLineHeight() const;
|
int getCommonLineHeight() const;
|
||||||
|
|
||||||
|
|
||||||
// string related stuff
|
// string related stuff
|
||||||
virtual int getStringNumLines() const;
|
int getStringNumLines() const;
|
||||||
virtual int getStringLenght() const;
|
int getStringLenght() const;
|
||||||
virtual TextHAlignment getTextAlignment() const;
|
TextHAlignment getTextAlignment() const;
|
||||||
|
|
||||||
// label related stuff
|
// label related stuff
|
||||||
virtual float getMaxLineWidth() const;
|
CC_DEPRECATED_ATTRIBUTE float getWidth() const { getMaxLineWidth(); }
|
||||||
virtual bool breakLineWithoutSpace() const;
|
float getMaxLineWidth() const;
|
||||||
|
bool breakLineWithoutSpace() const;
|
||||||
|
|
||||||
virtual const std::string& getString() const override { return _originalUTF8String; }
|
virtual const std::string& getString() const override { return _originalUTF8String; }
|
||||||
void addChild(Node * child, int zOrder=0, int tag=0) override;
|
virtual void addChild(Node * child, int zOrder=0, int tag=0) override;
|
||||||
|
|
||||||
virtual std::string getDescription() const override;
|
virtual std::string getDescription() const override;
|
||||||
virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
|
virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
|
||||||
virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
|
virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
|
||||||
virtual void onDraw();
|
virtual void onDraw();
|
||||||
|
|
||||||
virtual FontAtlas* getFontAtlas() const {return _fontAtlas;}
|
FontAtlas* getFontAtlas() const {return _fontAtlas;}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
struct LetterInfo
|
struct LetterInfo
|
||||||
{
|
{
|
||||||
FontLetterDefinition def;
|
FontLetterDefinition def;
|
||||||
|
@ -150,19 +174,19 @@ private:
|
||||||
* @js NA
|
* @js NA
|
||||||
* @lua NA
|
* @lua NA
|
||||||
*/
|
*/
|
||||||
~Label();
|
virtual ~Label();
|
||||||
|
|
||||||
bool initWithFontAtlas(FontAtlas* atlas,bool distanceFieldEnabled = false, bool useA8Shader = false);
|
virtual bool initWithFontAtlas(FontAtlas* atlas,bool distanceFieldEnabled = false, bool useA8Shader = false);
|
||||||
|
|
||||||
// CCLabelTextFormat protocol implementation
|
// CCLabelTextFormat protocol implementation
|
||||||
virtual bool recordLetterInfo(const cocos2d::Point& point,const FontLetterDefinition& letterDef, int spriteIndex);
|
bool recordLetterInfo(const cocos2d::Point& point,const FontLetterDefinition& letterDef, int spriteIndex);
|
||||||
virtual bool recordPlaceholderInfo(int spriteIndex);
|
bool recordPlaceholderInfo(int spriteIndex);
|
||||||
|
|
||||||
void setFontScale(float fontScale);
|
void setFontScale(float fontScale);
|
||||||
|
|
||||||
bool init();
|
virtual bool init();
|
||||||
|
|
||||||
void alignText();
|
virtual void alignText();
|
||||||
|
|
||||||
bool computeHorizontalKernings(unsigned short int *stringToRender);
|
bool computeHorizontalKernings(unsigned short int *stringToRender);
|
||||||
bool setCurrentString(unsigned short *stringToSet);
|
bool setCurrentString(unsigned short *stringToSet);
|
||||||
|
@ -174,6 +198,10 @@ private:
|
||||||
|
|
||||||
virtual void updateColor() override;
|
virtual void updateColor() override;
|
||||||
|
|
||||||
|
virtual void initProgram();
|
||||||
|
|
||||||
|
void drawShadowWithoutBlur();
|
||||||
|
|
||||||
//! used for optimization
|
//! used for optimization
|
||||||
Sprite *_reusedLetter;
|
Sprite *_reusedLetter;
|
||||||
Rect _reusedRect;
|
Rect _reusedRect;
|
||||||
|
@ -204,6 +232,19 @@ private:
|
||||||
|
|
||||||
std::vector<SpriteBatchNode*> _batchNodes;
|
std::vector<SpriteBatchNode*> _batchNodes;
|
||||||
|
|
||||||
|
Size _shadowOffset;
|
||||||
|
float _shadowOpacity;
|
||||||
|
int _shadowBlurRadius;
|
||||||
|
|
||||||
|
Color4B _outlineColor;
|
||||||
|
|
||||||
|
TTFConfig _fontConfig;
|
||||||
|
|
||||||
|
kmMat4 _parentTransform;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CC_DISALLOW_COPY_AND_ASSIGN(Label);
|
||||||
|
|
||||||
friend class LabelTextFormatter;
|
friend class LabelTextFormatter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ void main() \n\
|
||||||
//float width = fwidth(dist); \n\
|
//float width = fwidth(dist); \n\
|
||||||
//assign width for constant will lead to a little bit fuzzy,it's temporary measure.\n\
|
//assign width for constant will lead to a little bit fuzzy,it's temporary measure.\n\
|
||||||
float width = 0.04; \n\
|
float width = 0.04; \n\
|
||||||
float alpha = smoothstep(0.5-width, 0.5+width, dist); \n\
|
float alpha = smoothstep(0.5-width, 0.5+width, dist) * v_fragmentColor.a; \n\
|
||||||
gl_FragColor = vec4(v_fragmentColor.rgb,alpha); \n\
|
gl_FragColor = vec4(v_fragmentColor.rgb,alpha); \n\
|
||||||
} \n\
|
} \n\
|
||||||
";
|
";
|
||||||
|
|
|
@ -6,19 +6,19 @@ precision lowp float; \n\
|
||||||
varying vec4 v_fragmentColor; \n\
|
varying vec4 v_fragmentColor; \n\
|
||||||
varying vec2 v_texCoord; \n\
|
varying vec2 v_texCoord; \n\
|
||||||
uniform sampler2D CC_Texture0; \n\
|
uniform sampler2D CC_Texture0; \n\
|
||||||
uniform vec3 v_effectColor; \n\
|
uniform vec4 v_effectColor; \n\
|
||||||
\n\
|
\n\
|
||||||
void main() \n\
|
void main() \n\
|
||||||
{ \n\
|
{ \n\
|
||||||
float dist = texture2D(CC_Texture0, v_texCoord).a; \n\
|
vec4 sample = texture2D(CC_Texture0, v_texCoord); \n\
|
||||||
//todo:Implementation 'fwidth' for glsl 1.0 \n\
|
float fontAlpha = sample.a; \n\
|
||||||
//float width = fwidth(dist); \n\
|
float outlineAlpha = sample.r; \n\
|
||||||
//assign width for constant will lead to a little bit fuzzy,it's temporary measure.\n\
|
if (outlineAlpha > 0.0){ \n\
|
||||||
float width = 0.04; \n\
|
vec3 color = v_fragmentColor.rgb * fontAlpha + v_effectColor.rgb * (1.0 - fontAlpha);\n\
|
||||||
float alpha = smoothstep(0.5-width, 0.5+width, dist); \n\
|
gl_FragColor = vec4( color,max(fontAlpha,outlineAlpha)*v_fragmentColor.a); \n\
|
||||||
//outline \n\
|
} \n\
|
||||||
float mu = smoothstep(0.545-width, 0.545+width, dist); \n\
|
else { \n\
|
||||||
vec3 rgb = v_effectColor*(1.0-mu) + v_fragmentColor.rgb*mu; \n\
|
discard; \n\
|
||||||
gl_FragColor = vec4(rgb, max(alpha,mu)); \n\
|
} \n\
|
||||||
} \n\
|
} \n\
|
||||||
";
|
";
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include "../testResource.h"
|
#include "../testResource.h"
|
||||||
#include "renderer/CCRenderer.h"
|
#include "renderer/CCRenderer.h"
|
||||||
|
|
||||||
|
using namespace ui;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kTagTileMap = 1,
|
kTagTileMap = 1,
|
||||||
kTagSpriteManager = 1,
|
kTagSpriteManager = 1,
|
||||||
|
@ -68,7 +70,8 @@ static std::function<Layer*()> createFunctions[] =
|
||||||
CL(LabelTTFUnicodeNew),
|
CL(LabelTTFUnicodeNew),
|
||||||
CL(LabelBMFontTestNew),
|
CL(LabelBMFontTestNew),
|
||||||
CL(LabelTTFDistanceField),
|
CL(LabelTTFDistanceField),
|
||||||
CL(LabelTTFDistanceFieldEffect),
|
CL(LabelOutlineAndGlowTest),
|
||||||
|
CL(LabelShadowTest),
|
||||||
CL(LabelCharMapTest),
|
CL(LabelCharMapTest),
|
||||||
CL(LabelCharMapColorTest),
|
CL(LabelCharMapColorTest),
|
||||||
CL(LabelCrashTest),
|
CL(LabelCrashTest),
|
||||||
|
@ -1292,7 +1295,7 @@ std::string LabelTTFDistanceField::subtitle() const
|
||||||
return "Testing rendering base on DistanceField";
|
return "Testing rendering base on DistanceField";
|
||||||
}
|
}
|
||||||
|
|
||||||
LabelTTFDistanceFieldEffect::LabelTTFDistanceFieldEffect()
|
LabelOutlineAndGlowTest::LabelOutlineAndGlowTest()
|
||||||
{
|
{
|
||||||
auto size = Director::getInstance()->getWinSize();
|
auto size = Director::getInstance()->getWinSize();
|
||||||
|
|
||||||
|
@ -1302,36 +1305,115 @@ LabelTTFDistanceFieldEffect::LabelTTFDistanceFieldEffect()
|
||||||
TTFConfig ttfConfig("fonts/arial.ttf", 80, GlyphCollection::DYNAMIC,nullptr,true);
|
TTFConfig ttfConfig("fonts/arial.ttf", 80, GlyphCollection::DYNAMIC,nullptr,true);
|
||||||
|
|
||||||
auto label1 = Label::createWithTTF(ttfConfig,"Glow", TextHAlignment::CENTER, size.width);
|
auto label1 = Label::createWithTTF(ttfConfig,"Glow", TextHAlignment::CENTER, size.width);
|
||||||
label1->setPosition( Point(size.width/2, size.height*0.65) );
|
label1->setPosition( Point(size.width/2, size.height*0.7) );
|
||||||
label1->setColor( Color3B::GREEN );
|
label1->setColor( Color3B::GREEN );
|
||||||
label1->setAnchorPoint(Point::ANCHOR_MIDDLE);
|
label1->setAnchorPoint(Point::ANCHOR_MIDDLE);
|
||||||
label1->setLabelEffect(LabelEffect::GLOW,Color3B::YELLOW);
|
label1->enableGlow(Color3B::YELLOW);
|
||||||
addChild(label1);
|
addChild(label1);
|
||||||
|
|
||||||
|
ttfConfig.outlineSize = 1;
|
||||||
auto label2 = Label::createWithTTF(ttfConfig,"Outline", TextHAlignment::CENTER, size.width);
|
auto label2 = Label::createWithTTF(ttfConfig,"Outline", TextHAlignment::CENTER, size.width);
|
||||||
label2->setPosition( Point(size.width/2, size.height*0.5) );
|
label2->setPosition( Point(size.width/2, size.height*0.6) );
|
||||||
label2->setColor( Color3B::RED );
|
label2->setColor( Color3B::RED );
|
||||||
label2->setAnchorPoint(Point::ANCHOR_MIDDLE);
|
label2->setAnchorPoint(Point::ANCHOR_MIDDLE);
|
||||||
label2->setLabelEffect(LabelEffect::OUTLINE,Color3B::BLUE);
|
label2->enableOutline(Color4B::BLUE);
|
||||||
addChild(label2);
|
addChild(label2);
|
||||||
|
|
||||||
auto label3 = Label::createWithTTF(ttfConfig,"Shadow", TextHAlignment::CENTER, size.width);
|
ttfConfig.outlineSize = 2;
|
||||||
label3->setPosition( Point(size.width/2, size.height*0.35f) );
|
auto label3 = Label::createWithTTF(ttfConfig,"Outline", TextHAlignment::CENTER, size.width);
|
||||||
|
label3->setPosition( Point(size.width/2, size.height*0.48) );
|
||||||
label3->setColor( Color3B::RED );
|
label3->setColor( Color3B::RED );
|
||||||
label3->setAnchorPoint(Point::ANCHOR_MIDDLE);
|
label3->setAnchorPoint(Point::ANCHOR_MIDDLE);
|
||||||
label3->setLabelEffect(LabelEffect::SHADOW,Color3B::BLACK);
|
label3->enableOutline(Color4B::BLUE);
|
||||||
addChild(label3);
|
addChild(label3);
|
||||||
|
|
||||||
|
ttfConfig.outlineSize = 3;
|
||||||
|
auto label4 = Label::createWithTTF(ttfConfig,"Outline", TextHAlignment::CENTER, size.width);
|
||||||
|
label4->setPosition( Point(size.width/2, size.height*0.36) );
|
||||||
|
label4->setColor( Color3B::RED );
|
||||||
|
label4->setAnchorPoint(Point::ANCHOR_MIDDLE);
|
||||||
|
label4->enableOutline(Color4B::BLUE);
|
||||||
|
addChild(label4);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LabelTTFDistanceFieldEffect::title() const
|
std::string LabelOutlineAndGlowTest::title() const
|
||||||
{
|
{
|
||||||
return "New Label + .TTF";
|
return "New Label";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LabelTTFDistanceFieldEffect::subtitle() const
|
std::string LabelOutlineAndGlowTest::subtitle() const
|
||||||
{
|
{
|
||||||
return "Testing effect base on DistanceField";
|
return "Testing outline and glow of label";
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelShadowTest::LabelShadowTest()
|
||||||
|
{
|
||||||
|
auto size = Director::getInstance()->getWinSize();
|
||||||
|
|
||||||
|
auto bg = LayerColor::create(Color4B(200,191,231,255));
|
||||||
|
this->addChild(bg);
|
||||||
|
|
||||||
|
TTFConfig ttfConfig("fonts/arial.ttf", 80, GlyphCollection::DYNAMIC,nullptr,true);
|
||||||
|
|
||||||
|
shadowLabelTTF = Label::createWithTTF(ttfConfig,"TTF:Shadow", TextHAlignment::CENTER, size.width);
|
||||||
|
shadowLabelTTF->setPosition( Point(size.width/2, size.height*0.6f) );
|
||||||
|
shadowLabelTTF->setColor( Color3B::RED );
|
||||||
|
shadowLabelTTF->setAnchorPoint(Point::ANCHOR_MIDDLE);
|
||||||
|
shadowLabelTTF->enableShadow(Color3B::BLACK);
|
||||||
|
addChild(shadowLabelTTF);
|
||||||
|
|
||||||
|
shadowLabelBMFont = Label::createWithBMFont("fonts/bitmapFontTest.fnt", "BMFont:Shadow");
|
||||||
|
shadowLabelBMFont->setPosition( Point(size.width/2, size.height*0.4f) );
|
||||||
|
shadowLabelBMFont->setColor( Color3B::RED );
|
||||||
|
shadowLabelBMFont->setAnchorPoint(Point::ANCHOR_MIDDLE);
|
||||||
|
shadowLabelBMFont->enableShadow(Color3B::GREEN);
|
||||||
|
addChild(shadowLabelBMFont);
|
||||||
|
|
||||||
|
auto slider = ui::Slider::create();
|
||||||
|
slider->setTag(1);
|
||||||
|
slider->setTouchEnabled(true);
|
||||||
|
slider->loadBarTexture("cocosgui/sliderTrack.png");
|
||||||
|
slider->loadSlidBallTextures("cocosgui/sliderThumb.png", "cocosgui/sliderThumb.png", "");
|
||||||
|
slider->loadProgressBarTexture("cocosgui/sliderProgress.png");
|
||||||
|
slider->setPosition(Point(size.width / 2.0f, size.height * 0.15f + slider->getSize().height * 2.0f));
|
||||||
|
slider->setPercent(52);
|
||||||
|
slider->addEventListenerSlider(this, sliderpercentchangedselector(LabelShadowTest::sliderEvent));
|
||||||
|
addChild(slider);
|
||||||
|
|
||||||
|
auto slider2 = ui::Slider::create();
|
||||||
|
slider2->setTag(2);
|
||||||
|
slider2->setTouchEnabled(true);
|
||||||
|
slider2->loadBarTexture("cocosgui/sliderTrack.png");
|
||||||
|
slider2->loadSlidBallTextures("cocosgui/sliderThumb.png", "cocosgui/sliderThumb.png", "");
|
||||||
|
slider2->loadProgressBarTexture("cocosgui/sliderProgress.png");
|
||||||
|
slider2->setPosition(Point(size.width * 0.15f, size.height / 2.0));
|
||||||
|
slider2->setRotation(90);
|
||||||
|
slider2->setPercent(52);
|
||||||
|
slider2->addEventListenerSlider(this, sliderpercentchangedselector(LabelShadowTest::sliderEvent));
|
||||||
|
addChild(slider2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelShadowTest::sliderEvent(Ref *pSender, ui::SliderEventType type)
|
||||||
|
{
|
||||||
|
if (type == SLIDER_PERCENTCHANGED)
|
||||||
|
{
|
||||||
|
Slider* slider = (Slider*)this->getChildByTag(1);
|
||||||
|
Slider* slider2 = (Slider*)this->getChildByTag(2);
|
||||||
|
|
||||||
|
auto offset = Size(slider->getPercent()-50,50 - slider2->getPercent());
|
||||||
|
shadowLabelTTF->enableShadow(Color3B::BLACK,offset);
|
||||||
|
shadowLabelBMFont->enableShadow(Color3B::GREEN,offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LabelShadowTest::title() const
|
||||||
|
{
|
||||||
|
return "New Label";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LabelShadowTest::subtitle() const
|
||||||
|
{
|
||||||
|
return "Testing shadow of label";
|
||||||
}
|
}
|
||||||
|
|
||||||
LabelCharMapTest::LabelCharMapTest()
|
LabelCharMapTest::LabelCharMapTest()
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../testBasic.h"
|
#include "../testBasic.h"
|
||||||
#include "../BaseTest.h"
|
#include "../BaseTest.h"
|
||||||
#include "renderer/CCCustomCommand.h"
|
#include "renderer/CCCustomCommand.h"
|
||||||
|
#include "gui/CocosGUI.h"
|
||||||
|
|
||||||
|
|
||||||
class AtlasDemoNew : public BaseTest
|
class AtlasDemoNew : public BaseTest
|
||||||
|
@ -349,17 +350,33 @@ public:
|
||||||
virtual std::string subtitle() const override;
|
virtual std::string subtitle() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LabelTTFDistanceFieldEffect : public AtlasDemoNew
|
class LabelOutlineAndGlowTest : public AtlasDemoNew
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CREATE_FUNC(LabelTTFDistanceFieldEffect);
|
CREATE_FUNC(LabelOutlineAndGlowTest);
|
||||||
|
|
||||||
LabelTTFDistanceFieldEffect();
|
LabelOutlineAndGlowTest();
|
||||||
|
|
||||||
virtual std::string title() const override;
|
virtual std::string title() const override;
|
||||||
virtual std::string subtitle() const override;
|
virtual std::string subtitle() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LabelShadowTest : public AtlasDemoNew
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CREATE_FUNC(LabelShadowTest);
|
||||||
|
|
||||||
|
LabelShadowTest();
|
||||||
|
|
||||||
|
virtual std::string title() const override;
|
||||||
|
virtual std::string subtitle() const override;
|
||||||
|
|
||||||
|
void sliderEvent(Ref *pSender, ui::SliderEventType type);
|
||||||
|
private:
|
||||||
|
Label* shadowLabelTTF;
|
||||||
|
Label* shadowLabelBMFont;
|
||||||
|
};
|
||||||
|
|
||||||
class LabelCharMapTest : public AtlasDemoNew
|
class LabelCharMapTest : public AtlasDemoNew
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in New Issue