Add Label Overflow and wrap option.

Squashed commit of the following:

commit 7176582def3686f78701f92ead4d0976bccd115d
Author: zilongshanren <guanghui8827@126.com>
Date:   Thu Nov 19 10:30:54 2015 +0800

    add char map font test

commit 7ea7c251ff549e4a74d5c5c3faa49893fe5defc4
Author: zilongshanren <guanghui8827@126.com>
Date:   Wed Nov 18 15:00:17 2015 +0800

    system font overflow is not supported

commit a02fe0c7f94692b95a0bfd6f194a94c4519cee3a
Author: zilongshanren <guanghui8827@126.com>
Date:   Wed Nov 18 11:04:15 2015 +0800

    add system font test

commit eb098da8b16f485c86929a9b2ba00a64068264e9
Author: zilongshanren <guanghui8827@126.com>
Date:   Tue Nov 17 10:29:35 2015 +0800

    Finish resize height mode

commit ca78ba35abdbacc23bf6f8315454ec0a356a6aca
Author: zilongshanren <guanghui8827@126.com>
Date:   Mon Nov 16 11:01:27 2015 +0800

    fix wrap issue

commit baf1a5e0dc3a08da0a13500aea5afc82017b054a
Author: zilongshanren <guanghui8827@126.com>
Date:   Sat Nov 14 08:28:57 2015 +0800

    horizontal shrink still has a issue

commit 7e8abc0990cdf299d23c8072c5c1d4aa561bf798
Author: zilongshanren <guanghui8827@126.com>
Date:   Fri Nov 13 11:42:34 2015 +0800

    finish shrink without wrap

commit c9c45bd1f304ba00a6f9a274fa5631659a075bc1
Author: zilongshanren <guanghui8827@126.com>
Date:   Fri Nov 13 10:09:46 2015 +0800

    update shrink

commit ad82010ea846679e4d1a09f5127be29ae2e6adae
Author: zilongshanren <guanghui8827@126.com>
Date:   Thu Nov 12 17:55:15 2015 +0800

    refactor shrink logic

commit effc1ee1cd9f06eaa4f46dd5c2a1401f6a285af6
Author: zilongshanren <guanghui8827@126.com>
Date:   Wed Nov 11 18:25:34 2015 +0800

    add resize overflow type

commit 194d552adc2a4ba2c439eff969b082556315e0ae
Author: zilongshanren <guanghui8827@126.com>
Date:   Wed Nov 11 11:49:51 2015 +0800

    no wrap, shrink is working.

commit e2222ef14d5392817bd727895b3c2caec5ce4faf
Author: zilongshanren <guanghui8827@126.com>
Date:   Tue Nov 10 16:16:27 2015 +0800

    add overflow type to label.

    1. optimize the testcase

commit b65e2de4bfb3cb86a0d0cfa118be891a3f9fe858
Author: zilongshanren <guanghui8827@126.com>
Date:   Mon Nov 9 17:22:34 2015 +0800

    finish bmfont wrap by char

commit f339ff0309dc9e2ca2871f03f4551d329afce5e1
Author: zilongshanren <guanghui8827@126.com>
Date:   Mon Nov 9 17:04:51 2015 +0800

    finish bmfont wrap by word

commit 4c8edc65204a1294ac81315e72f1299acbdf43c0
Author: zilongshanren <guanghui8827@126.com>
Date:   Mon Nov 9 11:29:21 2015 +0800

    add BMFont size support

commit 3282481bda9dcb0f88b41f2568f7e5c856af6d53
Author: zilongshanren <guanghui8827@126.com>
Date:   Mon Nov 9 09:58:01 2015 +0800

    add font size support for BMFONT

commit 0c8e2a0374983625507a183cb2eb53a0b1709e25
Author: zilongshanren <guanghui8827@126.com>
Date:   Fri Nov 6 16:36:27 2015 +0800

    add toggle wrap option.

    1. make hirozontal clamp working

commit 19dcd3e80a34c54b20934d08937eb270e689a7db
Author: zilongshanren <guanghui8827@126.com>
Date:   Fri Nov 6 15:12:59 2015 +0800

    tweak label layout

commit e36a40babf4817ea7e9830614ac7560f2e69c583
Author: zilongshanren <guanghui8827@126.com>
Date:   Thu Nov 5 11:11:02 2015 +0800

    finish the test skeleton

commit a144a3a5d388d15c4f37cbfc12563eccabffb8e1
Author: zilongshanren <guanghui8827@126.com>
Date:   Wed Nov 4 16:38:54 2015 +0800

    add setFontSize api to label.

    1. add new chinese-english bmfont
    2. beautify base test

commit b22551c9eb3738fbb1c38ae4a3bfd07a202dcaf0
Author: zilongshanren <guanghui8827@126.com>
Date:   Wed Nov 4 11:27:18 2015 +0800

    add label layout test skeleton
This commit is contained in:
zilongshanren 2015-11-19 16:06:13 +08:00
parent bf08b5b16d
commit ccdb2a75f9
11 changed files with 1503 additions and 106 deletions

View File

