Merge branch 'develop' into develop_nutty_modify_framework_for315

This commit is contained in:
CaiWenzhi 2014-03-05 21:20:26 +08:00
commit ad85d2c800
28 changed files with 784 additions and 519 deletions

View File

@ -7,11 +7,6 @@ import os, os.path
import shutil
from optparse import OptionParser
CPP_SAMPLES = ['testcpp']
LUA_SAMPLES = []
JSB_SAMPLES = []
ALL_SAMPLES = CPP_SAMPLES + LUA_SAMPLES + JSB_SAMPLES
def get_num_of_cpu():
''' The build process can be accelerated by running multiple concurrent job processes using the -j-option.
'''
@ -72,34 +67,6 @@ def select_toolchain_version():
print "Couldn't find the gcc toolchain."
exit(1)
def caculate_built_samples(args):
''' Compute the sampels to be built
'cpp' for short of all cpp tests
'lua' for short of all lua tests
'jsb' for short of all javascript tests
'''
if 'all' in args:
return ALL_SAMPLES
targets = []
if 'cpp' in args:
targets += CPP_SAMPLES
args.remove('cpp')
if 'lua' in args:
targets += LUA_SAMPLES
args.remove('lua')
if 'jsb' in args:
targets += JSB_SAMPLES
args.remove('jsb')
targets += args
# remove duplicate elements, for example
# python android-build.py cpp hellocpp
targets = set(targets)
return list(targets)
def do_build(cocos_root, ndk_root, app_android_root, ndk_build_param,sdk_root,android_platform,build_mode):
ndk_path = os.path.join(ndk_root, "ndk-build")
@ -157,33 +124,11 @@ def copy_resources(target, app_android_root):
if os.path.isdir(resources_dir):
copy_files(resources_dir, assets_dir)
# jsb samples should copy javascript files and resources(shared with cocos2d-html5)
if target in JSB_SAMPLES:
resources_dir = os.path.join(app_android_root, "../../../cocos/scripting/javascript/script")
copy_files(resources_dir, assets_dir)
if target == "testjavascript":
resources_dir = os.path.join(app_android_root, "../tests/")
copy_files(resources_dir, assets_dir)
# lua samples should copy lua script
if target in LUA_SAMPLES:
resources_dir = os.path.join(app_android_root, "../../../cocos/scripting/lua/script")
copy_files(resources_dir, assets_dir)
# TestLua shared resources with TestCpp
if target == "testlua":
resources_dir = os.path.join(app_android_root, "../../test-cpp/Resources")
copy_files(resources_dir, assets_dir)
def build_samples(target,ndk_build_param,android_platform,build_mode):
ndk_root = check_environment_variables()
sdk_root = None
select_toolchain_version()
build_targets = caculate_built_samples(target)
current_dir = os.path.dirname(os.path.realpath(__file__))
cocos_root = os.path.join(current_dir, "..")
@ -201,20 +146,10 @@ def build_samples(target,ndk_build_param,android_platform,build_mode):
elif build_mode != 'release':
build_mode = 'debug'
app_android_root = ''
for target in build_targets:
if target == 'testcpp':
app_android_root = os.path.join(cocos_root, 'tests/proj.android')
elif target == 'testlua':
app_android_root = os.path.join(cocos_root, 'tests/test-lua/proj.android')
elif target == 'testjavascript':
app_android_root = os.path.join(cocos_root, 'tests/test-javascript/proj.android')
else:
print 'unknown target: %s' % target
continue
app_android_root = os.path.join(cocos_root, 'tests/proj.android')
copy_resources(target, app_android_root)
do_build(cocos_root, ndk_root, app_android_root, ndk_build_param,sdk_root,android_platform,build_mode)
copy_resources(target, app_android_root)
do_build(cocos_root, ndk_root, app_android_root, ndk_build_param,sdk_root,android_platform,build_mode)
# -------------- main --------------
if __name__ == '__main__':
@ -223,26 +158,15 @@ if __name__ == '__main__':
usage = """
This script is mainy used for building tests built-in with cocos2d-x.
Usage: %prog [options] target
Usage: %prog [options] [testcpp]
Valid targets are: [testcpp|testlua|testjavascript]. You can combine them arbitrarily with a whitespace among two valid targets.
You can use [all|cpp|lua|jsb], to build all the tests, or all the c++ tests, or all the Lua tests, or all the JavaScript tests respectevely.
cpp = ['testcpp']
lua = ['testlua']
jsb = ['testjavascript']
all = cpp + lua + jsb // be careful with the all target, it may took a very long time to compile all the projects, do it under your own risk.
If you are new to cocos2d-x, I recommend you start with testcpp, testlua or testjavascript.
If you are new to cocos2d-x, I recommend you start with testcpp.
You can combine these targets like this:
//1. to build simplegame and assetsmanager
python android-build.py -p 10 testcpp testlua
python android-build.py -p 10
//2. to build testlua and all the jsb tests
python android-build.py -p 19 testlua jsb
Note: You should install ant to generate apk while building the andriod tests. But it is optional. You can generate apk with eclipse.
"""
@ -256,7 +180,7 @@ if __name__ == '__main__':
help='The build mode for java project,debug[default] or release. Get more information,please refer to http://developer.android.com/tools/building/building-cmdline.html')
(opts, args) = parser.parse_args()
if len(args) == 0:
if len(args) == 1 and cmp(args[0], 'testcpp') != 0:
parser.print_help()
else:
try:

