mirror of https://github.com/axmolengine/axmol.git
Merge pull request #4025 from Dhilan007/di2893
issues #2893:perfect new label
This commit is contained in:
commit
f684dc0ff7
|
@ -60,6 +60,7 @@ THE SOFTWARE.
|
|||
#include "CCEGLView.h"
|
||||
#include "CCConfiguration.h"
|
||||
#include "CCEventDispatcher.h"
|
||||
#include "CCFontFreeType.h"
|
||||
|
||||
/**
|
||||
Position of the FPS
|
||||
|
@ -686,6 +687,8 @@ void Director::purgeDirector()
|
|||
// purge bitmap cache
|
||||
LabelBMFont::purgeCachedData();
|
||||
|
||||
FontFreeType::shutdownFreeType();
|
||||
|
||||
// purge all managed caches
|
||||
DrawPrimitives::free();
|
||||
AnimationCache::destroyInstance();
|
||||
|
|
|
@ -73,13 +73,15 @@ void Font::setCurrentGlyphCollection(GlyphCollection glyphs, const char *customG
|
|||
break;
|
||||
|
||||
default:
|
||||
|
||||
int lenght = strlen(customGlyphs);
|
||||
_customGlyphs = new char [lenght + 2];
|
||||
memcpy(_customGlyphs, customGlyphs, lenght);
|
||||
|
||||
_customGlyphs[lenght] = 0;
|
||||
_customGlyphs[lenght+1] = 0;
|
||||
if (customGlyphs)
|
||||
{
|
||||
int lenght = strlen(customGlyphs);
|
||||
_customGlyphs = new char [lenght + 2];
|
||||
memcpy(_customGlyphs, customGlyphs, lenght);
|
||||
|
||||
_customGlyphs[lenght] = 0;
|
||||
_customGlyphs[lenght+1] = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -9,18 +9,41 @@
|
|||
#include "cocos2d.h"
|
||||
#include "CCFontAtlas.h"
|
||||
#include "CCFont.h"
|
||||
#include "CCFontFreeType.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
FontAtlas::FontAtlas(Font &theFont) : _font(theFont)
|
||||
FontAtlas::FontAtlas(Font &theFont) :
|
||||
_font(&theFont),
|
||||
_currentPageData(nullptr)
|
||||
{
|
||||
_font.retain();
|
||||
_font->retain();
|
||||
|
||||
FontFreeType* fontTTf = dynamic_cast<FontFreeType*>(_font);
|
||||
if (fontTTf && fontTTf->isDynamicGlyphCollection())
|
||||
{
|
||||
_currentPageLineHeight = _font->getFontMaxHeight();
|
||||
_commonLineHeight = _currentPageLineHeight * 0.8f;
|
||||
Texture2D * tex = new Texture2D;
|
||||
_currentPage = 0;
|
||||
_currentPageOrigX = 0;
|
||||
_currentPageOrigY = 0;
|
||||
_letterPadding = 5;
|
||||
_currentPageDataSize = (1024 * 1024 * 4);
|
||||
|
||||
_currentPageData = new unsigned char[_currentPageDataSize];
|
||||
memset(_currentPageData, 0, _currentPageDataSize);
|
||||
addTexture(*tex,0);
|
||||
tex->release();
|
||||
}
|
||||
}
|
||||
|
||||
FontAtlas::~FontAtlas()
|
||||
{
|
||||
_font.release();
|
||||
_font->release();
|
||||
relaseTextures();
|
||||
|
||||
delete []_currentPageData;
|
||||
}
|
||||
|
||||
void FontAtlas::relaseTextures()
|
||||
|
@ -51,6 +74,146 @@ bool FontAtlas::getLetterDefinitionForChar(unsigned short letteCharUTF16, FontL
|
|||
}
|
||||
}
|
||||
|
||||
bool FontAtlas::prepareLetterDefinitions(unsigned short *utf16String)
|
||||
{
|
||||
if(_currentPageData == nullptr)
|
||||
return false;
|
||||
|
||||
FontFreeType* fontTTf = (FontFreeType*)_font;
|
||||
|
||||
std::vector<FontLetterDefinition> fontDefs;
|
||||
int length = cc_wcslen(utf16String);
|
||||
|
||||
//find out new letter
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
auto outIterator = _fontLetterDefinitions.find(utf16String[i]);
|
||||
|
||||
if (outIterator == _fontLetterDefinitions.end())
|
||||
{
|
||||
Rect tempRect;
|
||||
|
||||
FontLetterDefinition tempDef;
|
||||
tempDef.offsetX = 0;
|
||||
tempDef.anchorX = 0.0f;
|
||||
tempDef.anchorY = 1.0f;
|
||||
|
||||
if (!fontTTf->getBBOXFotChar(utf16String[i], tempRect))
|
||||
{
|
||||
tempDef.validDefinition = false;
|
||||
tempDef.letteCharUTF16 = utf16String[i];
|
||||
tempDef.commonLineHeight = 0;
|
||||
tempDef.width = 0;
|
||||
tempDef.height = 0;
|
||||
tempDef.U = 0;
|
||||
tempDef.V = 0;
|
||||
tempDef.offsetY = 0;
|
||||
tempDef.textureID = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempDef.validDefinition = true;
|
||||
tempDef.letteCharUTF16 = utf16String[i];
|
||||
tempDef.width = tempRect.size.width + _letterPadding;
|
||||
tempDef.height = _currentPageLineHeight - 1;
|
||||
tempDef.offsetY = tempRect.origin.y;
|
||||
tempDef.commonLineHeight = _currentPageLineHeight;
|
||||
|
||||
}
|
||||
fontDefs.push_back(tempDef);
|
||||
}
|
||||
}
|
||||
|
||||
float scaleFactor = CC_CONTENT_SCALE_FACTOR();
|
||||
int newLetterCount = fontDefs.size();
|
||||
float glyphWidth;
|
||||
for (int i = 0; i < newLetterCount; ++i)
|
||||
{
|
||||
if (fontDefs[i].validDefinition)
|
||||
{
|
||||
_currentPageOrigX += _letterPadding;
|
||||
glyphWidth = fontDefs[i].width - _letterPadding;
|
||||
|
||||
if (_currentPageOrigX + glyphWidth > 1024)
|
||||
{
|
||||
_currentPageOrigY += _currentPageLineHeight;
|
||||
if(_currentPageOrigY >= 1024)
|
||||
{
|
||||
_atlasTextures[_currentPage]->initWithData(_currentPageData, _currentPageDataSize, Texture2D::PixelFormat::RGBA8888, 1024, 1024, Size(1024, 1024) );
|
||||
_currentPageOrigX = 0;
|
||||
_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();
|
||||
}
|
||||
}
|
||||
renderCharAt(fontDefs[i].letteCharUTF16,_currentPageOrigX,_currentPageOrigY,_currentPageData,1024);
|
||||
|
||||
fontDefs[i].U = _currentPageOrigX - 1;
|
||||
fontDefs[i].V = _currentPageOrigY;
|
||||
fontDefs[i].textureID = _currentPage;
|
||||
// take from pixels to points
|
||||
fontDefs[i].width = fontDefs[i].width / scaleFactor;
|
||||
fontDefs[i].height = fontDefs[i].height / scaleFactor;
|
||||
fontDefs[i].U = fontDefs[i].U / scaleFactor;
|
||||
fontDefs[i].V = fontDefs[i].V / scaleFactor;
|
||||
}
|
||||
else
|
||||
glyphWidth = 0;
|
||||
|
||||
this->addLetterDefinition(fontDefs[i]);
|
||||
_currentPageOrigX += glyphWidth;
|
||||
}
|
||||
if(newLetterCount > 0)
|
||||
_atlasTextures[_currentPage]->initWithData(_currentPageData, _currentPageDataSize, Texture2D::PixelFormat::RGBA8888, 1024, 1024, Size(1024, 1024) );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FontAtlas::renderCharAt(unsigned short int charToRender, int posX, int posY, unsigned char *destMemory, int destSize)
|
||||
{
|
||||
unsigned char *sourceBitmap = 0;
|
||||
int sourceWidth = 0;
|
||||
int sourceHeight = 0;
|
||||
|
||||
// get the glyph's bitmap
|
||||
sourceBitmap = _font->getGlyphBitmap(charToRender, sourceWidth, sourceHeight);
|
||||
|
||||
if (!sourceBitmap)
|
||||
return false;
|
||||
|
||||
int iX = posX;
|
||||
int iY = posY;
|
||||
|
||||
for (int y = 0; y < sourceHeight; ++y)
|
||||
{
|
||||
int bitmap_y = y * sourceWidth;
|
||||
|
||||
for (int x = 0; x < sourceWidth; ++x)
|
||||
{
|
||||
unsigned char cTemp = sourceBitmap[bitmap_y + x];
|
||||
|
||||
// the final pixel
|
||||
int iTemp = cTemp << 24 | cTemp << 16 | cTemp << 8 | cTemp;
|
||||
*(int*) &destMemory[(iX + ( iY * destSize ) ) * 4] = iTemp;
|
||||
|
||||
iX += 1;
|
||||
}
|
||||
|
||||
iX = posX;
|
||||
iY += 1;
|
||||
}
|
||||
|
||||
//everything good
|
||||
return true;
|
||||
}
|
||||
|
||||
void FontAtlas::addTexture(Texture2D &texture, int slot)
|
||||
{
|
||||
texture.retain();
|
||||
|
@ -72,7 +235,7 @@ void FontAtlas::setCommonLineHeight(float newHeight)
|
|||
_commonLineHeight = newHeight;
|
||||
}
|
||||
|
||||
Font & FontAtlas::getFont() const
|
||||
const Font * FontAtlas::getFont() const
|
||||
{
|
||||
return _font;
|
||||
}
|
||||
|
|
|
@ -63,21 +63,32 @@ public:
|
|||
void addLetterDefinition(const FontLetterDefinition &letterDefinition);
|
||||
bool getLetterDefinitionForChar(unsigned short letteCharUTF16, FontLetterDefinition &outDefinition);
|
||||
|
||||
bool prepareLetterDefinitions(unsigned short *utf16String);
|
||||
|
||||
void addTexture(Texture2D &texture, int slot);
|
||||
float getCommonLineHeight() const;
|
||||
void setCommonLineHeight(float newHeight);
|
||||
|
||||
Texture2D & getTexture(int slot);
|
||||
Font & getFont() const;
|
||||
const Font * getFont() const;
|
||||
|
||||
private:
|
||||
|
||||
bool renderCharAt(unsigned short int charToRender, int posX, int posY, unsigned char *destMemory, int destSize);
|
||||
|
||||
void relaseTextures();
|
||||
std::map<int, Texture2D *> _atlasTextures;
|
||||
std::map<unsigned short, FontLetterDefinition> _fontLetterDefinitions;
|
||||
float _commonLineHeight;
|
||||
Font & _font;
|
||||
Font * _font;
|
||||
|
||||
// Dynamic GlyphCollection related stuff
|
||||
int _currentPage;
|
||||
unsigned char *_currentPageData;
|
||||
int _currentPageDataSize;
|
||||
float _currentPageOrigX;
|
||||
float _currentPageOrigY;
|
||||
float _currentPageLineHeight;
|
||||
float _letterPadding;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -16,11 +16,6 @@ NS_CC_BEGIN
|
|||
|
||||
FontAtlas * FontAtlasFactory::createAtlasFromTTF(const char* fntFilePath, int fontSize, GlyphCollection glyphs, const char *customGlyphs)
|
||||
{
|
||||
if( glyphs == GlyphCollection::DYNAMIC )
|
||||
{
|
||||
log("ERROR: GlyphCollection::DYNAMIC is not supported yet!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Font *font = Font::createWithTTF(fntFilePath, fontSize, glyphs, customGlyphs);
|
||||
if (font)
|
||||
|
@ -34,9 +29,14 @@ FontAtlas * FontAtlasFactory::createAtlasFromFNT(const char* fntFilePath)
|
|||
Font *font = Font::createWithFNT(fntFilePath);
|
||||
|
||||
if(font)
|
||||
return font->createFontAtlas();
|
||||
{
|
||||
FontAtlas * atlas = font->createFontAtlas();
|
||||
return atlas;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -49,6 +49,7 @@ FontDefinitionTTF* FontDefinitionTTF::create(Font *font, int textureSize)
|
|||
|
||||
if (ret->initDefinition(font, glyph, textureSize))
|
||||
{
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -32,14 +32,13 @@ FontFNT * FontFNT::create(const char* fntFilePath)
|
|||
delete newConf;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tempFont->autorelease();
|
||||
return tempFont;
|
||||
}
|
||||
|
||||
FontFNT::~FontFNT()
|
||||
{
|
||||
if (_configuration)
|
||||
_configuration->release();
|
||||
|
||||
}
|
||||
|
||||
Size * FontFNT::getAdvancesForTextUTF16(unsigned short *text, int &outNumLetters) const
|
||||
|
@ -176,7 +175,7 @@ FontAtlas * FontFNT::createFontAtlas()
|
|||
|
||||
tempDefinition.anchorX = 0.5f;
|
||||
tempDefinition.anchorY = 0.5f;
|
||||
|
||||
tempDefinition.validDefinition = true;
|
||||
// add the new definition
|
||||
tempAtlas->addLetterDefinition(tempDefinition);
|
||||
}
|
||||
|
|
|
@ -1,28 +1,29 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2013 Zynga Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
Copyright (c) 2013 Zynga Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "ccUTF8.h"
|
||||
#include "CCFontFreeType.h"
|
||||
|
@ -38,14 +39,12 @@ bool FontFreeType::_FTInitialized = false;
|
|||
|
||||
FontFreeType * FontFreeType::create(const std::string &fontName, int fontSize, GlyphCollection glyphs, const char *customGlyphs)
|
||||
{
|
||||
if( glyphs == GlyphCollection::DYNAMIC )
|
||||
{
|
||||
log("ERROR: GlyphCollection::DYNAMIC is not supported yet!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FontFreeType *tempFont = new FontFreeType();
|
||||
bool dynamicGlyphCollection = false;
|
||||
if(glyphs == GlyphCollection::DYNAMIC)
|
||||
dynamicGlyphCollection = true;
|
||||
|
||||
FontFreeType *tempFont = new FontFreeType(dynamicGlyphCollection);
|
||||
|
||||
if (!tempFont)
|
||||
return nullptr;
|
||||
|
||||
|
@ -56,7 +55,6 @@ FontFreeType * FontFreeType::create(const std::string &fontName, int fontSize, G
|
|||
delete tempFont;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return tempFont;
|
||||
}
|
||||
|
||||
|
@ -79,6 +77,7 @@ void FontFreeType::shutdownFreeType()
|
|||
if (_FTInitialized == true)
|
||||
{
|
||||
FT_Done_FreeType(_FTlibrary);
|
||||
_FTInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,34 +87,35 @@ FT_Library FontFreeType::getFTLibrary()
|
|||
return _FTlibrary;
|
||||
}
|
||||
|
||||
FontFreeType::FontFreeType() : _letterPadding(5)
|
||||
FontFreeType::FontFreeType(bool dynamicGlyphCollection)
|
||||
: _letterPadding(5),
|
||||
_ttfData(nullptr),
|
||||
_dynamicGlyphCollection(dynamicGlyphCollection),
|
||||
_fontRef(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool FontFreeType::createFontObject(const std::string &fontName, int fontSize)
|
||||
{
|
||||
int dpi = 72;
|
||||
|
||||
int len = 0;
|
||||
unsigned char* data = FileUtils::getInstance()->getFileData(fontName.c_str(), "rb", (unsigned long *)(&len));
|
||||
|
||||
if (!data)
|
||||
return false;
|
||||
|
||||
// create the new face
|
||||
FT_Face face;
|
||||
|
||||
// create the face from the data
|
||||
if (FT_New_Memory_Face(getFTLibrary(), data, len, 0, &face ))
|
||||
|
||||
int len = 0;
|
||||
_ttfData = FileUtils::getInstance()->getFileData(fontName.c_str(), "rb", (unsigned long *)(&len));
|
||||
if (!_ttfData)
|
||||
return false;
|
||||
|
||||
|
||||
// create the face from the data
|
||||
if (FT_New_Memory_Face(getFTLibrary(), _ttfData, len, 0, &face ))
|
||||
return false;
|
||||
|
||||
//we want to use unicode
|
||||
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE))
|
||||
return false;
|
||||
|
||||
|
||||
// set the requested font size
|
||||
int fontSizePoints = (int)(64.f * fontSize);
|
||||
if (FT_Set_Char_Size(face, fontSizePoints, fontSizePoints, dpi, dpi))
|
||||
int dpi = 72;
|
||||
int fontSizePoints = (int)(64.f * fontSize);
|
||||
if (FT_Set_Char_Size(face, fontSizePoints, fontSizePoints, dpi, dpi))
|
||||
return false;
|
||||
|
||||
// store the face globally
|
||||
|
@ -130,22 +130,36 @@ bool FontFreeType::createFontObject(const std::string &fontName, int fontSize)
|
|||
|
||||
FontFreeType::~FontFreeType()
|
||||
{
|
||||
// release the font
|
||||
// TO DO
|
||||
if (_fontRef)
|
||||
{
|
||||
FT_Done_Face(_fontRef);
|
||||
}
|
||||
if (_ttfData)
|
||||
{
|
||||
delete _ttfData;
|
||||
_ttfData = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
FontAtlas * FontFreeType::createFontAtlas()
|
||||
{
|
||||
FontDefinitionTTF *def = FontDefinitionTTF::create(this);
|
||||
|
||||
if (!def)
|
||||
return nullptr;
|
||||
|
||||
FontAtlas *atlas = def->createFontAtlas();
|
||||
|
||||
// release the font definition, we don't need it anymore
|
||||
def->release();
|
||||
return atlas;
|
||||
if (_dynamicGlyphCollection)
|
||||
{
|
||||
FontAtlas *atlas = new FontAtlas(*this);
|
||||
this->release();
|
||||
return atlas;
|
||||
}
|
||||
else
|
||||
{
|
||||
FontDefinitionTTF *def = FontDefinitionTTF::create(this);
|
||||
|
||||
if (!def)
|
||||
return nullptr;
|
||||
|
||||
FontAtlas *atlas = def->createFontAtlas();
|
||||
|
||||
return atlas;
|
||||
}
|
||||
}
|
||||
|
||||
bool FontFreeType::getBBOXFotChar(unsigned short theChar, Rect &outRect) const
|
||||
|
|
|
@ -39,7 +39,9 @@ class CC_DLL FontFreeType : public Font
|
|||
public:
|
||||
|
||||
static FontFreeType * create(const std::string &fontName, int fontSize, GlyphCollection glyphs, const char *customGlyphs);
|
||||
|
||||
|
||||
static void shutdownFreeType();
|
||||
|
||||
virtual FontAtlas * createFontAtlas() override;
|
||||
virtual Size * getAdvancesForTextUTF16(unsigned short *text, int &outNumLetters) const override;
|
||||
virtual GlyphDef * getGlyphDefintionsForText(const char *text, int &outNumGlyphs, bool UTF16text = false) const override;
|
||||
|
@ -47,20 +49,21 @@ public:
|
|||
virtual int getFontMaxHeight() const override;
|
||||
virtual int getLetterPadding() const override;
|
||||
|
||||
|
||||
bool getBBOXFotChar(unsigned short theChar, Rect &outRect) const;
|
||||
|
||||
inline bool isDynamicGlyphCollection() { return _dynamicGlyphCollection;}
|
||||
|
||||
protected:
|
||||
|
||||
FontFreeType();
|
||||
FontFreeType(bool dynamicGlyphCollection = false);
|
||||
virtual ~FontFreeType();
|
||||
bool createFontObject(const std::string &fontName, int fontSize);
|
||||
|
||||
private:
|
||||
|
||||
bool initFreeType();
|
||||
void shutdownFreeType();
|
||||
FT_Library getFTLibrary();
|
||||
|
||||
bool getBBOXFotChar(unsigned short theChar, Rect &outRect) const;
|
||||
int getAdvanceForChar(unsigned short theChar) const;
|
||||
int getBearingXForChar(unsigned short theChar) const;
|
||||
int getHorizontalKerningForChars(unsigned short firstChar, unsigned short secondChar) const;
|
||||
|
@ -70,7 +73,8 @@ private:
|
|||
FT_Face _fontRef;
|
||||
const int _letterPadding;
|
||||
std::string _fontName;
|
||||
|
||||
unsigned char* _ttfData;
|
||||
bool _dynamicGlyphCollection;
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -46,8 +46,6 @@ Label* Label::createWithTTF( const char* label, const char* fontFilePath, int fo
|
|||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Label* Label::createWithBMFont( const char* label, const char* bmfontFilePath, TextHAlignment alignment, int lineSize)
|
||||
|
@ -95,8 +93,8 @@ Label* Label::createWithAtlas(FontAtlas *atlas, TextHAlignment alignment, int li
|
|||
}
|
||||
|
||||
Label::Label(FontAtlas *atlas, TextHAlignment alignment)
|
||||
: _currentUTF8String(0)
|
||||
, _originalUTF8String(0)
|
||||
: _currentUTF16String(0)
|
||||
, _originalUTF16String(0)
|
||||
, _fontAtlas(atlas)
|
||||
, _alignment(alignment)
|
||||
, _lineBreakWithoutSpaces(false)
|
||||
|
@ -107,32 +105,32 @@ Label::Label(FontAtlas *atlas, TextHAlignment alignment)
|
|||
, _cascadeOpacityEnabled(true)
|
||||
, _displayedOpacity(255)
|
||||
, _realOpacity(255)
|
||||
, _isOpacityModifyRGB(false)
|
||||
, _isOpacityModifyRGB(true)
|
||||
,_reusedLetter(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Label::~Label()
|
||||
{
|
||||
CC_SAFE_RELEASE(_spriteArray);
|
||||
CC_SAFE_RELEASE(_spriteArrayCache);
|
||||
|
||||
if (_currentUTF8String)
|
||||
delete [] _currentUTF8String;
|
||||
|
||||
if (_advances)
|
||||
delete [] _advances;
|
||||
{
|
||||
delete [] _currentUTF16String;
|
||||
delete [] _originalUTF16String;
|
||||
delete [] _advances;
|
||||
|
||||
if (_fontAtlas)
|
||||
FontAtlasCache::releaseFontAtlas(_fontAtlas);
|
||||
|
||||
delete _reusedLetter;
|
||||
}
|
||||
|
||||
bool Label::init()
|
||||
{
|
||||
_spriteArray = Array::createWithCapacity(30);
|
||||
_spriteArrayCache = Array::createWithCapacity(30);
|
||||
|
||||
_spriteArray->retain();
|
||||
_spriteArrayCache->retain();
|
||||
{
|
||||
if(_fontAtlas)
|
||||
{
|
||||
_reusedLetter = new Sprite;
|
||||
_reusedLetter->initWithTexture(&_fontAtlas->getTexture(0));
|
||||
_reusedLetter->setOpacityModifyRGB(_isOpacityModifyRGB);
|
||||
return SpriteBatchNode::initWithTexture(&_fontAtlas->getTexture(0), 30);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -151,14 +149,10 @@ bool Label::setText(const char *stringToRender, float lineWidth, TextHAlignment
|
|||
// reset the string
|
||||
resetCurrentString();
|
||||
|
||||
|
||||
_width = lineWidth;
|
||||
_alignment = alignment;
|
||||
_lineBreakWithoutSpaces = lineBreakWithoutSpaces;
|
||||
|
||||
// release all the sprites
|
||||
moveAllSpritesToCache();
|
||||
|
||||
// store locally common line height
|
||||
_commonLineHeight = _fontAtlas->getCommonLineHeight();
|
||||
if (_commonLineHeight <= 0)
|
||||
|
@ -169,11 +163,8 @@ bool Label::setText(const char *stringToRender, float lineWidth, TextHAlignment
|
|||
if(!utf16String)
|
||||
return false;
|
||||
|
||||
numLetter = cc_wcslen(utf16String);
|
||||
SpriteBatchNode::initWithTexture(&_fontAtlas->getTexture(0), numLetter);
|
||||
_cascadeColorEnabled = true;
|
||||
|
||||
//
|
||||
setCurrentString(utf16String);
|
||||
setOriginalString(utf16String);
|
||||
|
||||
|
@ -247,30 +238,55 @@ void Label::setScaleY(float scaleY)
|
|||
}
|
||||
|
||||
void Label::alignText()
|
||||
{
|
||||
hideAllLetters();
|
||||
LabelTextFormatter::createStringSprites(this);
|
||||
|
||||
if( LabelTextFormatter::multilineText(this) )
|
||||
{
|
||||
hideAllLetters();
|
||||
{
|
||||
if(_textureAtlas)
|
||||
_textureAtlas->removeAllQuads();
|
||||
_fontAtlas->prepareLetterDefinitions(_currentUTF16String);
|
||||
LabelTextFormatter::createStringSprites(this);
|
||||
if( LabelTextFormatter::multilineText(this) )
|
||||
LabelTextFormatter::createStringSprites(this);
|
||||
}
|
||||
|
||||
LabelTextFormatter::alignText(this);
|
||||
}
|
||||
|
||||
void Label::hideAllLetters()
|
||||
{
|
||||
Object* Obj = NULL;
|
||||
CCARRAY_FOREACH(_spriteArray, Obj)
|
||||
|
||||
int strLen = cc_wcslen(_currentUTF16String);
|
||||
if (_children && _children->count() != 0)
|
||||
{
|
||||
((Sprite *)Obj)->setVisible(false);
|
||||
for (auto child: *_children)
|
||||
{
|
||||
Node* pNode = static_cast<Node*>( child );
|
||||
if (pNode)
|
||||
{
|
||||
int tag = pNode->getTag();
|
||||
if(tag < 0 || tag >= strLen)
|
||||
SpriteBatchNode::removeChild(pNode, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCARRAY_FOREACH(_spriteArrayCache, Obj)
|
||||
{
|
||||
((Sprite *)Obj)->setVisible(false);
|
||||
_reusedLetter->setBatchNode(nullptr);
|
||||
|
||||
int vaildIndex = 0;
|
||||
Sprite* child = nullptr;
|
||||
Rect uvRect;
|
||||
for (int ctr = 0; ctr < strLen; ++ctr)
|
||||
{
|
||||
if (_lettersInfo[ctr].def.validDefinition)
|
||||
{
|
||||
child = static_cast<Sprite*>( this->getChildByTag(ctr) );
|
||||
if (child)
|
||||
{
|
||||
uvRect.size.height = _lettersInfo[ctr].def.height;
|
||||
uvRect.size.width = _lettersInfo[ctr].def.width;
|
||||
uvRect.origin.x = _lettersInfo[ctr].def.U;
|
||||
uvRect.origin.y = _lettersInfo[ctr].def.V;
|
||||
|
||||
child->setTexture(&_fontAtlas->getTexture(_lettersInfo[ctr].def.textureID));
|
||||
child->setTextureRect(uvRect);
|
||||
}
|
||||
|
||||
updateSpriteWithLetterDefinition(_reusedLetter,_lettersInfo[ctr].def,&_fontAtlas->getTexture(_lettersInfo[ctr].def.textureID));
|
||||
_reusedLetter->setPosition(_lettersInfo[ctr].position);
|
||||
insertQuadFromSprite(_reusedLetter,vaildIndex++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,10 +298,8 @@ bool Label::computeAdvancesForString(unsigned short int *stringToRender)
|
|||
_advances = 0;
|
||||
}
|
||||
|
||||
Font &theFont = _fontAtlas->getFont();
|
||||
|
||||
int letterCount = 0;
|
||||
_advances = theFont.getAdvancesForTextUTF16(stringToRender, letterCount);
|
||||
_advances = _fontAtlas->getFont()->getAdvancesForTextUTF16(stringToRender, letterCount);
|
||||
|
||||
if(!_advances)
|
||||
return false;
|
||||
|
@ -295,17 +309,17 @@ bool Label::computeAdvancesForString(unsigned short int *stringToRender)
|
|||
|
||||
bool Label::setOriginalString(unsigned short *stringToSet)
|
||||
{
|
||||
if (_originalUTF8String)
|
||||
if (_originalUTF16String)
|
||||
{
|
||||
delete [] _originalUTF8String;
|
||||
_originalUTF8String = 0;
|
||||
delete [] _originalUTF16String;
|
||||
_originalUTF16String = 0;
|
||||
}
|
||||
|
||||
int newStringLenght = cc_wcslen(stringToSet);
|
||||
_originalUTF8String = new unsigned short int [newStringLenght + 1];
|
||||
memset(_originalUTF8String, 0, (newStringLenght + 1) * 2);
|
||||
memcpy(_originalUTF8String, stringToSet, (newStringLenght * 2));
|
||||
_originalUTF8String[newStringLenght] = 0;
|
||||
_originalUTF16String = new unsigned short int [newStringLenght + 1];
|
||||
memset(_originalUTF16String, 0, (newStringLenght + 1) * 2);
|
||||
memcpy(_originalUTF16String, stringToSet, (newStringLenght * 2));
|
||||
_originalUTF16String[newStringLenght] = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -313,65 +327,36 @@ bool Label::setOriginalString(unsigned short *stringToSet)
|
|||
bool Label::setCurrentString(unsigned short *stringToSet)
|
||||
{
|
||||
// set the new string
|
||||
if (_currentUTF8String)
|
||||
if (_currentUTF16String)
|
||||
{
|
||||
delete [] _currentUTF8String;
|
||||
_currentUTF8String = 0;
|
||||
delete [] _currentUTF16String;
|
||||
_currentUTF16String = 0;
|
||||
}
|
||||
//
|
||||
_currentUTF8String = stringToSet;
|
||||
_currentUTF16String = stringToSet;
|
||||
// compute the advances
|
||||
return computeAdvancesForString(stringToSet);
|
||||
}
|
||||
|
||||
void Label::resetCurrentString()
|
||||
{
|
||||
if ((!_currentUTF8String) && (!_originalUTF8String))
|
||||
if ((!_currentUTF16String) && (!_originalUTF16String))
|
||||
return;
|
||||
|
||||
// set the new string
|
||||
if (_currentUTF8String)
|
||||
if (_currentUTF16String)
|
||||
{
|
||||
delete [] _currentUTF8String;
|
||||
_currentUTF8String = 0;
|
||||
delete [] _currentUTF16String;
|
||||
_currentUTF16String = 0;
|
||||
}
|
||||
|
||||
int stringLenght = cc_wcslen(_originalUTF8String);
|
||||
_currentUTF8String = new unsigned short int [stringLenght + 1];
|
||||
memcpy(_currentUTF8String, _originalUTF8String, stringLenght * 2);
|
||||
_currentUTF8String[stringLenght] = 0;
|
||||
int stringLenght = cc_wcslen(_originalUTF16String);
|
||||
_currentUTF16String = new unsigned short int [stringLenght + 1];
|
||||
memcpy(_currentUTF16String, _originalUTF16String, stringLenght * 2);
|
||||
_currentUTF16String[stringLenght] = 0;
|
||||
|
||||
}
|
||||
|
||||
Sprite * Label::createNewSpriteFromLetterDefinition(const FontLetterDefinition &theDefinition, Texture2D *theTexture)
|
||||
{
|
||||
Rect uvRect;
|
||||
uvRect.size.height = theDefinition.height;
|
||||
uvRect.size.width = theDefinition.width;
|
||||
uvRect.origin.x = theDefinition.U;
|
||||
uvRect.origin.y = theDefinition.V;
|
||||
|
||||
SpriteFrame *pFrame = SpriteFrame::createWithTexture(theTexture, uvRect);
|
||||
Sprite *tempSprite = getSprite();
|
||||
|
||||
if (!tempSprite)
|
||||
return 0;
|
||||
|
||||
tempSprite->initWithSpriteFrame(pFrame);
|
||||
tempSprite->setAnchorPoint(Point(theDefinition.anchorX, theDefinition.anchorY));
|
||||
tempSprite->setBatchNode(this);
|
||||
|
||||
// Apply label properties
|
||||
tempSprite->setOpacityModifyRGB(_isOpacityModifyRGB);
|
||||
|
||||
// Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on
|
||||
tempSprite->updateDisplayedColor(_displayedColor);
|
||||
tempSprite->updateDisplayedOpacity(_displayedOpacity);
|
||||
|
||||
|
||||
return tempSprite;
|
||||
}
|
||||
|
||||
Sprite * Label::updateSpriteWithLetterDefinition(Sprite *spriteToUpdate, const FontLetterDefinition &theDefinition, Texture2D *theTexture)
|
||||
{
|
||||
if (!spriteToUpdate)
|
||||
|
@ -389,143 +374,93 @@ Sprite * Label::updateSpriteWithLetterDefinition(Sprite *spriteToUpdate, const F
|
|||
SpriteFrame *frame = SpriteFrame::createWithTexture(theTexture, uvRect);
|
||||
if (frame)
|
||||
{
|
||||
spriteToUpdate->setBatchNode(this);
|
||||
spriteToUpdate->setTexture(theTexture);
|
||||
spriteToUpdate->setDisplayFrame(frame);
|
||||
spriteToUpdate->setAnchorPoint(Point(theDefinition.anchorX, theDefinition.anchorY));
|
||||
spriteToUpdate->setBatchNode(this);
|
||||
}
|
||||
spriteToUpdate->setAnchorPoint(Point(theDefinition.anchorX, theDefinition.anchorY));
|
||||
}
|
||||
|
||||
return spriteToUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
Sprite * Label::getSpriteForLetter(unsigned short int newLetter)
|
||||
bool Label::recordLetterInfo(const cocos2d::Point& point,unsigned short int theChar, int spriteIndex)
|
||||
{
|
||||
if (!_fontAtlas)
|
||||
return 0;
|
||||
if (spriteIndex >= _lettersInfo.size())
|
||||
{
|
||||
LetterInfo tmpInfo;
|
||||
_lettersInfo.push_back(tmpInfo);
|
||||
}
|
||||
|
||||
_fontAtlas->getLetterDefinitionForChar(theChar, _lettersInfo[spriteIndex].def);
|
||||
_lettersInfo[spriteIndex].position = point;
|
||||
_lettersInfo[spriteIndex].contentSize.width = _lettersInfo[spriteIndex].def.width;
|
||||
_lettersInfo[spriteIndex].contentSize.height = _lettersInfo[spriteIndex].def.height;
|
||||
|
||||
return _lettersInfo[spriteIndex].def.validDefinition;
|
||||
}
|
||||
|
||||
bool Label::recordPlaceholderInfo(int spriteIndex)
|
||||
{
|
||||
if (spriteIndex >= _lettersInfo.size())
|
||||
{
|
||||
LetterInfo tmpInfo;
|
||||
_lettersInfo.push_back(tmpInfo);
|
||||
}
|
||||
|
||||
_lettersInfo[spriteIndex].def.validDefinition = false;
|
||||
|
||||
FontLetterDefinition tempDefinition;
|
||||
bool validDefinition = _fontAtlas->getLetterDefinitionForChar(newLetter, tempDefinition);
|
||||
if (validDefinition)
|
||||
{
|
||||
Sprite *newSprite = createNewSpriteFromLetterDefinition(tempDefinition, &_fontAtlas->getTexture(tempDefinition.textureID) );
|
||||
this->addChild(newSprite);
|
||||
return newSprite;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Sprite * Label::updateSpriteForLetter(Sprite *spriteToUpdate, unsigned short int newLetter)
|
||||
void Label::addChild(Node * child, int zOrder/* =0 */, int tag/* =0 */)
|
||||
{
|
||||
if (!spriteToUpdate || !_fontAtlas)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
FontLetterDefinition tempDefinition;
|
||||
bool validDefinition = _fontAtlas->getLetterDefinitionForChar(newLetter, tempDefinition);
|
||||
if (validDefinition)
|
||||
{
|
||||
Sprite *pNewSprite = updateSpriteWithLetterDefinition(spriteToUpdate, tempDefinition, &_fontAtlas->getTexture(tempDefinition.textureID) );
|
||||
return pNewSprite;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Label::moveAllSpritesToCache()
|
||||
{
|
||||
Object* pObj = NULL;
|
||||
CCARRAY_FOREACH(_spriteArray, pObj)
|
||||
{
|
||||
((Sprite *)pObj)->removeFromParent();
|
||||
_spriteArrayCache->addObject(pObj);
|
||||
}
|
||||
|
||||
_spriteArray->removeAllObjects();
|
||||
}
|
||||
|
||||
Sprite * Label::getSprite()
|
||||
{
|
||||
if (_spriteArrayCache->count())
|
||||
{
|
||||
Sprite *retSprite = static_cast<Sprite *>(_spriteArrayCache->getLastObject());
|
||||
_spriteArrayCache->removeLastObject();
|
||||
return retSprite;
|
||||
}
|
||||
else
|
||||
{
|
||||
Sprite *retSprite = new Sprite;
|
||||
return retSprite;
|
||||
}
|
||||
CCASSERT(0, "addChild: is not supported on Label.");
|
||||
}
|
||||
|
||||
///// PROTOCOL STUFF
|
||||
|
||||
Sprite * Label::getSpriteChild(int ID) const
|
||||
Sprite * Label::getLetter(int ID)
|
||||
{
|
||||
Object* pObj = NULL;
|
||||
CCARRAY_FOREACH(_spriteArray, pObj)
|
||||
{
|
||||
Sprite *pSprite = (Sprite *)pObj;
|
||||
if ( pSprite->getTag() == ID)
|
||||
if (ID < getStringLenght())
|
||||
{
|
||||
if(_lettersInfo[ID].def.validDefinition == false)
|
||||
return nullptr;
|
||||
|
||||
Sprite* sp = static_cast<Sprite*>(this->getChildByTag(ID));
|
||||
|
||||
if (!sp)
|
||||
{
|
||||
return pSprite;
|
||||
Rect uvRect;
|
||||
uvRect.size.height = _lettersInfo[ID].def.height;
|
||||
uvRect.size.width = _lettersInfo[ID].def.width;
|
||||
uvRect.origin.x = _lettersInfo[ID].def.U;
|
||||
uvRect.origin.y = _lettersInfo[ID].def.V;
|
||||
|
||||
sp = new Sprite();
|
||||
sp->initWithTexture(&_fontAtlas->getTexture(_lettersInfo[ID].def.textureID),uvRect);
|
||||
sp->setBatchNode(this);
|
||||
sp->setAnchorPoint(Point(_lettersInfo[ID].def.anchorX, _lettersInfo[ID].def.anchorY));
|
||||
sp->setPosition(_lettersInfo[ID].position);
|
||||
sp->setOpacity(_realOpacity);
|
||||
|
||||
this->addSpriteWithoutQuad(sp, ID, ID);
|
||||
sp->release();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Array* Label::getChildrenLetters() const
|
||||
{
|
||||
return _spriteArray;
|
||||
}
|
||||
|
||||
Sprite * Label::getSpriteForChar(unsigned short int theChar, int spriteIndexHint)
|
||||
{
|
||||
// ret sprite
|
||||
Sprite *retSprite = 0;
|
||||
|
||||
// look for already existing sprites
|
||||
retSprite = getSpriteChild(spriteIndexHint);
|
||||
|
||||
if (!retSprite)
|
||||
{
|
||||
retSprite = getSpriteForLetter(theChar);
|
||||
if (!retSprite)
|
||||
return 0;
|
||||
|
||||
if (retSprite)
|
||||
retSprite->setTag(spriteIndexHint);
|
||||
|
||||
_spriteArray->addObject(retSprite);
|
||||
return sp;
|
||||
}
|
||||
|
||||
// the sprite is now visible
|
||||
retSprite->setVisible(true);
|
||||
|
||||
// set the right texture letter to the sprite
|
||||
updateSpriteForLetter(retSprite, theChar);
|
||||
|
||||
// we are done here
|
||||
return retSprite;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
float Label::getLetterPosXLeft( Sprite* sp ) const
|
||||
float Label::getLetterPosXLeft( int index ) const
|
||||
{
|
||||
float scaleX = _scaleX;
|
||||
return sp->getPosition().x * scaleX - (sp->getContentSize().width * scaleX * sp->getAnchorPoint().x);
|
||||
return _lettersInfo[index].position.x * _scaleX - (_lettersInfo[index].contentSize.width * _scaleX * _lettersInfo[index].def.anchorX);
|
||||
}
|
||||
|
||||
float Label::getLetterPosXRight( Sprite* sp ) const
|
||||
float Label::getLetterPosXRight( int index ) const
|
||||
{
|
||||
float scaleX = _scaleX;
|
||||
return sp->getPosition().x * scaleX + (sp->getContentSize().width * scaleX * sp->getAnchorPoint().x);
|
||||
return _lettersInfo[index].position.x * _scaleX + (_lettersInfo[index].contentSize.width * _scaleX * _lettersInfo[index].def.anchorX);
|
||||
}
|
||||
|
||||
int Label::getCommonLineHeight() const
|
||||
|
@ -578,7 +513,7 @@ int Label::getAdvanceForChar(unsigned short c, int hintPositionInString) const
|
|||
|
||||
Rect Label::getRectForChar(unsigned short c) const
|
||||
{
|
||||
return _fontAtlas->getFont().getRectForChar(c);
|
||||
return _fontAtlas->getFont()->getRectForChar(c);
|
||||
}
|
||||
|
||||
// string related stuff
|
||||
|
@ -586,14 +521,14 @@ int Label::getStringNumLines() const
|
|||
{
|
||||
int quantityOfLines = 1;
|
||||
|
||||
unsigned int stringLen = _currentUTF8String ? cc_wcslen(_currentUTF8String) : 0;
|
||||
unsigned int stringLen = _currentUTF16String ? cc_wcslen(_currentUTF16String) : 0;
|
||||
if (stringLen == 0)
|
||||
return (-1);
|
||||
|
||||
// count number of lines
|
||||
for (unsigned int i = 0; i < stringLen - 1; ++i)
|
||||
{
|
||||
unsigned short c = _currentUTF8String[i];
|
||||
unsigned short c = _currentUTF16String[i];
|
||||
if (c == '\n')
|
||||
{
|
||||
quantityOfLines++;
|
||||
|
@ -605,17 +540,17 @@ int Label::getStringNumLines() const
|
|||
|
||||
int Label::getStringLenght() const
|
||||
{
|
||||
return _currentUTF8String ? cc_wcslen(_currentUTF8String) : 0;
|
||||
return _currentUTF16String ? cc_wcslen(_currentUTF16String) : 0;
|
||||
}
|
||||
|
||||
unsigned short Label::getCharAtStringPosition(int position) const
|
||||
{
|
||||
return _currentUTF8String[position];
|
||||
return _currentUTF16String[position];
|
||||
}
|
||||
|
||||
unsigned short * Label::getUTF8String() const
|
||||
{
|
||||
return _currentUTF8String;
|
||||
return _currentUTF16String;
|
||||
}
|
||||
|
||||
void Label::assignNewUTF8String(unsigned short *newString)
|
||||
|
@ -663,8 +598,7 @@ void Label::setOpacityModifyRGB(bool isOpacityModifyRGB)
|
|||
_isOpacityModifyRGB = isOpacityModifyRGB;
|
||||
if (_children && _children->count() != 0)
|
||||
{
|
||||
Object* child;
|
||||
CCARRAY_FOREACH(_children, child)
|
||||
for (auto child: *_children)
|
||||
{
|
||||
Node* pNode = static_cast<Node*>( child );
|
||||
if (pNode)
|
||||
|
@ -677,6 +611,7 @@ void Label::setOpacityModifyRGB(bool isOpacityModifyRGB)
|
|||
}
|
||||
}
|
||||
}
|
||||
_reusedLetter->setOpacityModifyRGB(true);
|
||||
}
|
||||
|
||||
unsigned char Label::getOpacity() const
|
||||
|
@ -692,7 +627,7 @@ unsigned char Label::getDisplayedOpacity() const
|
|||
void Label::setOpacity(GLubyte opacity)
|
||||
{
|
||||
_displayedOpacity = _realOpacity = opacity;
|
||||
|
||||
_reusedLetter->setOpacity(opacity);
|
||||
if( _cascadeOpacityEnabled ) {
|
||||
GLubyte parentOpacity = 255;
|
||||
RGBAProtocol* pParent = dynamic_cast<RGBAProtocol*>(_parent);
|
||||
|
@ -707,12 +642,28 @@ void Label::updateDisplayedOpacity(GLubyte parentOpacity)
|
|||
{
|
||||
_displayedOpacity = _realOpacity * parentOpacity/255.0;
|
||||
|
||||
Object* pObj;
|
||||
CCARRAY_FOREACH(_children, pObj)
|
||||
for (auto child: *_children)
|
||||
{
|
||||
Sprite *item = static_cast<Sprite*>( pObj );
|
||||
Sprite *item = static_cast<Sprite*>( child );
|
||||
item->updateDisplayedOpacity(_displayedOpacity);
|
||||
}
|
||||
V3F_C4B_T2F_Quad *quads = _textureAtlas->getQuads();
|
||||
int count = _textureAtlas->getTotalQuads();
|
||||
Color4B color4( _displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity );
|
||||
if (_isOpacityModifyRGB)
|
||||
{
|
||||
color4.r *= _displayedOpacity/255.0f;
|
||||
color4.g *= _displayedOpacity/255.0f;
|
||||
color4.b *= _displayedOpacity/255.0f;
|
||||
}
|
||||
for (int index = 0; index < count; ++index)
|
||||
{
|
||||
quads[index].bl.colors = color4;
|
||||
quads[index].br.colors = color4;
|
||||
quads[index].tl.colors = color4;
|
||||
quads[index].tr.colors = color4;
|
||||
_textureAtlas->updateQuad(&quads[index], index);
|
||||
}
|
||||
}
|
||||
|
||||
bool Label::isCascadeOpacityEnabled() const
|
||||
|
@ -738,7 +689,7 @@ const Color3B& Label::getDisplayedColor() const
|
|||
void Label::setColor(const Color3B& color)
|
||||
{
|
||||
_displayedColor = _realColor = color;
|
||||
|
||||
_reusedLetter->setColor(color);
|
||||
if( _cascadeColorEnabled )
|
||||
{
|
||||
Color3B parentColor = Color3B::WHITE;
|
||||
|
@ -757,12 +708,31 @@ void Label::updateDisplayedColor(const Color3B& parentColor)
|
|||
_displayedColor.g = _realColor.g * parentColor.g/255.0;
|
||||
_displayedColor.b = _realColor.b * parentColor.b/255.0;
|
||||
|
||||
Object* pObj;
|
||||
CCARRAY_FOREACH(_children, pObj)
|
||||
for (auto child: *_children)
|
||||
{
|
||||
Sprite *item = static_cast<Sprite*>( pObj );
|
||||
Sprite *item = static_cast<Sprite*>( child );
|
||||
item->updateDisplayedColor(_displayedColor);
|
||||
}
|
||||
|
||||
V3F_C4B_T2F_Quad *quads = _textureAtlas->getQuads();
|
||||
int count = _textureAtlas->getTotalQuads();
|
||||
Color4B color4( _displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity );
|
||||
|
||||
// special opacity for premultiplied textures
|
||||
if (_isOpacityModifyRGB)
|
||||
{
|
||||
color4.r *= _displayedOpacity/255.0f;
|
||||
color4.g *= _displayedOpacity/255.0f;
|
||||
color4.b *= _displayedOpacity/255.0f;
|
||||
}
|
||||
for (int index=0; index<count; ++index)
|
||||
{
|
||||
quads[index].bl.colors = color4;
|
||||
quads[index].br.colors = color4;
|
||||
quads[index].tl.colors = color4;
|
||||
quads[index].tr.colors = color4;
|
||||
_textureAtlas->updateQuad(&quads[index], index);
|
||||
}
|
||||
}
|
||||
|
||||
bool Label::isCascadeColorEnabled() const
|
||||
|
|
|
@ -82,12 +82,13 @@ public:
|
|||
virtual unsigned char getDisplayedOpacity() const override;
|
||||
|
||||
// CCLabelTextFormat protocol implementation
|
||||
virtual Sprite * getSpriteChild(int ID) const override;
|
||||
virtual Array * getChildrenLetters() const override;
|
||||
virtual Sprite * getSpriteForChar(unsigned short int theChar, int spriteIndexHint) override;
|
||||
virtual float getLetterPosXLeft( Sprite* sp ) const override;
|
||||
virtual float getLetterPosXRight( Sprite* sp ) const override;
|
||||
virtual std::vector<LetterInfo> *getLettersInfo() override { return &_lettersInfo; };
|
||||
virtual bool recordLetterInfo(const cocos2d::Point& point,unsigned short int theChar, int spriteIndex) override;
|
||||
virtual bool recordPlaceholderInfo(int spriteIndex) override;
|
||||
virtual float getLetterPosXLeft( int index ) const override;
|
||||
virtual float getLetterPosXRight( int index ) const override;
|
||||
|
||||
virtual Sprite * getLetter(int ID) override;
|
||||
|
||||
// font related stuff
|
||||
virtual int getCommonLineHeight() const override;
|
||||
|
@ -113,7 +114,8 @@ public:
|
|||
|
||||
// carloX
|
||||
const char * getString() const { return "not implemented"; }
|
||||
|
||||
void addChild(Node * child, int zOrder=0, int tag=0);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @js NA
|
||||
|
@ -129,29 +131,26 @@ private:
|
|||
|
||||
bool init();
|
||||
|
||||
void alignText();
|
||||
void hideAllLetters();
|
||||
void moveAllSpritesToCache();
|
||||
void alignText();
|
||||
|
||||
bool computeAdvancesForString(unsigned short int *stringToRender);
|
||||
bool setCurrentString(unsigned short *stringToSet);
|
||||
bool setOriginalString(unsigned short *stringToSet);
|
||||
void resetCurrentString();
|
||||
|
||||
Sprite * updateSpriteWithLetterDefinition(Sprite *spriteToUpdate, const FontLetterDefinition &theDefinition, Texture2D *theTexture);
|
||||
|
||||
Sprite * getSprite();
|
||||
Sprite * createNewSpriteFromLetterDefinition(const FontLetterDefinition &theDefinition, Texture2D *theTexture);
|
||||
Sprite * updateSpriteWithLetterDefinition(Sprite *spriteToUpdate, const FontLetterDefinition &theDefinition, Texture2D *theTexture);
|
||||
Sprite * getSpriteForLetter(unsigned short int newLetter);
|
||||
Sprite * updateSpriteForLetter(Sprite *spriteToUpdate, unsigned short int newLetter);
|
||||
|
||||
Array * _spriteArray;
|
||||
Array * _spriteArrayCache;
|
||||
//! used for optimization
|
||||
Sprite *_reusedLetter;
|
||||
std::vector<LetterInfo> _lettersInfo;
|
||||
|
||||
float _commonLineHeight;
|
||||
bool _lineBreakWithoutSpaces;
|
||||
float _width;
|
||||
TextHAlignment _alignment;
|
||||
unsigned short int * _currentUTF8String;
|
||||
unsigned short int * _originalUTF8String;
|
||||
unsigned short int * _currentUTF16String;
|
||||
unsigned short int * _originalUTF16String;
|
||||
Size * _advances;
|
||||
FontAtlas * _fontAtlas;
|
||||
Color3B _displayedColor;
|
||||
|
|
|
@ -24,19 +24,31 @@
|
|||
|
||||
#ifndef _CCLabelTextFormatProtocol_h_
|
||||
#define _CCLabelTextFormatProtocol_h_
|
||||
#include "CCFontAtlas.h"
|
||||
#include <vector>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
|
||||
struct LetterInfo
|
||||
{
|
||||
FontLetterDefinition def;
|
||||
|
||||
Point position;
|
||||
Size contentSize;
|
||||
bool visible;
|
||||
};
|
||||
|
||||
class CC_DLL LabelTextFormatProtocol
|
||||
{
|
||||
public:
|
||||
|
||||
virtual bool recordLetterInfo(const cocos2d::Point& point,unsigned short int theChar, int spriteIndex) = 0;
|
||||
virtual bool recordPlaceholderInfo(int spriteIndex) = 0;
|
||||
virtual std::vector<LetterInfo> *getLettersInfo() = 0;
|
||||
virtual float getLetterPosXLeft(int index) const = 0;
|
||||
virtual float getLetterPosXRight(int index) const = 0;
|
||||
// sprite related stuff
|
||||
virtual cocos2d::Sprite *getSpriteChild(int ID) const = 0;
|
||||
virtual cocos2d::Array *getChildrenLetters() const = 0;
|
||||
virtual cocos2d::Sprite *getSpriteForChar(unsigned short int theChar, int spriteIndexHint) = 0;
|
||||
virtual float getLetterPosXLeft(cocos2d::Sprite* sp) const = 0;
|
||||
virtual float getLetterPosXRight(cocos2d::Sprite* sp) const = 0;
|
||||
virtual cocos2d::Sprite *getLetter(int ID) = 0;
|
||||
|
||||
// font related stuff
|
||||
virtual int getCommonLineHeight() const = 0;
|
||||
|
|
|
@ -53,23 +53,24 @@ bool LabelTextFormatter::multilineText(LabelTextFormatProtocol *theLabel)
|
|||
float startOfLine = -1, startOfWord = -1;
|
||||
|
||||
int skip = 0;
|
||||
|
||||
Array* children = theLabel->getChildrenLetters();
|
||||
|
||||
for (int j = 0; j < children->count(); j++)
|
||||
{
|
||||
Sprite* characterSprite;
|
||||
unsigned int justSkipped = 0;
|
||||
|
||||
int strLen = theLabel->getStringLenght();
|
||||
std::vector<LetterInfo> *leterInfo = theLabel->getLettersInfo();
|
||||
int tIndex = 0;
|
||||
|
||||
for (int j = 0; j < strLen; j++)
|
||||
{
|
||||
LetterInfo* info = &leterInfo->at(j+skip);
|
||||
|
||||
unsigned int justSkipped = 0;
|
||||
|
||||
while (!(characterSprite = theLabel->getSpriteChild(j + skip + justSkipped)))
|
||||
while (info->def.validDefinition == false)
|
||||
{
|
||||
justSkipped++;
|
||||
info = &leterInfo->at( j+skip+justSkipped );
|
||||
}
|
||||
|
||||
skip += justSkipped;
|
||||
|
||||
if (!characterSprite->isVisible())
|
||||
continue;
|
||||
tIndex = j + skip;
|
||||
|
||||
if (i >= stringLength)
|
||||
break;
|
||||
|
@ -78,7 +79,7 @@ bool LabelTextFormatter::multilineText(LabelTextFormatProtocol *theLabel)
|
|||
|
||||
if (!isStartOfWord)
|
||||
{
|
||||
startOfWord = theLabel->getLetterPosXLeft( characterSprite );
|
||||
startOfWord = theLabel->getLetterPosXLeft( tIndex );
|
||||
isStartOfWord = true;
|
||||
}
|
||||
|
||||
|
@ -110,7 +111,7 @@ bool LabelTextFormatter::multilineText(LabelTextFormatProtocol *theLabel)
|
|||
|
||||
if (!startOfWord)
|
||||
{
|
||||
startOfWord = theLabel->getLetterPosXLeft( characterSprite );
|
||||
startOfWord = theLabel->getLetterPosXLeft( tIndex );
|
||||
isStartOfWord = true;
|
||||
}
|
||||
if (!startOfLine)
|
||||
|
@ -133,7 +134,7 @@ bool LabelTextFormatter::multilineText(LabelTextFormatProtocol *theLabel)
|
|||
}
|
||||
|
||||
// Out of bounds.
|
||||
if (theLabel->getLetterPosXRight( characterSprite ) - startOfLine > theLabel->getMaxLineWidth())
|
||||
if (theLabel->getLetterPosXRight( tIndex ) - startOfLine > theLabel->getMaxLineWidth())
|
||||
{
|
||||
if (!theLabel->breakLineWithoutSpace())
|
||||
{
|
||||
|
@ -171,7 +172,7 @@ bool LabelTextFormatter::multilineText(LabelTextFormatProtocol *theLabel)
|
|||
|
||||
if (!startOfWord)
|
||||
{
|
||||
startOfWord = theLabel->getLetterPosXLeft( characterSprite );
|
||||
startOfWord = theLabel->getLetterPosXLeft( tIndex );
|
||||
isStartOfWord = true;
|
||||
}
|
||||
if (!startOfLine)
|
||||
|
@ -222,9 +223,10 @@ bool LabelTextFormatter::alignText(LabelTextFormatProtocol *theLabel)
|
|||
int lineNumber = 0;
|
||||
int strLen = cc_wcslen(theLabel->getUTF8String());
|
||||
vector<unsigned short> lastLine;
|
||||
std::vector<LetterInfo> *leterInfo = theLabel->getLettersInfo();
|
||||
for (int ctr = 0; ctr <= strLen; ++ctr)
|
||||
{
|
||||
unsigned short int currentChar = theLabel->getCharAtStringPosition(ctr);
|
||||
unsigned short int currentChar = theLabel->getCharAtStringPosition(ctr);
|
||||
|
||||
if (currentChar == '\n' || currentChar == 0)
|
||||
{
|
||||
|
@ -240,11 +242,12 @@ bool LabelTextFormatter::alignText(LabelTextFormatProtocol *theLabel)
|
|||
int index = i + lineLength - 1 + lineNumber;
|
||||
if (index < 0) continue;
|
||||
|
||||
Sprite* lastChar = theLabel->getSpriteChild(index);
|
||||
if (lastChar == nullptr)
|
||||
if(currentChar == 0)
|
||||
continue;
|
||||
|
||||
lineWidth = lastChar->getPosition().x + lastChar->getContentSize().width / 2.0f;
|
||||
LetterInfo* info = &leterInfo->at( index );
|
||||
if(info->def.validDefinition == false)
|
||||
continue;
|
||||
lineWidth = info->position.x + info->contentSize.width /2.0f;
|
||||
|
||||
float shift = 0;
|
||||
switch (theLabel->getTextAlignment())
|
||||
|
@ -266,10 +269,11 @@ bool LabelTextFormatter::alignText(LabelTextFormatProtocol *theLabel)
|
|||
index = i + j + lineNumber;
|
||||
if (index < 0) continue;
|
||||
|
||||
Sprite* characterSprite = theLabel->getSpriteChild(index);
|
||||
|
||||
if (characterSprite)
|
||||
characterSprite->setPosition( characterSprite->getPosition() + Point(shift, 0.0f));
|
||||
info = &leterInfo->at( index );
|
||||
if(info)
|
||||
{
|
||||
info->position = info->position + Point(shift, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,15 +340,8 @@ bool LabelTextFormatter::createStringSprites(LabelTextFormatProtocol *theLabel)
|
|||
{
|
||||
nextFontPositionX = 0;
|
||||
nextFontPositionY -= commonLineHeight;
|
||||
continue;
|
||||
}
|
||||
|
||||
// get the sprite to this letter
|
||||
Sprite *letterSprite = theLabel->getSpriteForChar(c, i);
|
||||
|
||||
if (!letterSprite)
|
||||
{
|
||||
log("WARNING: can't find letter definition in font file for letter: %c", c);
|
||||
|
||||
theLabel->recordPlaceholderInfo(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -354,10 +351,13 @@ bool LabelTextFormatter::createStringSprites(LabelTextFormatProtocol *theLabel)
|
|||
|
||||
Point fontPos = Point((float)nextFontPositionX + charXOffset + charRect.size.width * 0.5f + kerningAmount,
|
||||
(float)nextFontPositionY + yOffset - charRect.size.height * 0.5f);
|
||||
|
||||
// set the sprite position
|
||||
letterSprite->setPosition(CC_POINT_PIXELS_TO_POINTS(fontPos));
|
||||
|
||||
|
||||
if( theLabel->recordLetterInfo(CC_POINT_PIXELS_TO_POINTS(fontPos),c,i) == false)
|
||||
{
|
||||
log("WARNING: can't find letter definition in font file for letter: %c", c);
|
||||
continue;
|
||||
}
|
||||
|
||||
// update kerning
|
||||
nextFontPositionX += charAdvance + kerningAmount;
|
||||
prev = c;
|
||||
|
|
|
@ -264,9 +264,9 @@ LabelFNTSpriteActions::LabelFNTSpriteActions()
|
|||
label->setAnchorPoint( Point(0.5f, 0.5f) );
|
||||
|
||||
|
||||
auto BChar = (Sprite*) label->getChildByTag(0);
|
||||
auto FChar = (Sprite*) label->getChildByTag(7);
|
||||
auto AChar = (Sprite*) label->getChildByTag(12);
|
||||
auto BChar = (Sprite*) label->getLetter(0);
|
||||
auto FChar = (Sprite*) label->getLetter(7);
|
||||
auto AChar = (Sprite*) label->getLetter(12);
|
||||
|
||||
|
||||
auto rotate = RotateBy::create(2, 360);
|
||||
|
@ -296,7 +296,7 @@ LabelFNTSpriteActions::LabelFNTSpriteActions()
|
|||
addChild(label2, 0, kTagBitmapAtlas2);
|
||||
label2->setPosition( Point(s.width/2.0f, 80) );
|
||||
|
||||
auto lastChar = (Sprite*) label2->getChildByTag(1);
|
||||
auto lastChar = (Sprite*) label2->getLetter(3);
|
||||
lastChar->runAction( rot_4ever->clone() );
|
||||
|
||||
schedule( schedule_selector(LabelFNTSpriteActions::step), 0.1f);
|
||||
|
|
Loading…
Reference in New Issue