@ -157,6 +157,19 @@ void FontAtlas::addLetterDefinition(char16_t utf16Char, const FontLetterDefiniti
_letterDefinitions[utf16Char] = letterDefinition;
}
void FontAtlas::scaleFontLetterDefinition(float scaleFactor)
{
for (auto&& fontDefinition : _letterDefinitions) {
FontLetterDefinition letterDefinition = fontDefinition.second;
letterDefinition.width *= scaleFactor;
letterDefinition.height *= scaleFactor;
letterDefinition.offsetX *= scaleFactor;
letterDefinition.offsetY *= scaleFactor;
letterDefinition.xAdvance *= scaleFactor;
_letterDefinitions[fontDefinition.first] = letterDefinition;
}
}
bool FontAtlas::getLetterDefinitionForChar(char16_t utf16Char, FontLetterDefinition &letterDefinition)
{
auto outIterator = _letterDefinitions.find(utf16Char);

View File

@ -115,6 +115,13 @@ protected:
void conversionU16TOGB2312(const std::u16string& u16Text, std::unordered_map<unsigned short, unsigned short>& charCodeMap);
/**
* Scale each font letter by scaleFactor.
*
* @param scaleFactor A float scale factor for scaling font letter info.
*/
void scaleFontLetterDefinition(float scaleFactor);
std::unordered_map<ssize_t, Texture2D*> _atlasTextures;
std::unordered_map<char16_t, FontLetterDefinition> _letterDefinitions;
float _lineHeight;

View File

@ -119,6 +119,8 @@ public://@public
// Character Set defines the letters that actually exist in the font
std::set<unsigned int> *_characterSet;
//! Font Size
int _fontSize;
public:
/**
* @js ctor
@ -225,6 +227,7 @@ BMFontConfiguration::BMFontConfiguration()
, _commonHeight(0)
, _kerningDictionary(nullptr)
, _characterSet(nullptr)
, _fontSize(0)
{
}
@ -539,7 +542,7 @@ void BMFontConfiguration::parseInfoArguments(const char* line)
// info face="Script" size=32 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=1,4,3,2 spacing=0,0 outline=0
// info face="Cracked" size=36 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1
//////////////////////////////////////////////////////////////////////////
sscanf(strstr(line, "size=") + 5, "%d", &_fontSize);
// padding
sscanf(strstr(line,"padding=") + 8, "%d,%d,%d,%d", &_padding.top, &_padding.right, &_padding.bottom, &_padding.left);
//CCLOG("cocos2d: padding: %d,%d,%d,%d", _padding.left, _padding.top, _padding.right, _padding.bottom);
@ -647,7 +650,7 @@ FontFNT * FontFNT::create(const std::string& fntFilePath, const Vec2& imageOffse
}
FontFNT *tempFont = new FontFNT(newConf,imageOffset);
tempFont->setFontSize(newConf->_fontSize);
if (!tempFont)
{
return nullptr;
@ -716,6 +719,16 @@ int FontFNT::getHorizontalKerningForChars(unsigned short firstChar, unsigned sh
return ret;
}
void FontFNT::setFontSize(float fontSize)
{
_fontSize = fontSize;
}
int FontFNT::getOriginalFontSize()const
{
return _configuration->_fontSize;
}
FontAtlas * FontFNT::createFontAtlas()
{
FontAtlas *tempAtlas = new (std::nothrow) FontAtlas(*this);
@ -734,7 +747,16 @@ FontAtlas * FontFNT::createFontAtlas()
return nullptr;
// common height
tempAtlas->setLineHeight(_configuration->_commonHeight);
int originalFontSize = _configuration->_fontSize;
float originalLineHeight = _configuration->_commonHeight;
float factor = 0.0f;
if (fabs(_fontSize - originalFontSize) < FLT_EPSILON) {
factor = 1.0f;
}else {
factor = _fontSize / originalFontSize;
}
tempAtlas->setLineHeight(originalLineHeight * factor);
BMFontDef fontDef;

View File

@ -46,7 +46,8 @@ public:
static void purgeCachedData();
virtual int* getHorizontalKerningForTextUTF16(const std::u16string& text, int &outNumLetters) const override;
virtual FontAtlas *createFontAtlas() override;
void setFontSize(float fontSize);
int getOriginalFontSize()const;
protected:
FontFNT(BMFontConfiguration *theContfig, const Vec2& imageOffset = Vec2::ZERO);
@ -62,7 +63,8 @@ private:
BMFontConfiguration * _configuration;
Vec2 _imageOffset;
//User defined font size
float _fontSize;
};
/// @endcond

View File

@ -39,6 +39,7 @@
#include "base/CCEventListenerCustom.h"
#include "base/CCEventDispatcher.h"
#include "base/CCEventCustom.h"
#include "2d/CCFontFNT.h"
NS_CC_BEGIN
@ -472,6 +473,12 @@ void Label::reset()
_blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
_isOpacityModifyRGB = false;
_insideBounds = true;
_enableWrap = true;
_bmFontSize = -1;
_bmfontScale = 1.0f;
_overflow = Overflow::NORMAL;
_originalFontSize = 0.0f;
}
void Label::updateShaderProgram()
@ -548,46 +555,37 @@ void Label::setFontAtlas(FontAtlas* atlas,bool distanceFieldEnabled /* = false *
bool Label::setTTFConfig(const TTFConfig& ttfConfig)
{
FontAtlas *newAtlas = FontAtlasCache::getFontAtlasTTF(&ttfConfig);
if (!newAtlas)
{
reset();
return false;
}
_systemFontDirty = false;
_currentLabelType = LabelType::TTF;
setFontAtlas(newAtlas,ttfConfig.distanceFieldEnabled,true);
_fontConfig = ttfConfig;
if (_fontConfig.outlineSize > 0)
{
_fontConfig.distanceFieldEnabled = false;
_useDistanceField = false;
_useA8Shader = false;
_currLabelEffect = LabelEffect::OUTLINE;
updateShaderProgram();
}
else
{
_currLabelEffect = LabelEffect::NORMAL;
updateShaderProgram();
}
return true;
_originalFontSize = ttfConfig.fontSize;
return setTTFConfigInternal(ttfConfig);
}
bool Label::setBMFontFilePath(const std::string& bmfontFilePath, const Vec2& imageOffset /* = Vec2::ZERO */)
bool Label::setBMFontFilePath(const std::string& bmfontFilePath, const Vec2& imageOffset, float fontSize)
{
FontAtlas *newAtlas = FontAtlasCache::getFontAtlasFNT(bmfontFilePath,imageOffset);
if (!newAtlas)
{
reset();
return false;
}
//asign the default fontSize
if (fabs(fontSize) < FLT_EPSILON) {
FontFNT *bmFont = (FontFNT*)newAtlas->getFont();
if (bmFont) {
float originalFontSize = bmFont->getOriginalFontSize();
if(fabs(_bmFontSize+1) < FLT_EPSILON){
_bmFontSize = originalFontSize / CC_CONTENT_SCALE_FACTOR();
}
}
}
if(fontSize > 0){
_bmFontSize = fontSize;
}
_bmFontPath = bmfontFilePath;
_currentLabelType = LabelType::BMFONT;
setFontAtlas(newAtlas);
@ -631,6 +629,9 @@ void Label::setMaxLineWidth(float maxLineWidth)
void Label::setDimensions(float width, float height)
{
if(_overflow == Overflow::RESIZE_HEIGHT){
height = 0;
}
if (height != _labelHeight || width != _labelWidth)
{
_labelWidth = width;
@ -640,7 +641,26 @@ void Label::setDimensions(float width, float height)
_maxLineWidth = width;
_contentDirty = true;
}
if(_overflow == Overflow::SHRINK){
if (_originalFontSize > 0) {
this->restoreFontSize();
}
}
}
}
void Label::restoreFontSize()
{
if(_currentLabelType == LabelType::TTF){
auto ttfConfig = this->getTTFConfig();
ttfConfig.fontSize = _originalFontSize;
this->setTTFConfigInternal(ttfConfig);
}else if(_currentLabelType == LabelType::BMFONT){
this->setBMFontSizeInternal(_originalFontSize);
}else if(_currentLabelType == LabelType::STRING_TEXTURE){
this->setSystemFontSize(_originalFontSize);
}
}
void Label::setLineBreakWithoutSpace(bool breakWithoutSpace)
@ -695,61 +715,94 @@ void Label::updateLabelLetters()
auto py = letterInfo.positionY - letterDef.height / 2 + _letterOffsetY;
letterSprite->setPosition(px, py);
if (_currentLabelType == LabelType::BMFONT && _bmFontSize > 0) {
_reusedLetter->setScale(_bmfontScale);
}else{
if(fabs(_bmFontSize)<FLT_EPSILON){
_reusedLetter->setScale(0);
}else{
_reusedLetter->setScale(1.0);
}
}
++it;
}
}
}
}
void Label::alignText()
bool Label::alignText()
{
if (_fontAtlas == nullptr || _utf16Text.empty())
{
setContentSize(Size::ZERO);
return;
return true;
}
_fontAtlas->prepareLetterDefinitions(_utf16Text);
auto& textures = _fontAtlas->getTextures();
if (textures.size() > _batchNodes.size())
{
for (auto index = _batchNodes.size(); index < textures.size(); ++index)
bool ret = true;
do {
_fontAtlas->prepareLetterDefinitions(_utf16Text);
auto& textures = _fontAtlas->getTextures();
if (textures.size() > _batchNodes.size())
{
auto batchNode = SpriteBatchNode::createWithTexture(textures.at(index));
if (batchNode)
for (auto index = _batchNodes.size(); index < textures.size(); ++index)
{
_isOpacityModifyRGB = batchNode->getTexture()->hasPremultipliedAlpha();
_blendFunc = batchNode->getBlendFunc();
batchNode->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
batchNode->setPosition(Vec2::ZERO);
_batchNodes.pushBack(batchNode);
auto batchNode = SpriteBatchNode::createWithTexture(textures.at(index));
if (batchNode)
{
_isOpacityModifyRGB = batchNode->getTexture()->hasPremultipliedAlpha();
_blendFunc = batchNode->getBlendFunc();
batchNode->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
batchNode->setPosition(Vec2::ZERO);
_batchNodes.pushBack(batchNode);
}
}
}
}
if (_batchNodes.empty())
{
return;
}
_reusedLetter->setBatchNode(_batchNodes.at(0));
if (_batchNodes.empty())
{
return true;
}
_reusedLetter->setBatchNode(_batchNodes.at(0));
_lengthOfString = 0;
_textDesiredHeight = 0.f;
_linesWidth.clear();
if (_maxLineWidth > 0.f && !_lineBreakWithoutSpaces)
{
multilineTextWrapByWord();
}
else
{
multilineTextWrapByChar();
}
computeAlignmentOffset();
_lengthOfString = 0;
_textDesiredHeight = 0.f;
_linesWidth.clear();
if (_maxLineWidth > 0.f && !_lineBreakWithoutSpaces)
{
multilineTextWrapByWord();
}
else
{
multilineTextWrapByChar();
}
computeAlignmentOffset();
if(_enableWrap && _overflow == Overflow::SHRINK){
float fontSize = 0;
if (_currentLabelType == LabelType::BMFONT) {
fontSize = _bmFontSize;
}else if(_currentLabelType == LabelType::TTF){
fontSize = this->getTTFConfig().fontSize;
}
updateQuads();
if(fontSize > 0 && isVerticalClamp()){
this->shrinkLabelToContentSize(CC_CALLBACK_0(Label::isVerticalClamp, this));
}
}
updateLabelLetters();
if(!updateQuads()){
ret = false;
if(!_enableWrap && _overflow == Overflow::SHRINK){
this->shrinkLabelToContentSize(CC_CALLBACK_0(Label::isHorizontalClamp, this));
}
break;
}
updateLabelLetters();
updateColor();
}while (0);
updateColor();
return ret;
}
bool Label::computeHorizontalKernings(const std::u16string& stringToRender)
@ -769,13 +822,15 @@ bool Label::computeHorizontalKernings(const std::u16string& stringToRender)
return true;
}
void Label::updateQuads()
bool Label::updateQuads()
{
bool ret = true;
for (auto&& batchNode : _batchNodes)
{
batchNode->getTextureAtlas()->removeAllQuads();
}
bool letterClamp = false;
for (int ctr = 0; ctr < _lengthOfString; ++ctr)
{
if (_lettersInfo[ctr].valid)
@ -802,16 +857,114 @@ void Label::updateQuads()
}
}
if(!_enableWrap){
auto px = _lettersInfo[ctr].positionX + letterDef.width/2;
if(_labelWidth > 0.f){
if (px > _contentSize.width) {
if(_overflow == Overflow::CLAMP){
_reusedRect.size.width = 0;
}else if(_overflow == Overflow::SHRINK){
if (letterDef.width > 0
&& _contentSize.width > letterDef.width) {
letterClamp = true;
ret = false;
break;
}else{
//clamp
_reusedRect.size.width = 0;
}
}
}
}
}
if (_reusedRect.size.height > 0.f && _reusedRect.size.width > 0.f)
{
_reusedLetter->setTextureRect(_reusedRect, false, _reusedRect.size);
_reusedLetter->setPosition(_lettersInfo[ctr].positionX + _linesOffsetX[_lettersInfo[ctr].lineIndex], py);
auto index = static_cast<int>(_batchNodes.at(letterDef.textureID)->getTextureAtlas()->getTotalQuads());
_lettersInfo[ctr].atlasIndex = index;
if (_currentLabelType == LabelType::BMFONT && _bmFontSize > 0) {
_reusedLetter->setScale(_bmfontScale);
}else{
if(fabs(_bmFontSize)<FLT_EPSILON){
_reusedLetter->setScale(0);
}else{
_reusedLetter->setScale(1.0);
}
}
_batchNodes.at(letterDef.textureID)->insertQuadFromSprite(_reusedLetter, index);
}
}
}
return ret;
}
bool Label::setTTFConfigInternal(const TTFConfig& ttfConfig)
{
FontAtlas *newAtlas = FontAtlasCache::getFontAtlasTTF(&ttfConfig);
if (!newAtlas)
{
reset();
return false;
}
_systemFontDirty = false;
_currentLabelType = LabelType::TTF;
setFontAtlas(newAtlas,ttfConfig.distanceFieldEnabled,true);
_fontConfig = ttfConfig;
if (_fontConfig.outlineSize > 0)
{
_fontConfig.distanceFieldEnabled = false;
_useDistanceField = false;
_useA8Shader = false;
_currLabelEffect = LabelEffect::OUTLINE;
updateShaderProgram();
}
else
{
_currLabelEffect = LabelEffect::NORMAL;
updateShaderProgram();
}
return true;
}
void Label::setBMFontSizeInternal(float fontSize)
{
if(_currentLabelType == LabelType::BMFONT){
this->setBMFontFilePath(_bmFontPath, Vec2::ZERO, fontSize);
_contentDirty = true;
}
}
void Label::scaleFontSizeDown(float fontSize)
{
bool shouldUpdateContent = true;
if(_currentLabelType == LabelType::TTF){
auto ttfConfig = this->getTTFConfig();
ttfConfig.fontSize = fontSize;
this->setTTFConfigInternal(ttfConfig);
}else if(_currentLabelType == LabelType::BMFONT){
if (fabs(fontSize) < FLT_EPSILON) {
fontSize = 0.1f;
shouldUpdateContent = false;
}
this->setBMFontSizeInternal(fontSize);
}else if (_currentLabelType == LabelType::STRING_TEXTURE){
this->setSystemFontSize(fontSize);
}
if (shouldUpdateContent) {
this->updateContent();
}
}
void Label::enableGlow(const Color4B& glowColor)
@ -1102,6 +1255,7 @@ void Label::updateContent()
CC_SAFE_RELEASE_NULL(_textSprite);
CC_SAFE_RELEASE_NULL(_shadowNode);
bool updateFinished = true;
if (_fontAtlas)
{
@ -1112,7 +1266,7 @@ void Label::updateContent()
}
computeHorizontalKernings(_utf16Text);
alignText();
updateFinished = alignText();
}
else
{
@ -1123,7 +1277,9 @@ void Label::updateContent()
createShadowSpriteForSystemFont(fontDef);
}
}
_contentDirty = false;
if(updateFinished){
_contentDirty = false;
}
#if CC_LABEL_DEBUG_DRAW
_debugDrawNode->clear();
@ -1138,6 +1294,17 @@ void Label::updateContent()
#endif
}
void Label::setBMFontSize(float fontSize)
{
this->setBMFontSizeInternal(fontSize);
_originalFontSize = fontSize;
}
float Label::getBMFontSize()const
{
return _bmFontSize;
}
void Label::onDrawShadow(GLProgram* glProgram)
{
if (_currentLabelType == LabelType::TTF)
@ -1381,6 +1548,7 @@ void Label::setSystemFontSize(float fontSize)
if (_systemFontSize != fontSize)
{
_systemFontSize = fontSize;
_originalFontSize = fontSize;
_systemFontDirty = true;
}
}
@ -1468,16 +1636,16 @@ float Label::getLineHeight() const
void Label::setLineSpacing(float height)
{
if (_lineSpacing != height)
{
_lineSpacing = height;
_contentDirty = true;
}
if (_lineSpacing != height)
{
_lineSpacing = height;
_contentDirty = true;
}
}
float Label::getLineSpacing() const
{
return _lineSpacing;
return _lineSpacing;
}
void Label::setAdditionalKerning(float space)
@ -1753,4 +1921,64 @@ void Label::setGlobalZOrder(float globalZOrder)
}
}
float Label::getRenderingFontSize()const
{
float fontSize;
if (_currentLabelType == LabelType::BMFONT) {
fontSize = _bmFontSize;
}else if(_currentLabelType == LabelType::TTF){
fontSize = this->getTTFConfig().fontSize;
}else if(_currentLabelType == LabelType::STRING_TEXTURE){
fontSize = _systemFontSize;
}else{ //FIXME: find a way to caculate char map font size
fontSize = this->getLineHeight();
}
return fontSize;
}
void Label::enableWrap(bool enable)
{
if(enable == _enableWrap || _overflow == Overflow::RESIZE_HEIGHT
|| _currentLabelType == LabelType::STRING_TEXTURE){
return;
}
this->_enableWrap = enable;
auto renderingFontSize = this->getRenderingFontSize();
if (fabs(_originalFontSize - renderingFontSize) >= 1) {
this->scaleFontSizeDown(_originalFontSize);
}
_contentDirty = true;
}
bool Label::isWrapEnabled()const
{
return this->_enableWrap;
}
void Label::setOverflow(Overflow overflow)
{
if(_overflow == overflow || _currentLabelType == LabelType::CHARMAP){
return;
}
if(overflow == Overflow::RESIZE_HEIGHT){
this->setDimensions(_labelDimensions.width,0);
this->enableWrap(true);
}
_overflow = overflow;
auto renderingFontSize = this->getRenderingFontSize();
if (fabs(_originalFontSize - renderingFontSize) >= 1) {
this->scaleFontSizeDown(_originalFontSize);
}
_contentDirty = true;
}
Label::Overflow Label::getOverflow()const
{
return _overflow;
}
NS_CC_END