View File

@ -28,11 +28,11 @@
#include "ccUTF8.h"
#include "CCDirector.h"
#define PAGE_WIDTH 1024
#define PAGE_HEIGHT 1024
NS_CC_BEGIN
const int FontAtlas::CacheTextureWidth = 1024;
const int FontAtlas::CacheTextureHeight = 1024;
FontAtlas::FontAtlas(Font &theFont) :
_font(&theFont),
_currentPageData(nullptr)
@ -44,28 +44,26 @@ _currentPageData(nullptr)
{
_currentPageLineHeight = _font->getFontMaxHeight();
_commonLineHeight = _currentPageLineHeight * 0.8f;
Texture2D * tex = new Texture2D;
auto texture = new Texture2D;
_currentPage = 0;
_currentPageOrigX = 0;
_currentPageOrigY = 0;
_letterPadding = 0;
_makeDistanceMap = fontTTf->isDistanceFieldEnabled();
if(_makeDistanceMap)
if(fontTTf->isDistanceFieldEnabled())
{
_commonLineHeight += 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];
memset(_currentPageData, 0, _currentPageDataSize);
addTexture(*tex,0);
tex->release();
}
else
{
_makeDistanceMap = false;
addTexture(texture,0);
texture->release();
}
}
@ -112,29 +110,75 @@ bool FontAtlas::prepareLetterDefinitions(unsigned short *utf16String)
return false;
FontFreeType* fontTTf = (FontFreeType*)_font;
std::unordered_map<unsigned short, FontLetterDefinition> fontDefs;
int length = cc_wcslen(utf16String);
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)
{
auto outIterator = _fontLetterDefinitions.find(utf16String[i]);
if (outIterator == _fontLetterDefinitions.end())
{
auto outIterator2 = fontDefs.find(utf16String[i]);
if(outIterator2 != fontDefs.end())
continue;
existNewLetter = true;
Rect tempRect;
FontLetterDefinition tempDef;
if (!fontTTf->getBBOXFotChar(utf16String[i], tempRect,tempDef.xAdvance))
auto bitmap = fontTTf->getGlyphBitmap(utf16String[i],bitmapWidth,bitmapHeight,tempRect,tempDef.xAdvance);
if (bitmap)
{
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.width = 0;
tempDef.height = 0;
@ -143,84 +187,29 @@ bool FontAtlas::prepareLetterDefinitions(unsigned short *utf16String)
tempDef.offsetX = 0;
tempDef.offsetY = 0;
tempDef.textureID = 0;
tempDef.xAdvance = 0;
_currentPageOrigX += 1;
}
else
{
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;
_fontLetterDefinitions[tempDef.letteCharUTF16] = tempDef;
}
}
Size _pageContentSize = Size(PAGE_WIDTH,PAGE_HEIGHT);
float scaleFactor = CC_CONTENT_SCALE_FACTOR();
float glyphWidth;
Texture2D::PixelFormat pixelFormat = Texture2D::PixelFormat::A8;
for(auto it = fontDefs.begin(); it != fontDefs.end(); it++)
if(existNewLetter)
{
if(it->second.validDefinition)
{
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;
_atlasTextures[_currentPage]->initWithData(_currentPageData, _currentPageDataSize, pixelFormat, CacheTextureWidth, CacheTextureHeight, contentSize );
}
if(fontDefs.size() > 0)
_atlasTextures[_currentPage]->initWithData(_currentPageData, _currentPageDataSize, pixelFormat, PAGE_WIDTH, PAGE_HEIGHT, _pageContentSize );
return true;
}
void FontAtlas::addTexture(Texture2D &texture, int slot)
void FontAtlas::addTexture(Texture2D *texture, int slot)
{
texture.retain();
_atlasTextures[slot] = &texture;
texture->retain();
_atlasTextures[slot] = texture;
}
Texture2D & FontAtlas::getTexture(int slot)
Texture2D* FontAtlas::getTexture(int slot)
{
return *(_atlasTextures[slot]);
return _atlasTextures[slot];
}
float FontAtlas::getCommonLineHeight() const

View File

@ -52,6 +52,8 @@ struct FontLetterDefinition
class CC_DLL FontAtlas : public Ref
{
public:
static const int CacheTextureWidth;
static const int CacheTextureHeight;
/**
* @js ctor
*/
@ -68,11 +70,11 @@ public:
bool prepareLetterDefinitions(unsigned short *utf16String);
inline const std::unordered_map<int, Texture2D*>& getTextures() const{ return _atlasTextures;}
void addTexture(Texture2D &texture, int slot);
void addTexture(Texture2D *texture, int slot);
float getCommonLineHeight() const;
void setCommonLineHeight(float newHeight);
Texture2D& getTexture(int slot);
Texture2D* getTexture(int slot);
const Font* getFont() const;
private:

View File

@ -35,17 +35,32 @@ NS_CC_BEGIN
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];
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)
{
font->setDistanceFieldEnabled(useDistanceField);
tempAtlas = font->createFontAtlas();
if (tempAtlas)
_atlasMap[atlasName] = tempAtlas;

View File

@ -37,7 +37,7 @@ NS_CC_BEGIN
class CC_DLL FontAtlasCache
{
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 * getFontAtlasCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap);

View File

@ -158,7 +158,7 @@ FontAtlas * FontCharMap::createFontAtlas()
}
}
tempAtlas->addTexture(*_texture,0);
tempAtlas->addTexture(_texture,0);
return tempAtlas;
}

