From 447b37ffd97cc3d52bfe7f7903e29d6a17a41783 Mon Sep 17 00:00:00 2001 From: Dhilan007 Date: Mon, 17 Mar 2014 18:33:15 +0800 Subject: [PATCH 1/5] closed issue#4428:fixed label display incorrect if invoking getLetter and it's multi-line. --- cocos/2d/CCLabel.cpp | 74 +++++++++++++++++++++++++------------------- cocos/2d/CCLabel.h | 6 +++- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/cocos/2d/CCLabel.cpp b/cocos/2d/CCLabel.cpp index 448dc2c0b1e1..b964f4e132ab 100644 --- a/cocos/2d/CCLabel.cpp +++ b/cocos/2d/CCLabel.cpp @@ -446,7 +446,7 @@ bool Label::setBMFontFilePath(const std::string& bmfontFilePath, const Point& im reset(); return false; } - + _bmFontPath = bmfontFilePath; setFontAtlas(newAtlas); _currentLabelType = LabelType::BMFONT; @@ -624,17 +624,7 @@ void Label::alignText() } } - int index; - for (int ctr = 0; ctr < _limitShowCount; ++ctr) - { - if (_lettersInfo[ctr].def.validDefinition) - { - updateSpriteWithLetterDefinition(_lettersInfo[ctr].def,textures[_lettersInfo[ctr].def.textureID]); - _reusedLetter->setPosition(_lettersInfo[ctr].position); - index = _batchNodes[_lettersInfo[ctr].def.textureID]->getTextureAtlas()->getTotalQuads(); - _batchNodes[_lettersInfo[ctr].def.textureID]->insertQuadFromSprite(_reusedLetter,index); - } - } + updateQuads(); updateColor(); } @@ -691,16 +681,30 @@ bool Label::setCurrentString(unsigned short *stringToSet) return true; } -void Label::updateSpriteWithLetterDefinition(const FontLetterDefinition &theDefinition, Texture2D *theTexture) +void Label::updateQuads() { - _reusedRect.size.height = theDefinition.height; - _reusedRect.size.width = theDefinition.width; - _reusedRect.origin.x = theDefinition.U; - _reusedRect.origin.y = theDefinition.V; + int index; + for (int ctr = 0; ctr < _limitShowCount; ++ctr) + { + auto &letterDef = _lettersInfo[ctr].def; - if(_reusedLetter->getBatchNode() != _batchNodes[theDefinition.textureID]) - _reusedLetter->setBatchNode(_batchNodes[theDefinition.textureID]); - _reusedLetter->setTextureRect(_reusedRect,false,_reusedRect.size); + if (letterDef.validDefinition) + { + _reusedRect.size.height = letterDef.height; + _reusedRect.size.width = letterDef.width; + _reusedRect.origin.x = letterDef.U; + _reusedRect.origin.y = letterDef.V; + + if(_reusedLetter->getBatchNode() != _batchNodes[letterDef.textureID]) + _reusedLetter->setBatchNode(_batchNodes[letterDef.textureID]); + _reusedLetter->setTextureRect(_reusedRect,false,_reusedRect.size); + + _reusedLetter->setPosition(_lettersInfo[ctr].position); + index = _batchNodes[letterDef.textureID]->getTextureAtlas()->getTotalQuads(); + _lettersInfo[ctr].atlasIndex = index; + _batchNodes[letterDef.textureID]->insertQuadFromSprite(_reusedLetter,index); + } + } } bool Label::recordLetterInfo(const cocos2d::Point& point,const FontLetterDefinition& letterDef, int spriteIndex) @@ -1056,6 +1060,10 @@ int Label::getFontSize() const ///// PROTOCOL STUFF Sprite * Label::getLetter(int lettetIndex) { + if (_fontDirty) + { + const_cast(this)->updateFont(); + } if (_contentDirty) { updateContent(); @@ -1063,7 +1071,9 @@ Sprite * Label::getLetter(int lettetIndex) if (! _textSprite && lettetIndex < _limitShowCount) { - if(! _lettersInfo[lettetIndex].def.validDefinition) + auto &letterDef = _lettersInfo[lettetIndex].def; + + if(! letterDef.validDefinition) return nullptr; Sprite* sp = static_cast(this->getChildByTag(lettetIndex)); @@ -1071,18 +1081,18 @@ Sprite * Label::getLetter(int lettetIndex) if (!sp) { Rect uvRect; - uvRect.size.height = _lettersInfo[lettetIndex].def.height; - uvRect.size.width = _lettersInfo[lettetIndex].def.width; - 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->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)); + uvRect.size.height = letterDef.height; + uvRect.size.width = letterDef.width; + uvRect.origin.x = letterDef.U; + uvRect.origin.y = letterDef.V; + + sp = Sprite::createWithTexture(_fontAtlas->getTexture(letterDef.textureID),uvRect); + sp->setBatchNode(_batchNodes[letterDef.textureID]); + sp->setPosition(Point(_lettersInfo[lettetIndex].position.x + uvRect.size.width / 2, + _lettersInfo[lettetIndex].position.y - uvRect.size.height / 2)); sp->setOpacity(_realOpacity); - this->addSpriteWithoutQuad(sp, lettetIndex, lettetIndex); + _batchNodes[letterDef.textureID]->addSpriteWithoutQuad(sp, _lettersInfo[lettetIndex].atlasIndex, lettetIndex); } return sp; } @@ -1120,7 +1130,7 @@ void Label::computeStringNumLines() int Label::getStringLength() const { - return _currentUTF16String ? cc_wcslen(_currentUTF16String) : 0; + return _currentUTF16String ? cc_wcslen(_currentUTF16String) : _originalUTF8String.length(); } // RGBA protocol diff --git a/cocos/2d/CCLabel.h b/cocos/2d/CCLabel.h index bef78167a667..2e4ecea274e0 100644 --- a/cocos/2d/CCLabel.h +++ b/cocos/2d/CCLabel.h @@ -116,6 +116,7 @@ class CC_DLL Label : public SpriteBatchNode, public LabelProtocol virtual bool setTTFConfig(const TTFConfig& ttfConfig); virtual bool setBMFontFilePath(const std::string& bmfontFilePath, const Point& imageOffset = Point::ZERO); + const std::string& getBMFontFilePath() const { return _bmFontPath;} virtual bool setCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap); virtual bool setCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap); @@ -248,6 +249,7 @@ class CC_DLL Label : public SpriteBatchNode, public LabelProtocol Point position; Size contentSize; + int atlasIndex; }; enum class LabelType { @@ -282,7 +284,7 @@ class CC_DLL Label : public SpriteBatchNode, public LabelProtocol bool setOriginalString(unsigned short *stringToSet); void computeStringNumLines(); - void updateSpriteWithLetterDefinition(const FontLetterDefinition &theDefinition, Texture2D *theTexture); + void updateQuads(); virtual void updateColor() override; @@ -295,6 +297,8 @@ class CC_DLL Label : public SpriteBatchNode, public LabelProtocol void updateFont(); void reset(); + std::string _bmFontPath; + bool _isOpacityModifyRGB; bool _contentDirty; bool _fontDirty; From c8a7a00025e4f50a7d1b108dfd40fc46b624dc64 Mon Sep 17 00:00:00 2001 From: Dhilan007 Date: Mon, 17 Mar 2014 19:31:58 +0800 Subject: [PATCH 2/5] change access specifier of SpriteBatchNode::addSpriteWithoutQuad. --- cocos/2d/CCSpriteBatchNode.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cocos/2d/CCSpriteBatchNode.h b/cocos/2d/CCSpriteBatchNode.h index d95fcfcaf4bd..b35b0fe61002 100644 --- a/cocos/2d/CCSpriteBatchNode.h +++ b/cocos/2d/CCSpriteBatchNode.h @@ -172,16 +172,16 @@ class CC_DLL SpriteBatchNode : public Node, public TextureProtocol For example: a tile map (TMXMap) or a label with lots of characters (LabelBMFont) */ void insertQuadFromSprite(Sprite *sprite, ssize_t index); + /* This is the opposite of "addQuadFromSprite. + It add the sprite to the children and descendants array, but it doesn't update add it to the texture atlas + */ + SpriteBatchNode * addSpriteWithoutQuad(Sprite *child, int z, int aTag); protected: /** Updates a quad at a certain index into the texture atlas. The Sprite won't be added into the children array. This method should be called only when you are dealing with very big AtlasSrite and when most of the Sprite won't be updated. For example: a tile map (TMXMap) or a label with lots of characters (LabelBMFont) */ - void updateQuadFromSprite(Sprite *sprite, ssize_t index); - /* This is the opposite of "addQuadFromSprite. - It add the sprite to the children and descendants array, but it doesn't update add it to the texture atlas - */ - SpriteBatchNode * addSpriteWithoutQuad(Sprite *child, int z, int aTag); + void updateQuadFromSprite(Sprite *sprite, ssize_t index); void updateAtlasIndex(Sprite* sprite, ssize_t* curIndex); void swap(ssize_t oldIndex, ssize_t newIndex); From 67d145ebefc3d58e6b96fb90ad408f5f6a35a5f2 Mon Sep 17 00:00:00 2001 From: Dhilan007 Date: Tue, 18 Mar 2014 10:20:25 +0800 Subject: [PATCH 3/5] Add a test case to reproduce issue 4428. --- .../Classes/LabelTest/LabelTestNew.cpp | 33 ++++++++++++++++++- .../Classes/LabelTest/LabelTestNew.h | 11 +++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/tests/cpp-tests/Classes/LabelTest/LabelTestNew.cpp b/tests/cpp-tests/Classes/LabelTest/LabelTestNew.cpp index c4f647dcfc92..f7680a4a003f 100644 --- a/tests/cpp-tests/Classes/LabelTest/LabelTestNew.cpp +++ b/tests/cpp-tests/Classes/LabelTest/LabelTestNew.cpp @@ -77,7 +77,8 @@ static std::function createFunctions[] = CL(LabelCrashTest), CL(LabelTTFOldNew), CL(LabelFontNameTest), - CL(LabelAlignmentTest) + CL(LabelAlignmentTest), + CL(LabelBugsTest) }; #define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0])) @@ -1779,3 +1780,33 @@ std::string LabelAlignmentTest::subtitle() const { return "Select the buttons on the sides to change alignment"; } + +LabelBugsTest::LabelBugsTest() +{ + auto size = Director::getInstance()->getWinSize(); + + auto label = Label::createWithBMFont( "fonts/bitmapFontTest3.fnt", "123\n456"); + label->setPosition(Point(size.width /2.0f, size.height / 2.0f)); + label->setAnchorPoint(Point::ANCHOR_BOTTOM_LEFT); + addChild(label); + + int len = label->getStringLength(); + for (int i = 0; i < len; ++i) + { + auto sprite = label->getLetter(i); + if (sprite != nullptr) + { + sprite->setFlippedY(true); + } + } +} + +std::string LabelBugsTest::title() const +{ + return "New Label Test"; +} + +std::string LabelBugsTest::subtitle() const +{ + return "Reorder issue #4428.The label should be flipped vertically."; +} diff --git a/tests/cpp-tests/Classes/LabelTest/LabelTestNew.h b/tests/cpp-tests/Classes/LabelTest/LabelTestNew.h index 6017b9e8516a..c8cd07082631 100644 --- a/tests/cpp-tests/Classes/LabelTest/LabelTestNew.h +++ b/tests/cpp-tests/Classes/LabelTest/LabelTestNew.h @@ -484,6 +484,17 @@ class LabelAlignmentTest : public AtlasDemoNew TextVAlignment _vertAlign; }; +class LabelBugsTest : public AtlasDemoNew +{ +public: + CREATE_FUNC(LabelBugsTest); + + LabelBugsTest(); + + virtual std::string title() const override; + virtual std::string subtitle() const override; +}; + // we don't support linebreak mode #endif From 4ac47266b0ce0874e82642ed1a6f7559a6924820 Mon Sep 17 00:00:00 2001 From: Dhilan007 Date: Tue, 18 Mar 2014 10:26:45 +0800 Subject: [PATCH 4/5] update test case of issue 4428. --- tests/cpp-tests/Classes/LabelTest/LabelTestNew.cpp | 10 +++++----- tests/cpp-tests/Classes/LabelTest/LabelTestNew.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/cpp-tests/Classes/LabelTest/LabelTestNew.cpp b/tests/cpp-tests/Classes/LabelTest/LabelTestNew.cpp index f7680a4a003f..dbd963d0bdec 100644 --- a/tests/cpp-tests/Classes/LabelTest/LabelTestNew.cpp +++ b/tests/cpp-tests/Classes/LabelTest/LabelTestNew.cpp @@ -78,7 +78,7 @@ static std::function createFunctions[] = CL(LabelTTFOldNew), CL(LabelFontNameTest), CL(LabelAlignmentTest), - CL(LabelBugsTest) + CL(LabelIssue4428Test) }; #define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0])) @@ -1781,7 +1781,7 @@ std::string LabelAlignmentTest::subtitle() const return "Select the buttons on the sides to change alignment"; } -LabelBugsTest::LabelBugsTest() +LabelIssue4428Test::LabelIssue4428Test() { auto size = Director::getInstance()->getWinSize(); @@ -1801,12 +1801,12 @@ LabelBugsTest::LabelBugsTest() } } -std::string LabelBugsTest::title() const +std::string LabelIssue4428Test::title() const { - return "New Label Test"; + return "New Label Bugs Test"; } -std::string LabelBugsTest::subtitle() const +std::string LabelIssue4428Test::subtitle() const { return "Reorder issue #4428.The label should be flipped vertically."; } diff --git a/tests/cpp-tests/Classes/LabelTest/LabelTestNew.h b/tests/cpp-tests/Classes/LabelTest/LabelTestNew.h index c8cd07082631..7ea2f570e3cd 100644 --- a/tests/cpp-tests/Classes/LabelTest/LabelTestNew.h +++ b/tests/cpp-tests/Classes/LabelTest/LabelTestNew.h @@ -484,12 +484,12 @@ class LabelAlignmentTest : public AtlasDemoNew TextVAlignment _vertAlign; }; -class LabelBugsTest : public AtlasDemoNew +class LabelIssue4428Test : public AtlasDemoNew { public: - CREATE_FUNC(LabelBugsTest); + CREATE_FUNC(LabelIssue4428Test); - LabelBugsTest(); + LabelIssue4428Test(); virtual std::string title() const override; virtual std::string subtitle() const override; From caf69d9b17e8d347952d411065c298afc0ffd9af Mon Sep 17 00:00:00 2001 From: Dhilan007 Date: Tue, 18 Mar 2014 13:48:41 +0800 Subject: [PATCH 5/5] fixed typo. --- cocos/2d/CCLabel.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/cocos/2d/CCLabel.cpp b/cocos/2d/CCLabel.cpp index b964f4e132ab..0b7a5f6dd5a5 100644 --- a/cocos/2d/CCLabel.cpp +++ b/cocos/2d/CCLabel.cpp @@ -1058,41 +1058,41 @@ int Label::getFontSize() const } ///// PROTOCOL STUFF -Sprite * Label::getLetter(int lettetIndex) +Sprite * Label::getLetter(int letterIndex) { if (_fontDirty) { - const_cast(this)->updateFont(); + updateFont(); } if (_contentDirty) { updateContent(); } - if (! _textSprite && lettetIndex < _limitShowCount) + if (! _textSprite && letterIndex < _limitShowCount) { - auto &letterDef = _lettersInfo[lettetIndex].def; + const auto &letter = _lettersInfo[letterIndex]; - if(! letterDef.validDefinition) + if(! letter.def.validDefinition) return nullptr; - Sprite* sp = static_cast(this->getChildByTag(lettetIndex)); + Sprite* sp = static_cast(this->getChildByTag(letterIndex)); if (!sp) { Rect uvRect; - uvRect.size.height = letterDef.height; - uvRect.size.width = letterDef.width; - uvRect.origin.x = letterDef.U; - uvRect.origin.y = letterDef.V; - - sp = Sprite::createWithTexture(_fontAtlas->getTexture(letterDef.textureID),uvRect); - sp->setBatchNode(_batchNodes[letterDef.textureID]); - sp->setPosition(Point(_lettersInfo[lettetIndex].position.x + uvRect.size.width / 2, - _lettersInfo[lettetIndex].position.y - uvRect.size.height / 2)); + uvRect.size.height = letter.def.height; + uvRect.size.width = letter.def.width; + uvRect.origin.x = letter.def.U; + uvRect.origin.y = letter.def.V; + + sp = Sprite::createWithTexture(_fontAtlas->getTexture(letter.def.textureID),uvRect); + sp->setBatchNode(_batchNodes[letter.def.textureID]); + sp->setPosition(Point(letter.position.x + uvRect.size.width / 2, + letter.position.y - uvRect.size.height / 2)); sp->setOpacity(_realOpacity); - _batchNodes[letterDef.textureID]->addSpriteWithoutQuad(sp, _lettersInfo[lettetIndex].atlasIndex, lettetIndex); + _batchNodes[letter.def.textureID]->addSpriteWithoutQuad(sp, letter.atlasIndex, letterIndex); } return sp; }