View File

@ -95,6 +95,23 @@ class EventListenerCustom;
class CC_DLL Label : public Node, public LabelProtocol, public BlendProtocol
{
public:
enum class Overflow
{
//for keep back compatibility
NORMAL,
/**
* In SHRINK mode, the font size will change dynamically to adapt the content size.
*/
SHRINK,
/**
*In CLAMP mode, when label content goes out of the bounding box, it will be clipped.
*/
CLAMP,
/**
*In RESIZE_HEIGHT mode, you can only change the width of label and the height is changed automatically.
*/
RESIZE_HEIGHT
};
/// @name Creators
/// @{
@ -221,7 +238,7 @@ public:
virtual const TTFConfig& getTTFConfig() const { return _fontConfig;}
/** Sets a new bitmap font to Label */
virtual bool setBMFontFilePath(const std::string& bmfontFilePath, const Vec2& imageOffset = Vec2::ZERO);
virtual bool setBMFontFilePath(const std::string& bmfontFilePath, const Vec2& imageOffset = Vec2::ZERO, float fontSize = 0);
/** Returns the bitmap font used by the Label.*/
const std::string& getBMFontFilePath() const { return _bmFontPath;}
@ -366,12 +383,53 @@ public:
*/
void setMaxLineWidth(float maxLineWidth);
float getMaxLineWidth() { return _maxLineWidth; }
/**
* Change font size of label type BMFONT
* Note: This function only scale the BMFONT letter to mimic the font size change effect.
*
* @param fontSize The desired font size in float.
*/
void setBMFontSize(float fontSize);
/**
* Return the user define BMFont size.
*
* @return The BMFont size in float value.
*/
float getBMFontSize()const;
/**
* Toggle wrap option the label.
* Note: System font doesn't support manually toggle wrap.
*
* @param enable Set true to enable wrap and false to disable wrap.
*/
void enableWrap(bool enable);
/**
* Query the wrap is enabled or not.
* Note: System font will always return true.
*/
bool isWrapEnabled()const;
/**
* Change the label's Overflow type, currently only TTF and BMFont support all the valid Overflow type.
*
* @param overflow see `Overflow`
*/
void setOverflow(Overflow overflow);
/**
* Query the label's Overflow type.
*
* @return see `Overflow`
*/
Overflow getOverflow()const;
/**
* Makes the Label exactly this untransformed width.
*
* The Label's width be used for text align if the value not equal zero.
*/
*/
void setWidth(float width) { setDimensions(width,_labelHeight);}
float getWidth() const { return _labelWidth; }
@ -508,21 +566,30 @@ protected:
bool multilineTextWrapByChar();
bool multilineTextWrapByWord();
void shrinkLabelToContentSize(std::function<bool(void)> lambda);
bool isHorizontalClamp();
bool isVerticalClamp();
float getRenderingFontSize()const;
void updateLabelLetters();
virtual void alignText();
virtual bool alignText();
void computeAlignmentOffset();
bool computeHorizontalKernings(const std::u16string& stringToRender);
void recordLetterInfo(const cocos2d::Vec2& point, char16_t utf16Char, int letterIndex, int lineIndex);
void recordPlaceholderInfo(int letterIndex, char16_t utf16Char);
void updateQuads();
bool updateQuads();
void createSpriteForSystemFont(const FontDefinition& fontDef);
void createShadowSpriteForSystemFont(const FontDefinition& fontDef);
virtual void updateShaderProgram();
void updateBMFontScale();
void scaleFontSizeDown(float fontSize);
bool setTTFConfigInternal(const TTFConfig& ttfConfig);
void setBMFontSizeInternal(float fontSize);
void restoreFontSize();
void reset();
@ -614,6 +681,12 @@ protected:
#if CC_LABEL_DEBUG_DRAW
DrawNode* _debugDrawNode;
#endif
bool _enableWrap;
float _bmFontSize;
float _bmfontScale;
Overflow _overflow;
float _originalFontSize;
private:
CC_DISALLOW_COPY_AND_ASSIGN(Label);
};

View File