View File

@ -816,7 +816,7 @@ FontAtlas * FontFNT::createFontAtlas()
return 0;
// add the texture
tempAtlas->addTexture(*tempTexture, 0);
tempAtlas->addTexture(tempTexture, 0);
// done
return tempAtlas;

View File

@ -30,6 +30,7 @@ THE SOFTWARE.
#include "CCFontFreeType.h"
#include "platform/CCFileUtils.h"
#include "edtaa3func.h"
#include FT_BBOX_H
NS_CC_BEGIN
@ -38,9 +39,9 @@ FT_Library FontFreeType::_FTlibrary;
bool FontFreeType::_FTInitialized = false;
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)
return nullptr;
@ -84,10 +85,21 @@ FT_Library FontFreeType::getFTLibrary()
return _FTlibrary;
}
FontFreeType::FontFreeType()
FontFreeType::FontFreeType(bool distanceFieldEnabled /* = false */,int outline /* = 0 */)
: _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)
@ -125,6 +137,10 @@ bool FontFreeType::createFontObject(const std::string &fontName, int fontSize)
FontFreeType::~FontFreeType()
{
if (_stroker)
{
FT_Stroker_Done(_stroker);
}
if (_fontRef)
{
FT_Done_Face(_fontRef);
@ -144,41 +160,6 @@ FontAtlas * FontFreeType::createFontAtlas()
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
{
if (!text)
@ -239,27 +220,162 @@ int FontFreeType::getFontMaxHeight() const
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)
return 0;
bool invalidChar = true;
unsigned char * ret = nullptr;
if (_distanceFieldEnabled)
do
{
if (FT_Load_Char(_fontRef,theChar,FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT))
return 0;
if (!_fontRef)
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
{
if (FT_Load_Char(_fontRef,theChar,FT_LOAD_RENDER))
return 0;
return ret;
}
}
unsigned char * FontFreeType::getGlyphBitmapWithOutline(unsigned short theChar, FT_BBox &bbox)
{
unsigned char* ret = nullptr;
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(&params, 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, &params);
ret = bmp.buffer;
}
FT_Done_Glyph(glyph);
}
}
}
outWidth = _fontRef->glyph->bitmap.width;
outHeight = _fontRef->glyph->bitmap.rows;
// return the pointer to the bitmap
return _fontRef->glyph->bitmap.buffer;
return ret;
}
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;
}
void FontFreeType::setDistanceFieldEnabled(bool distanceFieldEnabled)
void FontFreeType::renderCharAt(unsigned char *dest,int posX, int posY, unsigned char* bitmap,int bitmapWidth,int bitmapHeight)
{
_distanceFieldEnabled = distanceFieldEnabled;
}
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;
int iX = posX;
int iY = posY;
if (_distanceFieldEnabled)
{
unsigned char * out = makeDistanceMap(sourceBitmap,sourceWidth,sourceHeight);
auto distanceMap = makeDistanceMap(bitmap,bitmapWidth,bitmapHeight);
int iX = posX;
int iY = posY;
bitmapWidth += 2 * DistanceMapSpread;
bitmapHeight += 2 * DistanceMapSpread;
sourceWidth += 2 * DistanceMapSpread;
sourceHeight += 2 * DistanceMapSpread;
for (int y = 0; y < sourceHeight; ++y)
for (int y = 0; y < bitmapHeight; ++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) */
/*int index = (iX + ( iY * destSize )) * 3;
int index2 = (bitmap_y + x)*3;
destMemory[index] = out[index2];
destMemory[index + 1] = out[index2 + 1];
destMemory[index + 2] = out[index2 + 2];*/
dest[index] = out[index2];
dest[index + 1] = out[index2 + 1];
dest[index + 2] = out[index2 + 2];*/
//Single channel 8-bit output
destMemory[iX + ( iY * destSize )] = out[bitmap_y + x];
dest[iX + ( iY * FontAtlas::CacheTextureWidth )] = distanceMap[bitmap_y + x];
iX += 1;
}
@ -391,33 +493,50 @@ bool FontFreeType::renderCharAt(unsigned short int charToRender, int posX, int p
iX = posX;
iY += 1;
}
free(out);
return true;
free(distanceMap);
}
int iX = posX;
int iY = posY;
for (int y = 0; y < sourceHeight; ++y)
else if(_outlineSize > 0)
{
int bitmap_y = y * sourceWidth;
for (int x = 0; x < sourceWidth; ++x)
unsigned char tempChar;
for (int y = 0; y < bitmapHeight; ++y)
{
unsigned char cTemp = sourceBitmap[bitmap_y + x];
int bitmap_y = y * bitmapWidth;
// the final pixel
destMemory[(iX + ( iY * destSize ) )] = cTemp;
for (int x = 0; x < bitmapWidth; ++x)
{
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;
}
iX = posX;
iY += 1;
delete [] bitmap;
}
else
{
for (int y = 0; y < bitmapHeight; ++y)
{
int bitmap_y = y * bitmapWidth;
//everything good
return true;
for (int x = 0; x < bitmapWidth; ++x)
{
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

View File

@ -33,6 +33,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_STROKER_H
NS_CC_BEGIN
@ -41,25 +42,24 @@ class CC_DLL FontFreeType : public Font
public:
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();
void setDistanceFieldEnabled(bool 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 int * getHorizontalKerningForTextUTF16(unsigned short *text, int &outNumLetters) const override;
unsigned char * getGlyphBitmap(unsigned short theChar, int &outWidth, int &outHeight) const override;
virtual int getFontMaxHeight() const override;
unsigned char * getGlyphBitmap(unsigned short theChar, int &outWidth, int &outHeight, Rect &outRect,int &xAdvance);
bool getBBOXFotChar(unsigned short theChar, Rect &outRect,int &xAdvance) const;
virtual int getFontMaxHeight() const override;
protected:
FontFreeType();
FontFreeType(bool distanceFieldEnabled = false,int outline = 0);
virtual ~FontFreeType();
bool createFontObject(const std::string &fontName, int fontSize);
@ -69,13 +69,16 @@ private:
FT_Library getFTLibrary();
int getHorizontalKerningForChars(unsigned short firstChar, unsigned short secondChar) const;
unsigned char * getGlyphBitmapWithOutline(unsigned short theChar, FT_BBox &bbox);
static FT_Library _FTlibrary;
static bool _FTInitialized;
FT_Face _fontRef;
FT_Stroker _stroker;
std::string _fontName;
Data _ttfData;
bool _distanceFieldEnabled;
int _outlineSize;
};
NS_CC_END

View File

@ -59,8 +59,7 @@ const char* GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR = "ShaderPositi
const char* GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_NORMAL = "ShaderLabelNormol";
const char* GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_GLOW = "ShaderLabelGlow";
const char* GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_OUTLINE = "ShaderLabelOutline";
const char* GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_SHADOW = "ShaderLabelShadow";
const char* GLProgram::SHADER_NAME_LABEL_OUTLINE = "ShaderLabelOutline";
// uniform names

View File

@ -92,8 +92,7 @@ public:
static const char* SHADER_NAME_LABEL_DISTANCEFIELD_NORMAL;
static const char* SHADER_NAME_LABEL_DISTANCEFIELD_GLOW;
static const char* SHADER_NAME_LABEL_DISTANCEFIELD_OUTLINE;
static const char* SHADER_NAME_LABEL_DISTANCEFIELD_SHADOW;
static const char* SHADER_NAME_LABEL_OUTLINE;
// uniform names
static const char* UNIFORM_NAME_P_MATRIX;

View File

@ -34,10 +34,10 @@
#include "renderer/CCRenderer.h"
#include "CCFont.h"
#define DISTANCEFIELD_ATLAS_FONTSIZE 50
NS_CC_BEGIN
const int Label::DefultFontSize = 50;
Label* Label::create()
{
Label *ret = new Label();
@ -59,8 +59,6 @@ Label* Label::createWithTTF(const TTFConfig& ttfConfig, const std::string& text,
if (ret->setTTFConfig(ttfConfig))
{
if(ttfConfig.distanceFieldEnabled)
ret->setFontScale(1.0f * ttfConfig.fontSize / DISTANCEFIELD_ATLAS_FONTSIZE);
ret->setMaxLineWidth(lineSize);
ret->setString(text);
ret->autorelease();
@ -203,6 +201,7 @@ Label::Label(FontAtlas *atlas, TextHAlignment alignment, bool useDistanceField,b
, _fontScale(1.0f)
, _uniformEffectColor(0)
,_currNumLines(-1)
,_fontConfig(TTFConfig(""))
{
_cascadeColorEnabled = true;
_batchNodes.push_back(this);
@ -225,25 +224,49 @@ bool Label::init()
bool ret = true;
if(_fontAtlas)
{
ret = SpriteBatchNode::initWithTexture(_fontAtlas->getTexture(0), 30);
if (_reusedLetter == nullptr)
{
_reusedLetter = Sprite::createWithTexture(&_fontAtlas->getTexture(0));
_reusedLetter = Sprite::createWithTexture(_fontAtlas->getTexture(0));
_reusedLetter->setOpacityModifyRGB(_isOpacityModifyRGB);
_reusedLetter->retain();
_reusedLetter->setAnchorPoint(Point::ANCHOR_TOP_LEFT);
_reusedLetter->setBatchNode(this);
}
ret = SpriteBatchNode::initWithTexture(&_fontAtlas->getTexture(0), 30);
}
if (_useDistanceField)
setLabelEffect(LabelEffect::NORMAL,Color3B::BLACK);
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));
_currLabelEffect = LabelEffect::NORMAL;
initProgram();
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_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 */)
{
FontAtlas *oldAtlas = _fontAtlas;
@ -287,16 +310,32 @@ bool Label::initWithFontAtlas(FontAtlas* atlas,bool distanceFieldEnabled /* = fa
bool Label::setTTFConfig(const TTFConfig& ttfConfig)
{
FontAtlas *newAtlas = nullptr;
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);
FontAtlas *newAtlas = FontAtlasCache::getFontAtlasTTF(ttfConfig);
if (!newAtlas)
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 */)
@ -614,31 +653,68 @@ void Label::addChild(Node * child, int zOrder/* =0 */, int tag/* =0 */)
void Label::setLabelEffect(LabelEffect effect,const Color3B& effectColor)
{
if(_useDistanceField == false)
return;
_currLabelEffect = effect;
_effectColor = effectColor;
switch (_currLabelEffect)
switch (effect)
{
case cocos2d::LabelEffect::NORMAL:
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_NORMAL));
disableEffect();
break;
case cocos2d::LabelEffect::OUTLINE:
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_OUTLINE));
enableOutline(Color4B(effectColor));
break;
case cocos2d::LabelEffect::SHADOW:
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_SHADOW));
enableShadow(effectColor);
break;
case cocos2d::LabelEffect::GLOW:
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_GLOW));
enableGlow(effectColor);
break;
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)
@ -657,28 +733,79 @@ void Label::onDraw()
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);
}
else if(_currLabelEffect == LabelEffect::SHADOW && _shadowBlurRadius <= 0)
{
trans = true;
drawShadowWithoutBlur();
}
_shaderProgram->setUniformsForBuiltins(_modelViewTransform);
for(const auto &child: _children)
{
child->updateTransform();
if(child->getTag() >= 0)
child->updateTransform();
}
GL::blendFunc( _blendFunc.src, _blendFunc.dst );
for (const auto& batchNode:_batchNodes)
{
batchNode->getTextureAtlas()->drawQuads();
}
if (trans)
{
kmGLPopMatrix();
}
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)
{
_customCommand.init(_globalZOrder);
@ -693,26 +820,34 @@ void Label::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parent
return;
}
bool dirty = parentTransformUpdated || _transformUpdated;
if(dirty)
_modelViewTransform = transform(parentTransform);
_transformUpdated = false;
if (_currLabelEffect == LabelEffect::SHADOW && _shadowBlurRadius <= 0)
{
_parentTransform = parentTransform;
draw(renderer, _modelViewTransform, true);
}
else
{
bool dirty = parentTransformUpdated || _transformUpdated;
// 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);
if(dirty)
_modelViewTransform = transform(parentTransform);
_transformUpdated = false;
draw(renderer, _modelViewTransform, dirty);
// 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);
kmGLPopMatrix();
draw(renderer, _modelViewTransform, dirty);
kmGLPopMatrix();
}
setOrderOfArrival(0);
}
///// PROTOCOL STUFF
Sprite * Label::getLetter(int lettetIndex)
{
if (lettetIndex < getStringLenght())
@ -730,7 +865,7 @@ Sprite * Label::getLetter(int lettetIndex)
uvRect.origin.x = _lettersInfo[lettetIndex].def.U;
uvRect.origin.y = _lettersInfo[lettetIndex].def.V;
sp = Sprite::createWithTexture(&_fontAtlas->getTexture(_lettersInfo[lettetIndex].def.textureID),uvRect);
sp = Sprite::createWithTexture(_fontAtlas->getTexture(_lettersInfo[lettetIndex].def.textureID),uvRect);
sp->setBatchNode(this);
sp->setAnchorPoint(Point::ANCHOR_MIDDLE);
sp->setPosition(Point(_lettersInfo[lettetIndex].position.x+uvRect.size.width/2,_lettersInfo[lettetIndex].position.y-uvRect.size.height/2));
@ -800,8 +935,6 @@ bool Label::breakLineWithoutSpace() const
}
// RGBA protocol
bool Label::isOpacityModifyRGB() const
{
return _isOpacityModifyRGB;
@ -820,7 +953,7 @@ void Label::setOpacityModifyRGB(bool isOpacityModifyRGB)
void Label::setColor(const Color3B& color)
{
_reusedLetter->setColor(color);
_reusedLetter->setColor(color);
SpriteBatchNode::setColor(color);
}

View File

@ -57,20 +57,29 @@ typedef struct _ttfConfig
GlyphCollection glyphs;
const char *customGlyphs;
bool distanceFieldEnabled;
int outlineSize;
_ttfConfig(const char* filePath,int size = 36, const GlyphCollection& glyphCollection = GlyphCollection::NEHE,
const char *customGlyphCollection = nullptr,bool useDistanceField = false)
_ttfConfig(const char* filePath = "",int size = 36, const GlyphCollection& glyphCollection = GlyphCollection::NEHE,
const char *customGlyphCollection = nullptr,bool useDistanceField = false,int outline = 0)
:fontFilePath(filePath)
,fontSize(size)
,glyphs(glyphCollection)
,customGlyphs(customGlyphCollection)
,distanceFieldEnabled(useDistanceField)
{}
,outlineSize(outline)
{
if(outline > 0)
{
distanceFieldEnabled = false;
}
}
}TTFConfig;
class CC_DLL Label : public SpriteBatchNode, public LabelProtocol
{
public:
static const int DefultFontSize;
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);
@ -82,18 +91,33 @@ public:
static Label * createWithCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap);
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);
bool setCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap);
bool setCharMap(const std::string& plistFile);
virtual bool setCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap);
virtual bool setCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap);
virtual bool setCharMap(const std::string& plistFile);
virtual void setString(const std::string& text) override;
//only support for TTF
void setLabelEffect(LabelEffect effect,const Color3B& effectColor);
CC_DEPRECATED_ATTRIBUTE 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);
CC_DEPRECATED_ATTRIBUTE void setWidth(float width) { setMaxLineWidth(width);}
@ -112,29 +136,29 @@ public:
virtual Sprite * getLetter(int lettetIndex);
// font related stuff
virtual int getCommonLineHeight() const;
int getCommonLineHeight() const;
// string related stuff
virtual int getStringNumLines() const;
virtual int getStringLenght() const;
virtual TextHAlignment getTextAlignment() const;
int getStringNumLines() const;
int getStringLenght() const;
TextHAlignment getTextAlignment() const;
// label related stuff
virtual float getMaxLineWidth() const;
virtual bool breakLineWithoutSpace() const;
CC_DEPRECATED_ATTRIBUTE float getWidth() const { getMaxLineWidth(); }
float getMaxLineWidth() const;
bool breakLineWithoutSpace() const;
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 void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
virtual void onDraw();
virtual FontAtlas* getFontAtlas() const {return _fontAtlas;}
FontAtlas* getFontAtlas() const {return _fontAtlas;}
private:
protected:
struct LetterInfo
{
FontLetterDefinition def;
@ -150,19 +174,19 @@ private:
* @js 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
virtual bool recordLetterInfo(const cocos2d::Point& point,const FontLetterDefinition& letterDef, int spriteIndex);
virtual bool recordPlaceholderInfo(int spriteIndex);
bool recordLetterInfo(const cocos2d::Point& point,const FontLetterDefinition& letterDef, int spriteIndex);
bool recordPlaceholderInfo(int spriteIndex);
void setFontScale(float fontScale);
bool init();
virtual bool init();
void alignText();
virtual void alignText();
bool computeHorizontalKernings(unsigned short int *stringToRender);
bool setCurrentString(unsigned short *stringToSet);
@ -174,6 +198,10 @@ private:
virtual void updateColor() override;
virtual void initProgram();
void drawShadowWithoutBlur();
//! used for optimization
Sprite *_reusedLetter;
Rect _reusedRect;
@ -204,6 +232,19 @@ private:
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;
};

View File

@ -45,8 +45,7 @@ enum {
kShaderType_PositionLengthTexureColor,
kShaderType_LabelDistanceFieldNormal,
kShaderType_LabelDistanceFieldGlow,
kShaderType_LabelDistanceFieldOutline,
kShaderType_LabelDistanceFieldShadow,
kShaderType_LabelOutline,
kShaderType_MAX,
};
@ -177,12 +176,8 @@ void ShaderCache::loadDefaultShaders()
_programs.insert( std::make_pair(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_GLOW, p) );
p = new GLProgram();
loadDefaultShader(p, kShaderType_LabelDistanceFieldOutline);
_programs.insert( std::make_pair(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_OUTLINE, p) );
p = new GLProgram();
loadDefaultShader(p, kShaderType_LabelDistanceFieldShadow);
_programs.insert( std::make_pair(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_SHADOW, p) );
loadDefaultShader(p, kShaderType_LabelOutline);
_programs.insert( std::make_pair(GLProgram::SHADER_NAME_LABEL_OUTLINE, p) );
}
void ShaderCache::reloadDefaultShaders()
@ -260,13 +255,9 @@ void ShaderCache::reloadDefaultShaders()
p->reset();
loadDefaultShader(p, kShaderType_LabelDistanceFieldGlow);
p = getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_OUTLINE);
p = getProgram(GLProgram::SHADER_NAME_LABEL_OUTLINE);
p->reset();
loadDefaultShader(p, kShaderType_LabelDistanceFieldOutline);
p = getProgram(GLProgram::SHADER_NAME_LABEL_DISTANCEFIELD_SHADOW);
p->reset();
loadDefaultShader(p, kShaderType_LabelDistanceFieldShadow);
loadDefaultShader(p, kShaderType_LabelOutline);
}
void ShaderCache::loadDefaultShader(GLProgram *p, int type)
@ -362,16 +353,8 @@ void ShaderCache::loadDefaultShader(GLProgram *p, int type)
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORDS);
break;
case kShaderType_LabelDistanceFieldOutline:
p->initWithByteArrays(ccLabelDistanceFieldOutline_vert, ccLabelDistanceFieldOutline_frag);
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR);
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORDS);
break;
case kShaderType_LabelDistanceFieldShadow:
p->initWithByteArrays(ccLabelDistanceFieldShadow_vert, ccLabelDistanceFieldShadow_frag);
case kShaderType_LabelOutline:
p->initWithByteArrays(ccLabelOutline_vert, ccLabelOutline_frag);
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR);

