axmol/cocos/2d/CCFontAtlas.cpp

243 lines
7.0 KiB
C++
Raw Normal View History

2013-07-20 01:33:26 +08:00
//
// CCFontAtlas.cpp
// cocos2d_libs
//
// Created by Carlo Morgantini on 7/18/13.
//
//
#include "cocos2d.h"
#include "CCFontAtlas.h"
#include "CCFont.h"
#include "CCFontFreeType.h"
2013-07-20 01:33:26 +08:00
NS_CC_BEGIN
FontAtlas::FontAtlas(Font &theFont) :
2013-10-31 17:52:22 +08:00
_font(&theFont),
_currentPageData(nullptr)
{
2013-10-31 17:52:22 +08:00
_font->retain();
2013-10-31 17:52:22 +08:00
FontFreeType* fontTTf = dynamic_cast<FontFreeType*>(_font);
if (fontTTf && fontTTf->isDynamicGlyphCollection())
{
2013-10-31 17:52:22 +08:00
_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);
2013-10-31 17:52:22 +08:00
tex->release();
}
}
FontAtlas::~FontAtlas()
{
2013-10-31 17:52:22 +08:00
_font->release();
relaseTextures();
2013-10-31 17:52:22 +08:00
delete []_currentPageData;
}
void FontAtlas::relaseTextures()
{
for( auto &item: _atlasTextures)
{
2013-08-06 07:41:23 +08:00
item.second->release();
}
}
2013-08-06 08:49:20 +08:00
void FontAtlas::addLetterDefinition(const FontLetterDefinition &letterDefinition)
2013-07-20 01:33:26 +08:00
{
_fontLetterDefinitions[letterDefinition.letteCharUTF16] = letterDefinition;
}
2013-08-06 08:49:20 +08:00
bool FontAtlas::getLetterDefinitionForChar(unsigned short letteCharUTF16, FontLetterDefinition &outDefinition)
2013-07-20 01:33:26 +08:00
{
auto outIterator = _fontLetterDefinitions.find(letteCharUTF16);
2013-08-06 08:49:20 +08:00
if (outIterator != _fontLetterDefinitions.end())
{
2013-08-06 08:49:20 +08:00
outDefinition = (*outIterator).second;
return true;
}
else
{
2013-08-06 08:49:20 +08:00
return false;
}
2013-07-20 01:33:26 +08:00
}
bool FontAtlas::prepareLetterDefinitions(unsigned short *utf16String)
{
if(_currentPageData == nullptr)
return false;
2013-10-31 17:52:22 +08:00
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++;
2013-10-31 17:52:22 +08:00
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
2013-10-31 17:52:22 +08:00
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;
}
2013-08-06 08:49:20 +08:00
void FontAtlas::addTexture(Texture2D &texture, int slot)
2013-07-20 01:33:26 +08:00
{
2013-08-06 08:49:20 +08:00
texture.retain();
_atlasTextures[slot] = &texture;
2013-07-20 01:33:26 +08:00
}
2013-08-06 08:49:20 +08:00
Texture2D & FontAtlas::getTexture(int slot)
2013-07-20 01:33:26 +08:00
{
2013-08-06 08:49:20 +08:00
return *(_atlasTextures[slot]);
2013-07-20 01:33:26 +08:00
}
2013-09-13 11:46:46 +08:00
float FontAtlas::getCommonLineHeight() const
{
return _commonLineHeight;
}
void FontAtlas::setCommonLineHeight(float newHeight)
{
_commonLineHeight = newHeight;
}
2013-10-31 17:52:22 +08:00
const Font * FontAtlas::getFont() const
{
return _font;
}
2013-07-20 01:33:26 +08:00
NS_CC_END