@ -28,6 +28,7 @@
#include "base/ccUTF8.h"
#include "base/CCDirector.h"
#include "2d/CCFontAtlas.h"
#include "2d/CCFontFNT.h"
NS_CC_BEGIN
@ -93,6 +94,18 @@ static int getFirstWordLen(const std::u16string& utf16Text, int startIndex, int
return len;
}
void Label::updateBMFontScale()
{
auto font = _fontAtlas->getFont();
if (_currentLabelType == LabelType::BMFONT) {
FontFNT *bmFont = (FontFNT*)font;
float originalFontSize = bmFont->getOriginalFontSize();
_bmfontScale = _bmFontSize * CC_CONTENT_SCALE_FACTOR() / originalFontSize;
}else{
_bmfontScale = 1.0f;
}
}
bool Label::multilineTextWrapByWord()
{
int textLen = getStringLength();
@ -108,7 +121,9 @@ bool Label::multilineTextWrapByWord()
float lowestY = 0.f;
FontLetterDefinition letterDef;
Vec2 letterPosition;
this->updateBMFontScale();
for (int index = 0; index < textLen; )
{
auto character = _utf16Text[index];
@ -118,7 +133,7 @@ bool Label::multilineTextWrapByWord()
letterRight = 0.f;
lineIndex++;
nextWordX = 0.f;
nextWordY -= _lineHeight + lineSpacing;
nextWordY -= _lineHeight*_bmfontScale + lineSpacing;
recordPlaceholderInfo(index, character);
index++;
continue;
@ -146,14 +161,14 @@ bool Label::multilineTextWrapByWord()
continue;
}
auto letterX = (nextLetterX + letterDef.offsetX) / contentScaleFactor;
if (_maxLineWidth > 0.f && nextWordX > 0.f && letterX + letterDef.width > _maxLineWidth)
auto letterX = (nextLetterX + letterDef.offsetX * _bmfontScale) / contentScaleFactor;
if (_enableWrap && _maxLineWidth > 0.f && nextWordX > 0.f && letterX + letterDef.width * _bmfontScale > _maxLineWidth)
{
_linesWidth.push_back(letterRight);
letterRight = 0.f;
lineIndex++;
nextWordX = 0.f;
nextWordY -= _lineHeight + lineSpacing;
nextWordY -= (_lineHeight*_bmfontScale + lineSpacing);
newLine = true;
break;
}
@ -161,19 +176,19 @@ bool Label::multilineTextWrapByWord()
{
letterPosition.x = letterX;
}
letterPosition.y = (nextWordY - letterDef.offsetY) / contentScaleFactor;
letterPosition.y = (nextWordY - letterDef.offsetY * _bmfontScale) / contentScaleFactor;
recordLetterInfo(letterPosition, character, letterIndex, lineIndex);
if (_horizontalKernings && letterIndex < textLen - 1)
nextLetterX += _horizontalKernings[letterIndex + 1];
nextLetterX += letterDef.xAdvance + _additionalKerning;
nextLetterX += letterDef.xAdvance * _bmfontScale + _additionalKerning;
wordRight = letterPosition.x + letterDef.width;
wordRight = letterPosition.x + letterDef.width * _bmfontScale;
if (wordHighestY < letterPosition.y)
wordHighestY = letterPosition.y;
if (wordLowestY > letterPosition.y - letterDef.height)
wordLowestY = letterPosition.y - letterDef.height;
if (wordLowestY > letterPosition.y - letterDef.height * _bmfontScale)
wordLowestY = letterPosition.y - letterDef.height * _bmfontScale;
}
if (newLine)
@ -196,7 +211,7 @@ bool Label::multilineTextWrapByWord()
_linesWidth.push_back(letterRight);
_numberOfLines = lineIndex + 1;
_textDesiredHeight = (_numberOfLines * _lineHeight) / contentScaleFactor;
_textDesiredHeight = (_numberOfLines * _lineHeight * _bmfontScale) / contentScaleFactor;
if (_numberOfLines > 1)
_textDesiredHeight += (_numberOfLines - 1) * _lineSpacing;
Size contentSize(_labelWidth, _labelHeight);
@ -232,6 +247,8 @@ bool Label::multilineTextWrapByChar()
FontLetterDefinition letterDef;
Vec2 letterPosition;
this->updateBMFontScale();
for (int index = 0; index < textLen; index++)
{
auto character = _utf16Text[index];
@ -246,7 +263,7 @@ bool Label::multilineTextWrapByChar()
letterRight = 0.f;
lineIndex++;
nextLetterX = 0.f;
nextLetterY -= _lineHeight + lineSpacing;
nextLetterY -= _lineHeight * _bmfontScale + lineSpacing;
recordPlaceholderInfo(index, character);
continue;
}
@ -258,33 +275,33 @@ bool Label::multilineTextWrapByChar()
continue;
}
auto letterX = (nextLetterX + letterDef.offsetX) / contentScaleFactor;
if (_maxLineWidth > 0.f && nextLetterX > 0.f && letterX + letterDef.width > _maxLineWidth)
auto letterX = (nextLetterX + letterDef.offsetX * _bmfontScale) / contentScaleFactor;
if (_enableWrap && _maxLineWidth > 0.f && nextLetterX > 0.f && letterX + letterDef.width * _bmfontScale > _maxLineWidth)
{
_linesWidth.push_back(letterRight);
letterRight = 0.f;
lineIndex++;
nextLetterX = 0.f;
nextLetterY -= _lineHeight + lineSpacing;
letterPosition.x = letterDef.offsetX / contentScaleFactor;
nextLetterY -= _lineHeight * _bmfontScale + lineSpacing;
letterPosition.x = letterDef.offsetX * _bmfontScale / contentScaleFactor;
}
else
{
letterPosition.x = letterX;
}
letterPosition.y = (nextLetterY - letterDef.offsetY) / contentScaleFactor;
letterPosition.y = (nextLetterY - letterDef.offsetY * _bmfontScale) / contentScaleFactor;
recordLetterInfo(letterPosition, character, index, lineIndex);
if (_horizontalKernings && index < textLen - 1)
nextLetterX += _horizontalKernings[index + 1];
nextLetterX += letterDef.xAdvance + _additionalKerning;
nextLetterX += letterDef.xAdvance * _bmfontScale + _additionalKerning;
letterRight = letterPosition.x + letterDef.width;
letterRight = letterPosition.x + letterDef.width * _bmfontScale;
if (highestY < letterPosition.y)
highestY = letterPosition.y;
if (lowestY > letterPosition.y - letterDef.height)
lowestY = letterPosition.y - letterDef.height;
if (lowestY > letterPosition.y - letterDef.height * _bmfontScale)
lowestY = letterPosition.y - letterDef.height * _bmfontScale;
if (longestLine < letterRight)
longestLine = letterRight;
}
@ -292,7 +309,7 @@ bool Label::multilineTextWrapByChar()
_linesWidth.push_back(letterRight);
_numberOfLines = lineIndex + 1;
_textDesiredHeight = (_numberOfLines * _lineHeight) / contentScaleFactor;
_textDesiredHeight = (_numberOfLines * _lineHeight * _bmfontScale) / contentScaleFactor;
if (_numberOfLines > 1)
_textDesiredHeight += (_numberOfLines - 1) * _lineSpacing;
Size contentSize(_labelWidth, _labelHeight);
@ -300,6 +317,7 @@ bool Label::multilineTextWrapByChar()
contentSize.width = longestLine;
if (_labelHeight <= 0.f)
contentSize.height = _textDesiredHeight;
setContentSize(contentSize);
_tailoredTopY = contentSize.height;
@ -312,6 +330,81 @@ bool Label::multilineTextWrapByChar()
return true;
}
bool Label::isVerticalClamp()
{
if (_textDesiredHeight > _contentSize.height)
{
return true;
}
else
{
return false;
}
}
bool Label::isHorizontalClamp()
{
bool letterClamp = false;
for (int ctr = 0; ctr < _lengthOfString; ++ctr)
{
if (_lettersInfo[ctr].valid)
{
auto& letterDef = _fontAtlas->_letterDefinitions[_lettersInfo[ctr].utf16Char];
auto px = _lettersInfo[ctr].positionX + letterDef.width/2;
if(_labelWidth > 0.f){
if (px > _contentSize.width) {
letterClamp = true;
break;
}
}
}
}
return letterClamp;
}
void Label::shrinkLabelToContentSize(std::function<bool(void)> lambda)
{
float fontSize = this->getRenderingFontSize();
int i = 0;
auto letterDefinition = _fontAtlas->_letterDefinitions;
auto tempLetterDefinition = letterDefinition;
float originalLineHeight = this->getLineHeight();
bool flag = true;
while (lambda()) {
++i;
float newFontSize = fontSize - i;
flag = false;
if (newFontSize <= 0) {
break;
}
float scale = newFontSize / fontSize;
std::swap(_fontAtlas->_letterDefinitions, tempLetterDefinition);
_fontAtlas->scaleFontLetterDefinition(scale);
this->setLineHeight(originalLineHeight * scale);
if (_maxLineWidth > 0.f && !_lineBreakWithoutSpaces)
{
multilineTextWrapByWord();
}
else
{
multilineTextWrapByChar();
}
computeAlignmentOffset();
tempLetterDefinition = letterDefinition;
}
this->setLineHeight(originalLineHeight);
std::swap(_fontAtlas->_letterDefinitions, letterDefinition);
if (!flag) {
if (fontSize - i >= 0) {
this->scaleFontSizeDown(fontSize - i);
}
}
}
void Label::recordLetterInfo(const cocos2d::Vec2& point, char16_t utf16Char, int letterIndex, int lineIndex)
{
if (static_cast<std::size_t>(letterIndex) >= _lettersInfo.size())

View File

@ -5,6 +5,7 @@
USING_NS_CC;
using namespace ui;
using namespace extension;
enum {
kTagTileMap = 1,
@ -88,6 +89,14 @@ NewLabelTests::NewLabelTests()
ADD_TEST_CASE(LabelIssue10688Test);
ADD_TEST_CASE(LabelIssue13202Test);
ADD_TEST_CASE(LabelIssue9500Test);
ADD_TEST_CASE(LabelWrapByWordTest);
ADD_TEST_CASE(LabelWrapByCharTest);
ADD_TEST_CASE(LabelShrinkByWordTest);
ADD_TEST_CASE(LabelShrinkByCharTest);
ADD_TEST_CASE(LabelResizeTest);
ADD_TEST_CASE(LabelToggleTypeTest);
ADD_TEST_CASE(LabelSystemFontTest);
ADD_TEST_CASE(LabelCharMapFontTest);
};
LabelFNTColorAndOpacity::LabelFNTColorAndOpacity()
@ -2003,3 +2012,725 @@ std::string LabelIssue9500Test::subtitle() const
{
return "Spaces should not be lost if label created with Fingerpop.ttf";
}
ControlStepper *LabelLayoutBaseTest::makeControlStepper()
{
auto minusSprite = Sprite::create("extensions/stepper-minus.png");
auto plusSprite = Sprite::create("extensions/stepper-plus.png");
return ControlStepper::create(minusSprite, plusSprite);
}
LabelLayoutBaseTest::LabelLayoutBaseTest()
{
auto size = Director::getInstance()->getVisibleSize();
this->initTestLabel(size);
this->initFontSizeChange(size);
this->initToggleLabelTypeOption(size);
this->initWrapOption(size);
this->initAlignmentOption(size);
this->initDrawNode(size);
this->initSliders(size);
}
void LabelLayoutBaseTest::initFontSizeChange(const cocos2d::Size& size)
{
auto fontSizeLabel = Label::createWithSystemFont("font size:20", "Arial", 10);
fontSizeLabel->setName("fontSize");
ControlStepper *stepper = this->makeControlStepper();
stepper->setPosition(size.width * 0.5 - stepper->getContentSize().width / 2,
size.height * 0.8);
stepper->setValue(20);
stepper->addTargetWithActionForControlEvents(this,
cccontrol_selector(LabelLayoutBaseTest::valueChanged),
Control::EventType::VALUE_CHANGED);
this->addChild(stepper);
stepper->setName("stepper");
stepper->setScale(0.5);
fontSizeLabel->setPosition(stepper->getPosition() -
Vec2(stepper->getContentSize().width/2 + fontSizeLabel->getContentSize().width/2,0));
this->addChild(fontSizeLabel);
}
void LabelLayoutBaseTest::initWrapOption(const cocos2d::Size& size)
{
auto label = Label::createWithSystemFont("Enable Wrap:", "Arial", 10);
label->setColor(Color3B::WHITE);
label->setPosition(Vec2(size.width * 0.8f - 100, size.height * 0.8f));
this->addChild(label);
CheckBox* checkBox = CheckBox::create("cocosui/check_box_normal.png",
"cocosui/check_box_normal_press.png",
"cocosui/check_box_active.png",
"cocosui/check_box_normal_disable.png",
"cocosui/check_box_active_disable.png");
checkBox->setPosition(Vec2(size.width * 0.8f - 55, size.height * 0.8f));
checkBox->setScale(0.5);
checkBox->setSelected(true);
checkBox->setName("toggleWrap");
checkBox->addEventListener([=](Ref* ref, CheckBox::EventType event){
if (event == CheckBox::EventType::SELECTED) {
_label->enableWrap(true);
}else{
_label->enableWrap(false);
}
this->updateDrawNodeSize(_label->getContentSize());
});
this->addChild(checkBox);
}
void LabelLayoutBaseTest::initToggleLabelTypeOption(const cocos2d::Size& size)
{
auto label = Label::createWithSystemFont("Toggle Label Type:", "Arial", 10);
label->setColor(Color3B::WHITE);
label->setPosition(Vec2(size.width * 0.8f + 15, size.height * 0.8f));
this->addChild(label);
CheckBox* checkBox = CheckBox::create("cocosui/check_box_normal.png",
"cocosui/check_box_normal_press.png",
"cocosui/check_box_active.png",
"cocosui/check_box_normal_disable.png",
"cocosui/check_box_active_disable.png");
checkBox->setPosition(Vec2(size.width * 0.8f + 70, size.height * 0.8f));
checkBox->setScale(0.5);
checkBox->setName("toggleType");
checkBox->setSelected(true);
auto stepper = (ControlStepper*)this->getChildByName("stepper");
checkBox->addEventListener([=](Ref* ref, CheckBox::EventType event){
float fontSize = stepper->getValue();
if (event == CheckBox::EventType::SELECTED) {
_labelType = 0;
auto ttfConfig = _label->getTTFConfig();
ttfConfig.fontSize = fontSize;
_label->setTTFConfig(ttfConfig);
}else{
_labelType = 1;
_label->setBMFontFilePath("fonts/enligsh-chinese.fnt");
_label->setBMFontSize(fontSize);
}
});
this->addChild(checkBox);
}
void LabelLayoutBaseTest::initAlignmentOption(const cocos2d::Size& size)
{
//add text alignment settings
MenuItemFont::setFontSize(30);
auto menu = Menu::create(
MenuItemFont::create("Left", CC_CALLBACK_1(LabelLayoutBaseTest::setAlignmentLeft, this)),
MenuItemFont::create("Center", CC_CALLBACK_1(LabelLayoutBaseTest::setAlignmentCenter, this)),
MenuItemFont::create("Right", CC_CALLBACK_1(LabelLayoutBaseTest::setAlignmentRight, this)),
nullptr);
menu->alignItemsVerticallyWithPadding(4);
menu->setPosition(Vec2(50, size.height / 2 - 20));
this->addChild(menu);
menu = Menu::create(
MenuItemFont::create("Top", CC_CALLBACK_1(LabelLayoutBaseTest::setAlignmentTop, this)),
MenuItemFont::create("Middle", CC_CALLBACK_1(LabelLayoutBaseTest::setAlignmentMiddle, this)),
MenuItemFont::create("Bottom", CC_CALLBACK_1(LabelLayoutBaseTest::setAlignmentBottom, this)),
nullptr);
menu->alignItemsVerticallyWithPadding(4);
menu->setPosition(Vec2(size.width - 50, size.height / 2 - 20));
this->addChild(menu);
}
void LabelLayoutBaseTest::initSliders(const cocos2d::Size& size)
{
auto slider = ui::Slider::create();
slider->setTag(1);
slider->setTouchEnabled(true);
slider->loadBarTexture("cocosui/sliderTrack.png");
slider->loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "");
slider->loadProgressBarTexture("cocosui/sliderProgress.png");
slider->setPosition(Vec2(size.width / 2.0f, size.height * 0.15f + slider->getContentSize().height * 2.0f - 5));
slider->setPercent(52);
addChild(slider);
auto slider2 = ui::Slider::create();
slider2->setTag(2);
slider2->setTouchEnabled(true);
slider2->loadBarTexture("cocosui/sliderTrack.png");
slider2->loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "");
slider2->loadProgressBarTexture("cocosui/sliderProgress.png");
slider2->setPosition(Vec2(size.width * 0.2f, size.height / 2.0));
slider2->setRotation(90);
slider2->setPercent(52);
addChild(slider2);
auto winSize = Director::getInstance()->getVisibleSize();
auto labelSize = _label->getContentSize();
slider->addEventListener([=](Ref* ref, Slider::EventType event){
float percent = slider->getPercent();
auto drawNodeSize = Size(percent / 100.0 * winSize.width, labelSize.height);
if(drawNodeSize.width <=0){
drawNodeSize.width = 0.1f;
}
_label->setDimensions(drawNodeSize.width, drawNodeSize.height);
this->updateDrawNodeSize(drawNodeSize);
});
slider2->addEventListener([=](Ref* ref, Slider::EventType event){
float percent = slider2->getPercent();
auto drawNodeSize = Size( labelSize.width, percent / 100.0 * winSize.height);
if(drawNodeSize.height <= 0){
drawNodeSize.height = 0.1f;
}
_label->setDimensions(drawNodeSize.width, drawNodeSize.height);
this->updateDrawNodeSize(drawNodeSize);
});
}
void LabelLayoutBaseTest::initTestLabel(const cocos2d::Size& size)
{
auto center = VisibleRect::center();
_label = Label::createWithTTF("五六七八This is a very long sentence一二三四.", "fonts/HKYuanMini.ttf", 20);
_label->setDimensions(size.width/2, size.height/2);
_label->setPosition(center);
_label->setName("Label");
_label->setString("五六七八This is a very long sentence一二三.");
addChild(_label);
_labelType = 0;
}
void LabelLayoutBaseTest::initDrawNode(const cocos2d::Size& size)
{
_drawNode = DrawNode::create();
_drawNode->setTag(3);
addChild(_drawNode);
this->updateDrawNodeSize(_label->getContentSize());
}
void LabelLayoutBaseTest::setAlignmentLeft(Ref* sender)
{
_label->setHorizontalAlignment(TextHAlignment::LEFT);
}
void LabelLayoutBaseTest::setAlignmentCenter(Ref* sender)
{
_label->setHorizontalAlignment(TextHAlignment::CENTER);
}
void LabelLayoutBaseTest::setAlignmentRight(Ref* sender)
{
_label->setHorizontalAlignment(TextHAlignment::RIGHT);
}
void LabelLayoutBaseTest::setAlignmentTop(Ref* sender)
{
_label->setVerticalAlignment(TextVAlignment::TOP);
}
void LabelLayoutBaseTest::setAlignmentMiddle(Ref* sender)
{
_label->setVerticalAlignment(TextVAlignment::CENTER);
}
void LabelLayoutBaseTest::setAlignmentBottom(Ref* sender)
{
_label->setVerticalAlignment(TextVAlignment::BOTTOM);
}
void LabelLayoutBaseTest::valueChanged(cocos2d::Ref *sender, cocos2d::extension::Control::EventType controlEvent)
{
ControlStepper* pControl = (ControlStepper*)sender;
// Change value of label.
auto fontSizeLabel = (Label*)this->getChildByName("fontSize");
float fontSize = (float)pControl->getValue();
fontSizeLabel->setString(StringUtils::format("font size:%d", (int)fontSize));
if (_labelType == 0) {
auto ttfConfig = _label->getTTFConfig();
ttfConfig.fontSize = fontSize;
_label->setTTFConfig(ttfConfig);
}else if(_labelType == 1){
_label->setBMFontSize(fontSize);
}
this->updateDrawNodeSize(_label->getContentSize());
}
void LabelLayoutBaseTest::updateDrawNodeSize(const cocos2d::Size &drawNodeSize)
{
auto origin = Director::getInstance()->getWinSize();
auto labelSize = _label->getContentSize();
origin.width = origin.width / 2 - (labelSize.width / 2);
origin.height = origin.height / 2 - (labelSize.height / 2);
Vec2 vertices[4]=
{
Vec2(origin.width, origin.height),
Vec2(drawNodeSize.width + origin.width, origin.height),
Vec2(drawNodeSize.width + origin.width, drawNodeSize.height + origin.height),
Vec2(origin.width, drawNodeSize.height + origin.height)
};
_drawNode->clear();
_drawNode->drawLine(vertices[0], vertices[1], Color4F(1.0, 1.0, 1.0, 1.0));
_drawNode->drawLine(vertices[0], vertices[3], Color4F(1.0, 1.0, 1.0, 1.0));
_drawNode->drawLine(vertices[2], vertices[3], Color4F(1.0, 1.0, 1.0, 1.0));
_drawNode->drawLine(vertices[1], vertices[2], Color4F(1.0, 1.0, 1.0, 1.0));
}
LabelWrapByWordTest::LabelWrapByWordTest()
{
_label->setLineSpacing(5);
_label->setAdditionalKerning(2);
_label->setVerticalAlignment(TextVAlignment::CENTER);
_label->setOverflow(Label::Overflow::CLAMP);
}
std::string LabelWrapByWordTest::title() const
{
return "Clamp content Test: Word Wrap";
}
std::string LabelWrapByWordTest::subtitle() const
{
return "";
}
LabelWrapByCharTest::LabelWrapByCharTest()
{
_label->setLineBreakWithoutSpace(true);
_label->setLineSpacing(5);
_label->setAdditionalKerning(2);
_label->setVerticalAlignment(TextVAlignment::TOP);
_label->setOverflow(Label::Overflow::CLAMP);
}
std::string LabelWrapByCharTest::title() const
{
return "Clamp content Test: Char Wrap";
}
std::string LabelWrapByCharTest::subtitle() const
{
return "";
}
LabelShrinkByWordTest::LabelShrinkByWordTest()
{
_label->setLineSpacing(5);
_label->setAdditionalKerning(2);
_label->setString("This is Hello World hehe I love 一二三");
_label->setVerticalAlignment(TextVAlignment::TOP);
_label->setOverflow(Label::Overflow::SHRINK);
}
std::string LabelShrinkByWordTest::title() const
{
return "Shrink content Test: Word Wrap";
}
std::string LabelShrinkByWordTest::subtitle() const
{
return "";
}
LabelShrinkByCharTest::LabelShrinkByCharTest()
{
_label->setLineSpacing(5);
_label->setAdditionalKerning(2);
_label->setLineBreakWithoutSpace(true);
_label->setString("This is Hello World hehe I love 一二三");
_label->setVerticalAlignment(TextVAlignment::CENTER);
_label->setOverflow(Label::Overflow::SHRINK);
}
std::string LabelShrinkByCharTest::title() const
{
return "Shrink content Test: Char Wrap";
}
std::string LabelShrinkByCharTest::subtitle() const
{
return "";
}
LabelResizeTest::LabelResizeTest()
{
_label->setLineSpacing(5);
_label->setAdditionalKerning(2);
_label->setVerticalAlignment(TextVAlignment::TOP);
_label->setOverflow(Label::Overflow::RESIZE_HEIGHT);
this->updateDrawNodeSize(_label->getContentSize());
auto slider1 = (ui::Slider*)this->getChildByTag(1);
auto slider2 = (ui::Slider*)this->getChildByTag(2);
slider2->setVisible(false);
auto winSize = Director::getInstance()->getVisibleSize();
slider1->addEventListener([=](Ref* ref, Slider::EventType event){
float percent = slider1->getPercent();
auto drawNodeSize = Size(percent / 100.0 * winSize.width,_label->getContentSize().height);
if(drawNodeSize.height <= 0){
drawNodeSize.height = 0.1f;
}
_label->setDimensions(drawNodeSize.width, drawNodeSize.height);
this->updateDrawNodeSize(drawNodeSize);
});
auto stepper = (ControlStepper*)this->getChildByName("stepper");
stepper->setValue(12);
auto label = Label::createWithSystemFont("Word Line break:", "Arial", 10);
label->setColor(Color3B::WHITE);
label->setPosition(Vec2(winSize.width * 0.1f, winSize.height * 0.8f));
this->addChild(label);
CheckBox* checkBox = CheckBox::create("cocosui/check_box_normal.png",
"cocosui/check_box_normal_press.png",
"cocosui/check_box_active.png",
"cocosui/check_box_normal_disable.png",
"cocosui/check_box_active_disable.png");
checkBox->setPosition(Vec2(winSize.width * 0.2f , winSize.height * 0.8f));
checkBox->setScale(0.5);
checkBox->setSelected(false);
checkBox->setName("LineBreak");
checkBox->addEventListener([=](Ref* ref, CheckBox::EventType event){
if (event == CheckBox::EventType::SELECTED) {
_label->setLineBreakWithoutSpace(true);
}else{
_label->setLineBreakWithoutSpace(false);
}
this->updateDrawNodeSize(_label->getContentSize());
});
this->addChild(checkBox);
}
std::string LabelResizeTest::title() const
{
return "Resize content Test";
}
std::string LabelResizeTest::subtitle() const
{
return "";
}
LabelToggleTypeTest::LabelToggleTypeTest()
{
_label->setLineSpacing(5);
_label->setAdditionalKerning(2);
_label->setVerticalAlignment(TextVAlignment::CENTER);
_label->setOverflow(Label::Overflow::NORMAL);
this->updateDrawNodeSize(_label->getContentSize());
auto slider1 = (ui::Slider*)this->getChildByTag(1);
auto slider2 = (ui::Slider*)this->getChildByTag(2);
slider2->setVisible(false);
auto winSize = Director::getInstance()->getVisibleSize();
slider1->addEventListener([=](Ref* ref, Slider::EventType event){
float percent = slider1->getPercent();
auto drawNodeSize = Size(percent / 100.0 * winSize.width,_label->getContentSize().height);
if(drawNodeSize.height <= 0){
drawNodeSize.height = 0.1f;
}
_label->setDimensions(drawNodeSize.width, drawNodeSize.height);
this->updateDrawNodeSize(drawNodeSize);
});
auto stepper = (ControlStepper*)this->getChildByName("stepper");
stepper->setValue(12);
auto label = Label::createWithSystemFont("Word Line break:", "Arial", 10);
label->setColor(Color3B::WHITE);
label->setPosition(Vec2(winSize.width * 0.1f, winSize.height * 0.8f));
this->addChild(label);
CheckBox* checkBox = CheckBox::create("cocosui/check_box_normal.png",
"cocosui/check_box_normal_press.png",
"cocosui/check_box_active.png",
"cocosui/check_box_normal_disable.png",
"cocosui/check_box_active_disable.png");
checkBox->setPosition(Vec2(winSize.width * 0.2f , winSize.height * 0.8f));
checkBox->setScale(0.5);
checkBox->setSelected(false);
checkBox->setName("LineBreak");
checkBox->addEventListener([=](Ref* ref, CheckBox::EventType event){
if (event == CheckBox::EventType::SELECTED) {
_label->setLineBreakWithoutSpace(true);
}else{
_label->setLineBreakWithoutSpace(false);
}
this->updateDrawNodeSize(_label->getContentSize());
});
this->addChild(checkBox);
this->initToggleCheckboxes();
}
void LabelToggleTypeTest::initToggleCheckboxes()
{
const float BUTTON_WIDTH = 100;
float startPosX = 0;
Size winSize = Director::getInstance()->getVisibleSize();
// Create a radio button group
auto radioButtonGroup = RadioButtonGroup::create();
this->addChild(radioButtonGroup);
// Create the radio buttons
static const int NUMBER_OF_BUTTONS = 4;
startPosX = winSize.width / 2.0f - (NUMBER_OF_BUTTONS - 1 ) * 0.5 * BUTTON_WIDTH - 30;
std::vector<std::string> labelTypes = {"Normal", "Clamp", "Shrink", "RESIZE"};
for(int i = 0; i < NUMBER_OF_BUTTONS; ++i)
{
RadioButton* radioButton = RadioButton::create("cocosui/radio_button_off.png", "cocosui/radio_button_on.png");
float posX = startPosX + BUTTON_WIDTH * i;
radioButton->setPosition(Vec2(posX, winSize.height / 2.0f + 70));
radioButton->setScale(1.2f);
radioButton->addEventListener(CC_CALLBACK_2(LabelToggleTypeTest::onChangedRadioButtonSelect, this));
radioButton->setTag(i);
radioButtonGroup->addRadioButton(radioButton);
this->addChild(radioButton);
auto label = Label::createWithSystemFont(labelTypes.at(i), "Arial", 20);
label->setPosition(radioButton->getPosition() + Vec2(50,0));
this->addChild(label);
}
}
std::string LabelToggleTypeTest::title() const
{
return "Toggle Label Type Test";
}
std::string LabelToggleTypeTest::subtitle() const
{
return "";
}
void LabelToggleTypeTest::onChangedRadioButtonSelect(RadioButton* radioButton, RadioButton::EventType type)
{
if(radioButton == nullptr)
{
return;
}
switch (type)
{
case RadioButton::EventType::SELECTED:
{
switch (radioButton->getTag()) {
case 0:
_label->setOverflow(Label::Overflow::NORMAL);
break;
case 1:
_label->setOverflow(Label::Overflow::CLAMP);
break;
case 2:
_label->setOverflow(Label::Overflow::SHRINK);
break;
case 3:
_label->setOverflow(Label::Overflow::RESIZE_HEIGHT);
break;
default:
break;
}
break;
}
default:
break;
}
auto checkbox = (CheckBox*)(this->getChildByName("toggleWrap"));
checkbox->setSelected(_label->isWrapEnabled());
this->updateDrawNodeSize(_label->getContentSize());
}
LabelSystemFontTest::LabelSystemFontTest()
{
_label->setLineSpacing(5);
_label->setVerticalAlignment(TextVAlignment::CENTER);
_label->setOverflow(Label::Overflow::NORMAL);
_label->setSystemFontName("Hiragino Sans GB");
this->updateDrawNodeSize(_label->getContentSize());
auto slider1 = (ui::Slider*)this->getChildByTag(1);
auto slider2 = (ui::Slider*)this->getChildByTag(2);
slider2->setVisible(false);
auto winSize = Director::getInstance()->getVisibleSize();
slider1->addEventListener([=](Ref* ref, Slider::EventType event){
float percent = slider1->getPercent();
auto drawNodeSize = Size(percent / 100.0 * winSize.width,_label->getContentSize().height);
if(drawNodeSize.height <= 0){
drawNodeSize.height = 0.1f;
}
_label->setDimensions(drawNodeSize.width, drawNodeSize.height);
this->updateDrawNodeSize(drawNodeSize);
});
auto label = Label::createWithSystemFont("Word Line break:", "Arial", 10);
label->setColor(Color3B::WHITE);
label->setPosition(Vec2(winSize.width * 0.1f, winSize.height * 0.8f));
this->addChild(label);
CheckBox* checkBox = CheckBox::create("cocosui/check_box_normal.png",
"cocosui/check_box_normal_press.png",
"cocosui/check_box_active.png",
"cocosui/check_box_normal_disable.png",
"cocosui/check_box_active_disable.png");
checkBox->setPosition(Vec2(winSize.width * 0.2f , winSize.height * 0.8f));
checkBox->setScale(0.5);
checkBox->setSelected(false);
checkBox->setName("LineBreak");
checkBox->addEventListener([=](Ref* ref, CheckBox::EventType event){
if (event == CheckBox::EventType::SELECTED) {
_label->setLineBreakWithoutSpace(true);
}else{
_label->setLineBreakWithoutSpace(false);
}
this->updateDrawNodeSize(_label->getContentSize());
});
this->addChild(checkBox);
this->initToggleCheckboxes();
}
void LabelSystemFontTest::initToggleCheckboxes()
{
const float BUTTON_WIDTH = 100;
float startPosX = 0;
Size winSize = Director::getInstance()->getVisibleSize();
// Create a radio button group
auto radioButtonGroup = RadioButtonGroup::create();
this->addChild(radioButtonGroup);
// Create the radio buttons
static const int NUMBER_OF_BUTTONS = 4;
startPosX = winSize.width / 2.0f - (NUMBER_OF_BUTTONS - 1 ) * 0.5 * BUTTON_WIDTH - 30;
std::vector<std::string> labelTypes = {"Normal", "Clamp", "Shrink", "RESIZE"};
for(int i = 0; i < NUMBER_OF_BUTTONS; ++i)
{
RadioButton* radioButton = RadioButton::create("cocosui/radio_button_off.png", "cocosui/radio_button_on.png");
float posX = startPosX + BUTTON_WIDTH * i;
radioButton->setPosition(Vec2(posX, winSize.height / 2.0f + 70));
radioButton->setScale(1.2f);
radioButton->addEventListener(CC_CALLBACK_2(LabelSystemFontTest::onChangedRadioButtonSelect, this));
radioButton->setTag(i);
radioButtonGroup->addRadioButton(radioButton);
this->addChild(radioButton);
auto label = Label::createWithSystemFont(labelTypes.at(i), "Arial", 20);
label->setPosition(radioButton->getPosition() + Vec2(50,0));
this->addChild(label);
}
}
std::string LabelSystemFontTest::title() const
{
return "System Font Test";
}
std::string LabelSystemFontTest::subtitle() const
{
return "";
}
void LabelSystemFontTest::onChangedRadioButtonSelect(RadioButton* radioButton, RadioButton::EventType type)
{
if(radioButton == nullptr)
{
return;
}
switch (type)
{
case RadioButton::EventType::SELECTED:
{
switch (radioButton->getTag()) {
case 0:
_label->setOverflow(Label::Overflow::NORMAL);
break;
case 1:
_label->setOverflow(Label::Overflow::CLAMP);
break;
case 2:
_label->setOverflow(Label::Overflow::SHRINK);
break;
case 3:
_label->setOverflow(Label::Overflow::RESIZE_HEIGHT);
break;
default:
break;
}
break;
}
default:
break;
}
auto checkbox = (CheckBox*)(this->getChildByName("toggleWrap"));
checkbox->setSelected(_label->isWrapEnabled());
this->updateDrawNodeSize(_label->getContentSize());
}
LabelCharMapFontTest::LabelCharMapFontTest()
{
_label->setLineSpacing(5);
_label->setVerticalAlignment(TextVAlignment::CENTER);
_label->setOverflow(Label::Overflow::NORMAL);
_label->setCharMap("fonts/tuffy_bold_italic-charmap.plist");
_label->setString("Hello World, This is a char map test.");
_label->setScale(0.5f);
auto stepper = (ControlStepper*)this->getChildByName("stepper");
stepper->setEnabled(false);
auto checkbox = (CheckBox*)(this->getChildByName("toggleType"));
checkbox->setEnabled(false);
this->updateDrawNodeSize(_label->getContentSize());
}
std::string LabelCharMapFontTest::title() const
{
return "CharMap Font Test";
}
std::string LabelCharMapFontTest::subtitle() const
{
return "";
}