View File

@ -18,7 +18,7 @@ void main() \n\
//float width = fwidth(dist); \n\
//assign width for constant will lead to a little bit fuzzy,it's temporary measure.\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\
} \n\
";

View File

@ -6,19 +6,19 @@ precision lowp float; \n\
varying vec4 v_fragmentColor; \n\
varying vec2 v_texCoord; \n\
uniform sampler2D CC_Texture0; \n\
uniform vec3 v_effectColor; \n\
uniform vec4 v_effectColor; \n\
\n\
void main() \n\
{ \n\
float dist = texture2D(CC_Texture0, v_texCoord).a; \n\
//todo:Implementation 'fwidth' for glsl 1.0 \n\
//float width = fwidth(dist); \n\
//assign width for constant will lead to a little bit fuzzy,it's temporary measure.\n\
float width = 0.04; \n\
float alpha = smoothstep(0.5-width, 0.5+width, dist); \n\
//outline \n\
float mu = smoothstep(0.545-width, 0.545+width, dist); \n\
vec3 rgb = v_effectColor*(1.0-mu) + v_fragmentColor.rgb*mu; \n\
gl_FragColor = vec4(rgb, max(alpha,mu)); \n\
} \n\
void main() \n\
{ \n\
vec4 sample = texture2D(CC_Texture0, v_texCoord); \n\
float fontAlpha = sample.a; \n\
float outlineAlpha = sample.r; \n\
if (outlineAlpha > 0.0){ \n\
vec3 color = v_fragmentColor.rgb * fontAlpha + v_effectColor.rgb * (1.0 - fontAlpha);\n\
gl_FragColor = vec4( color,max(fontAlpha,outlineAlpha)*v_fragmentColor.a); \n\
} \n\
else { \n\
discard; \n\
} \n\
} \n\
";

View File

@ -91,14 +91,9 @@ const GLchar * ccLabelDistanceFieldGlow_frag =
const GLchar * ccLabelDistanceFieldGlow_vert =
#include "ccShader_Label_vert.h"
const GLchar * ccLabelDistanceFieldOutline_frag =
const GLchar * ccLabelOutline_frag =
#include "ccShader_Label_frag_outline.h"
const GLchar * ccLabelDistanceFieldOutline_vert =
#include "ccShader_Label_vert.h"
const GLchar * ccLabelDistanceFieldShadow_frag =
#include "ccShader_Label_frag_shadow.h"
const GLchar * ccLabelDistanceFieldShadow_vert =
const GLchar * ccLabelOutline_vert =
#include "ccShader_Label_vert.h"
NS_CC_END

View File

@ -68,11 +68,8 @@ extern CC_DLL const GLchar * ccLabelDistanceFieldNormal_vert;
extern CC_DLL const GLchar * ccLabelDistanceFieldGlow_frag;
extern CC_DLL const GLchar * ccLabelDistanceFieldGlow_vert;
extern CC_DLL const GLchar * ccLabelDistanceFieldOutline_frag;
extern CC_DLL const GLchar * ccLabelDistanceFieldOutline_vert;
extern CC_DLL const GLchar * ccLabelDistanceFieldShadow_frag;
extern CC_DLL const GLchar * ccLabelDistanceFieldShadow_vert;
extern CC_DLL const GLchar * ccLabelOutline_frag;
extern CC_DLL const GLchar * ccLabelOutline_vert;
extern CC_DLL const GLchar * ccExSwitchMask_frag;