View File

@ -4,6 +4,7 @@
#include "../BaseTest.h"
#include "renderer/CCCustomCommand.h"
#include "ui/CocosGUI.h"
#include "extensions/cocos-ext.h"
DEFINE_TEST_SUITE(NewLabelTests);
@ -635,4 +636,123 @@ public:
virtual std::string subtitle() const override;
};
class LabelLayoutBaseTest : public AtlasDemoNew
{
public:
LabelLayoutBaseTest();
void updateDrawNodeSize(const cocos2d::Size &drawNodeSize);
cocos2d::extension::ControlStepper* makeControlStepper();
void valueChanged(cocos2d::Ref* sender, cocos2d::extension::Control::EventType controlEvent);
protected:
void setAlignmentLeft(cocos2d::Ref* sender);
void setAlignmentCenter(cocos2d::Ref* sender);
void setAlignmentRight(cocos2d::Ref* sender);
void setAlignmentTop(cocos2d::Ref* sender);
void setAlignmentMiddle(cocos2d::Ref* sender);
void setAlignmentBottom(cocos2d::Ref* sender);
void initWrapOption(const cocos2d::Size& size);
void initToggleLabelTypeOption(const cocos2d::Size& size);
void initAlignmentOption(const cocos2d::Size& size);
void initFontSizeChange(const cocos2d::Size& size);
void initSliders(const cocos2d::Size& size);
void initTestLabel(const cocos2d::Size& size);
void initDrawNode(const cocos2d::Size& size);
cocos2d::DrawNode* _drawNode;
cocos2d::Label* _label;
int _labelType;
};
class LabelWrapByWordTest : public LabelLayoutBaseTest
{
public:
CREATE_FUNC(LabelWrapByWordTest);
LabelWrapByWordTest();
virtual std::string title() const override;
virtual std::string subtitle() const override;
};
class LabelWrapByCharTest : public LabelLayoutBaseTest
{
public:
CREATE_FUNC(LabelWrapByCharTest);
LabelWrapByCharTest();
virtual std::string title() const override;
virtual std::string subtitle() const override;
};
class LabelShrinkByWordTest : public LabelLayoutBaseTest
{
public:
CREATE_FUNC(LabelShrinkByWordTest);
LabelShrinkByWordTest();
virtual std::string title() const override;
virtual std::string subtitle() const override;
};
class LabelShrinkByCharTest : public LabelLayoutBaseTest
{
public:
CREATE_FUNC(LabelShrinkByCharTest);
LabelShrinkByCharTest();
virtual std::string title() const override;
virtual std::string subtitle() const override;
};
class LabelResizeTest : public LabelLayoutBaseTest
{
public:
CREATE_FUNC(LabelResizeTest);
LabelResizeTest();
virtual std::string title() const override;
virtual std::string subtitle() const override;
};
class LabelToggleTypeTest : public LabelLayoutBaseTest
{
public:
CREATE_FUNC(LabelToggleTypeTest);
LabelToggleTypeTest();
void initToggleCheckboxes();
void onChangedRadioButtonSelect(cocos2d::ui::RadioButton* radioButton,cocos2d::ui::RadioButton::EventType type);
virtual std::string title() const override;
virtual std::string subtitle() const override;
};
class LabelSystemFontTest : public LabelLayoutBaseTest
{
public:
CREATE_FUNC(LabelSystemFontTest);
LabelSystemFontTest();
void initToggleCheckboxes();
void onChangedRadioButtonSelect(cocos2d::ui::RadioButton* radioButton,cocos2d::ui::RadioButton::EventType type);
virtual std::string title() const override;
virtual std::string subtitle() const override;
};
class LabelCharMapFontTest : public LabelSystemFontTest
{
public:
CREATE_FUNC(LabelCharMapFontTest);
LabelCharMapFontTest();
virtual std::string title() const override;
virtual std::string subtitle() const override;
};
#endif