View File

@ -194,11 +194,11 @@ bool ControlSwitchSprite::initWithMaskSprite(
clipper->setStencil(_clipperStencil);
clipper->addChild(thumbSprite);
clipper->addChild(onSprite);
clipper->addChild(offSprite);
clipper->addChild(onLabel);
clipper->addChild(offLabel);
clipper->addChild(thumbSprite);
addChild(clipper);
@ -263,24 +263,6 @@ void ControlSwitchSprite::needsLayout()
_offSprite->getContentSize().height / 2));
}
RenderTexture *rt = RenderTexture::create((int)_maskTexture->getContentSize().width, (int)_maskTexture->getContentSize().height);
rt->begin();
_onSprite->visit();
_offSprite->visit();
if (_onLabel)
{
_onLabel->visit();
}
if (_offLabel)
{
_offLabel->visit();
}
rt->end();
setTexture(rt->getSprite()->getTexture());
setFlippedY(true);
}

2
plugin

@ -1 +1 @@
Subproject commit 3c325c4198e0e65764602a60c807d7e07e26f066
Subproject commit d177da9b541ab1b436476f9caa057766d485d9c3

View File

@ -177,8 +177,6 @@ Box2DView* Box2DView::viewWithEntryID(int entryId)
bool Box2DView::initWithEntryID(int entryId)
{
schedule( schedule_selector(Box2DView::tick) );
m_entry = g_testEntries + entryId;
m_test = m_entry->createFcn();
@ -202,11 +200,6 @@ std::string Box2DView::title() const
return std::string(m_entry->name);
}
void Box2DView::tick(float dt)
{
m_test->Step(&settings);
}
void Box2DView::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{
Layer::draw(renderer, transform, transformUpdated);
@ -222,6 +215,7 @@ void Box2DView::onDraw()
kmGLGetMatrix(KM_GL_MODELVIEW, &oldMat);
kmGLLoadMatrix(&_modelViewTransform);
GL::enableVertexAttribs( cocos2d::GL::VERTEX_ATTRIB_FLAG_POSITION );
m_test->Step(&settings);
m_test->m_world->DrawDebugData();
CHECK_GL_ERROR_DEBUG();

View File

@ -41,7 +41,6 @@ public:
bool initWithEntryID(int entryId);
std::string title() const;
void tick(float dt);
virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
// virtual void registerWithTouchDispatcher();

View File

@ -263,11 +263,6 @@ std::string TestFilenameLookup::title() const
return "FileUtils: filename lookup";
}
std::string TestFilenameLookup::subtitle() const
{
return "See the console";
}
//#pragma mark - TestIsFileExist
void TestIsFileExist::onEnter()

View File

@ -59,7 +59,6 @@ public:
virtual void onEnter() override;
virtual void onExit() override;
virtual std::string title() const override;
virtual std::string subtitle() const override;
};
class TestIsFileExist : public FileUtilsDemo

View File

@ -2,6 +2,8 @@
#include "../testResource.h"
#include "renderer/CCRenderer.h"
using namespace ui;
enum {
kTagTileMap = 1,
kTagSpriteManager = 1,
@ -68,7 +70,8 @@ static std::function<Layer*()> createFunctions[] =
CL(LabelTTFUnicodeNew),
CL(LabelBMFontTestNew),
CL(LabelTTFDistanceField),
CL(LabelTTFDistanceFieldEffect),
CL(LabelOutlineAndGlowTest),
CL(LabelShadowTest),
CL(LabelCharMapTest),
CL(LabelCharMapColorTest),
CL(LabelCrashTest),
@ -1292,7 +1295,7 @@ std::string LabelTTFDistanceField::subtitle() const
return "Testing rendering base on DistanceField";
}
LabelTTFDistanceFieldEffect::LabelTTFDistanceFieldEffect()
LabelOutlineAndGlowTest::LabelOutlineAndGlowTest()
{
auto size = Director::getInstance()->getWinSize();
@ -1302,36 +1305,115 @@ LabelTTFDistanceFieldEffect::LabelTTFDistanceFieldEffect()
TTFConfig ttfConfig("fonts/arial.ttf", 80, GlyphCollection::DYNAMIC,nullptr,true);
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->setAnchorPoint(Point::ANCHOR_MIDDLE);
label1->setLabelEffect(LabelEffect::GLOW,Color3B::YELLOW);
label1->enableGlow(Color3B::YELLOW);
addChild(label1);
ttfConfig.outlineSize = 1;
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->setAnchorPoint(Point::ANCHOR_MIDDLE);
label2->setLabelEffect(LabelEffect::OUTLINE,Color3B::BLUE);
label2->enableOutline(Color4B::BLUE);
addChild(label2);
auto label3 = Label::createWithTTF(ttfConfig,"Shadow", TextHAlignment::CENTER, size.width);
label3->setPosition( Point(size.width/2, size.height*0.35f) );
ttfConfig.outlineSize = 2;
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->setAnchorPoint(Point::ANCHOR_MIDDLE);
label3->setLabelEffect(LabelEffect::SHADOW,Color3B::BLACK);
label3->enableOutline(Color4B::BLUE);
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()

View File

@ -4,6 +4,7 @@
#include "../testBasic.h"
#include "../BaseTest.h"
#include "renderer/CCCustomCommand.h"
#include "gui/CocosGUI.h"
class AtlasDemoNew : public BaseTest
@ -349,17 +350,33 @@ public:
virtual std::string subtitle() const override;
};
class LabelTTFDistanceFieldEffect : public AtlasDemoNew
class LabelOutlineAndGlowTest : public AtlasDemoNew
{
public:
CREATE_FUNC(LabelTTFDistanceFieldEffect);
CREATE_FUNC(LabelOutlineAndGlowTest);
LabelTTFDistanceFieldEffect();
LabelOutlineAndGlowTest();
virtual std::string title() 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
{
public:

View File

@ -700,17 +700,15 @@ bool ShaderRetroEffect::init()
p->link();
p->updateUniforms();
auto director = Director::getInstance();
auto s = director->getWinSize();
_label = LabelBMFont::create("RETRO EFFECT", "fonts/west_england-64.fnt");
_label = Label::createWithBMFont("fonts/west_england-64.fnt","RETRO EFFECT");
_label->setAnchorPoint(Point::ANCHOR_MIDDLE);
_label->setShaderProgram(p);
p->release();
_label->setPosition(Point(s.width/2,s.height/2));
addChild(_label);
@ -725,10 +723,10 @@ bool ShaderRetroEffect::init()
void ShaderRetroEffect::update(float dt)
{
_accum += dt;
int i=0;
for(const auto &sprite : _label->getChildren()) {
i++;
int letterCount = _label->getStringLenght();
for (int i = 0; i < letterCount; ++i)
{
auto sprite = _label->getLetter(i);
auto oldPosition = sprite->getPosition();
sprite->setPosition(Point( oldPosition.x, sinf( _accum * 2 + i/2.0) * 20 ));

View File

@ -106,7 +106,7 @@ public:
bool init();
void update(float dt);
protected:
LabelBMFont* _label;
Label* _label;
float _accum;
};