View File

@ -0,0 +1,108 @@
info face="DFYuanW7-GBK" size=40 bold=1 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=1,1,1,1 spacing=2,2
common lineHeight=43 base=34 scaleW=512 scaleH=256 pages=1 packed=0
page id=0 file="enligsh-chinese.png"
chars count=104
char id=32 x=261 y=151 width=0 height=0 xoffset=0 yoffset=37 xadvance=20 page=0 chnl=0 letter="space"
char id=33 x=368 y=82 width=10 height=33 xoffset=7 yoffset=4 xadvance=20 page=0 chnl=0 letter="!"
char id=34 x=44 y=151 width=14 height=15 xoffset=5 yoffset=0 xadvance=20 page=0 chnl=0 letter="""
char id=35 x=419 y=47 width=20 height=33 xoffset=2 yoffset=5 xadvance=20 page=0 chnl=0 letter="#"
char id=36 x=231 y=2 width=21 height=39 xoffset=1 yoffset=1 xadvance=20 page=0 chnl=0 letter="$"
char id=37 x=480 y=2 width=22 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="%"
char id=38 x=74 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="&"
char id=39 x=60 y=151 width=11 height=14 xoffset=6 yoffset=0 xadvance=20 page=0 chnl=0 letter="'"
char id=40 x=10 y=2 width=15 height=40 xoffset=4 yoffset=1 xadvance=20 page=0 chnl=0 letter="("
char id=41 x=27 y=2 width=15 height=40 xoffset=4 yoffset=1 xadvance=20 page=0 chnl=0 letter=")"
char id=42 x=212 y=117 width=23 height=26 xoffset=0 yoffset=8 xadvance=20 page=0 chnl=0 letter="*"
char id=43 x=23 y=151 width=19 height=21 xoffset=2 yoffset=10 xadvance=20 page=0 chnl=0 letter="+"
char id=44 x=107 y=151 width=9 height=13 xoffset=7 yoffset=28 xadvance=20 page=0 chnl=0 letter=","
char id=45 x=190 y=151 width=19 height=7 xoffset=2 yoffset=17 xadvance=20 page=0 chnl=0 letter="-"
char id=46 x=137 y=151 width=9 height=9 xoffset=7 yoffset=28 xadvance=20 page=0 chnl=0 letter="."
char id=47 x=254 y=2 width=21 height=39 xoffset=1 yoffset=2 xadvance=20 page=0 chnl=0 letter="/"
char id=48 x=176 y=82 width=18 height=33 xoffset=3 yoffset=4 xadvance=20 page=0 chnl=0 letter="0"
char id=49 x=355 y=82 width=11 height=33 xoffset=6 yoffset=4 xadvance=20 page=0 chnl=0 letter="1"
char id=50 x=196 y=82 width=18 height=33 xoffset=3 yoffset=3 xadvance=20 page=0 chnl=0 letter="2"
char id=51 x=216 y=82 width=18 height=33 xoffset=3 yoffset=4 xadvance=20 page=0 chnl=0 letter="3"
char id=52 x=441 y=47 width=20 height=33 xoffset=2 yoffset=4 xadvance=20 page=0 chnl=0 letter="4"
char id=53 x=236 y=82 width=18 height=33 xoffset=3 yoffset=4 xadvance=20 page=0 chnl=0 letter="5"
char id=54 x=256 y=82 width=18 height=33 xoffset=3 yoffset=4 xadvance=20 page=0 chnl=0 letter="6"
char id=55 x=276 y=82 width=18 height=33 xoffset=3 yoffset=4 xadvance=20 page=0 chnl=0 letter="7"
char id=56 x=296 y=82 width=18 height=33 xoffset=3 yoffset=4 xadvance=20 page=0 chnl=0 letter="8"
char id=57 x=316 y=82 width=18 height=33 xoffset=3 yoffset=4 xadvance=20 page=0 chnl=0 letter="9"
char id=58 x=495 y=117 width=10 height=24 xoffset=7 yoffset=13 xadvance=20 page=0 chnl=0 letter=":"
char id=59 x=200 y=117 width=10 height=28 xoffset=7 yoffset=13 xadvance=20 page=0 chnl=0 letter=";"
char id=60 x=47 y=117 width=20 height=31 xoffset=2 yoffset=5 xadvance=20 page=0 chnl=0 letter="<"
char id=61 x=86 y=151 width=19 height=13 xoffset=2 yoffset=14 xadvance=20 page=0 chnl=0 letter="="
char id=62 x=69 y=117 width=20 height=31 xoffset=2 yoffset=5 xadvance=20 page=0 chnl=0 letter=">"
char id=63 x=97 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="?"
char id=64 x=120 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="@"
char id=65 x=143 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="A"
char id=66 x=451 y=82 width=21 height=32 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="B"
char id=67 x=166 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="C"
char id=68 x=474 y=82 width=21 height=32 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="D"
char id=69 x=25 y=117 width=20 height=32 xoffset=2 yoffset=4 xadvance=20 page=0 chnl=0 letter="E"
char id=70 x=463 y=47 width=20 height=33 xoffset=2 yoffset=4 xadvance=20 page=0 chnl=0 letter="F"
char id=71 x=189 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="G"
char id=72 x=485 y=47 width=20 height=33 xoffset=2 yoffset=4 xadvance=20 page=0 chnl=0 letter="H"
char id=73 x=390 y=82 width=7 height=33 xoffset=8 yoffset=4 xadvance=20 page=0 chnl=0 letter="I"
char id=74 x=212 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="J"
char id=75 x=2 y=82 width=20 height=33 xoffset=2 yoffset=4 xadvance=20 page=0 chnl=0 letter="K"
char id=76 x=24 y=82 width=20 height=33 xoffset=2 yoffset=3 xadvance=20 page=0 chnl=0 letter="L"
char id=77 x=2 y=47 width=22 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="M"
char id=78 x=46 y=82 width=20 height=33 xoffset=2 yoffset=4 xadvance=20 page=0 chnl=0 letter="N"
char id=79 x=26 y=47 width=22 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="O"
char id=80 x=235 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="P"
char id=81 x=258 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="Q"
char id=82 x=281 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="R"
char id=83 x=304 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="S"
char id=84 x=50 y=47 width=22 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="T"
char id=85 x=68 y=82 width=20 height=33 xoffset=2 yoffset=4 xadvance=20 page=0 chnl=0 letter="U"
char id=86 x=327 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="V"
char id=87 x=350 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="W"
char id=88 x=373 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="X"
char id=89 x=396 y=47 width=21 height=33 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="Y"
char id=90 x=2 y=117 width=21 height=32 xoffset=1 yoffset=4 xadvance=20 page=0 chnl=0 letter="Z"
char id=91 x=44 y=2 width=13 height=40 xoffset=5 yoffset=1 xadvance=20 page=0 chnl=0 letter="["
char id=92 x=277 y=2 width=21 height=39 xoffset=1 yoffset=2 xadvance=20 page=0 chnl=0 letter="\"
char id=93 x=59 y=2 width=13 height=40 xoffset=5 yoffset=1 xadvance=20 page=0 chnl=0 letter="]"
char id=94 x=118 y=151 width=17 height=9 xoffset=3 yoffset=2 xadvance=20 page=0 chnl=0 letter="^"
char id=95 x=211 y=151 width=23 height=6 xoffset=0 yoffset=37 xadvance=20 page=0 chnl=0 letter="_"
char id=96 x=73 y=151 width=11 height=14 xoffset=6 yoffset=0 xadvance=20 page=0 chnl=0 letter="`"
char id=97 x=395 y=117 width=19 height=24 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="a"
char id=98 x=90 y=82 width=20 height=33 xoffset=2 yoffset=4 xadvance=20 page=0 chnl=0 letter="b"
char id=99 x=285 y=117 width=20 height=24 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="c"
char id=100 x=112 y=82 width=20 height=33 xoffset=2 yoffset=4 xadvance=20 page=0 chnl=0 letter="d"
char id=101 x=307 y=117 width=20 height=24 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="e"
char id=102 x=336 y=82 width=17 height=33 xoffset=3 yoffset=4 xadvance=20 page=0 chnl=0 letter="f"
char id=103 x=91 y=117 width=22 height=29 xoffset=1 yoffset=13 xadvance=20 page=0 chnl=0 letter="g"
char id=104 x=134 y=82 width=19 height=33 xoffset=2 yoffset=4 xadvance=20 page=0 chnl=0 letter="h"
char id=105 x=380 y=82 width=8 height=33 xoffset=8 yoffset=4 xadvance=20 page=0 chnl=0 letter="i"
char id=106 x=381 y=2 width=13 height=38 xoffset=5 yoffset=4 xadvance=20 page=0 chnl=0 letter="j"
char id=107 x=155 y=82 width=19 height=33 xoffset=2 yoffset=4 xadvance=20 page=0 chnl=0 letter="k"
char id=108 x=399 y=82 width=7 height=33 xoffset=8 yoffset=4 xadvance=20 page=0 chnl=0 letter="l"
char id=109 x=237 y=117 width=22 height=24 xoffset=1 yoffset=13 xadvance=20 page=0 chnl=0 letter="m"
char id=110 x=416 y=117 width=19 height=24 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="n"
char id=111 x=329 y=117 width=20 height=24 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="o"
char id=112 x=115 y=117 width=20 height=29 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="p"
char id=113 x=137 y=117 width=20 height=29 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="q"
char id=114 x=479 y=117 width=14 height=24 xoffset=5 yoffset=13 xadvance=20 page=0 chnl=0 letter="r"
char id=115 x=437 y=117 width=19 height=24 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="s"
char id=116 x=181 y=117 width=17 height=28 xoffset=3 yoffset=8 xadvance=20 page=0 chnl=0 letter="t"
char id=117 x=458 y=117 width=19 height=24 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="u"
char id=118 x=351 y=117 width=20 height=24 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="v"
char id=119 x=261 y=117 width=22 height=24 xoffset=1 yoffset=13 xadvance=20 page=0 chnl=0 letter="w"
char id=120 x=373 y=117 width=20 height=24 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="x"
char id=121 x=159 y=117 width=20 height=29 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="y"
char id=122 x=2 y=151 width=19 height=23 xoffset=2 yoffset=13 xadvance=20 page=0 chnl=0 letter="z"
char id=123 x=74 y=2 width=13 height=40 xoffset=5 yoffset=1 xadvance=20 page=0 chnl=0 letter="{"
char id=124 x=2 y=2 width=6 height=43 xoffset=9 yoffset=0 xadvance=20 page=0 chnl=0 letter="|"
char id=125 x=89 y=2 width=13 height=40 xoffset=5 yoffset=1 xadvance=20 page=0 chnl=0 letter="}"
char id=126 x=236 y=151 width=23 height=6 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=0 letter="~"
char id=19968 x=148 y=151 width=40 height=7 xoffset=2 yoffset=16 xadvance=40 page=0 chnl=0 letter="一"
char id=19971 x=300 y=2 width=40 height=38 xoffset=1 yoffset=1 xadvance=40 page=0 chnl=0 letter="七"
char id=19977 x=439 y=2 width=39 height=36 xoffset=2 yoffset=3 xadvance=40 page=0 chnl=0 letter="三"
char id=20061 x=189 y=2 width=40 height=39 xoffset=2 yoffset=2 xadvance=40 page=0 chnl=0 letter="九"
char id=20108 x=408 y=82 width=41 height=32 xoffset=1 yoffset=6 xadvance=40 page=0 chnl=0 letter="二"
char id=20116 x=396 y=2 width=41 height=37 xoffset=1 yoffset=2 xadvance=40 page=0 chnl=0 letter="五"
char id=20843 x=104 y=2 width=41 height=39 xoffset=1 yoffset=2 xadvance=40 page=0 chnl=0 letter="八"
char id=20845 x=147 y=2 width=40 height=39 xoffset=2 yoffset=1 xadvance=40 page=0 chnl=0 letter="六"
char id=22235 x=342 y=2 width=37 height=38 xoffset=3 yoffset=3 xadvance=40 page=0 chnl=0 letter="四"

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB