From cc671835f83b2e2b959307d73814d078788adcb5 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 | 72 +++++++++++++++++++++++++------------------- cocos/2d/CCLabel.h | 6 +++- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/cocos/2d/CCLabel.cpp b/cocos/2d/CCLabel.cpp index 448dc2c0b1..b964f4e132 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; + 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(_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)); + 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 bef78167a6..2e4ecea274 100644 --- a/cocos/2d/CCLabel.h +++ b/cocos/2d/CCLabel.h @@ -116,6 +116,7 @@ public: 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 @@ protected: Point position; Size contentSize; + int atlasIndex; }; enum class LabelType { @@ -282,7 +284,7 @@ protected: bool setOriginalString(unsigned short *stringToSet); void computeStringNumLines(); - void updateSpriteWithLetterDefinition(const FontLetterDefinition &theDefinition, Texture2D *theTexture); + void updateQuads(); virtual void updateColor() override; @@ -295,6 +297,8 @@ protected: void updateFont(); void reset(); + std::string _bmFontPath; + bool _isOpacityModifyRGB; bool _contentDirty; bool _fontDirty; From 46a4c17097fa7fb4d0e3916e57167e0693be46ce 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 d95fcfcaf4..b35b0fe610 100644 --- a/cocos/2d/CCSpriteBatchNode.h +++ b/cocos/2d/CCSpriteBatchNode.h @@ -172,16 +172,16 @@ public: 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 4d5c7fc6342981ee3b0889ff3a96bc517fca3a88 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 c4f647dcfc..f7680a4a00 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 6017b9e851..c8cd070826 100644 --- a/tests/cpp-tests/Classes/LabelTest/LabelTestNew.h +++ b/tests/cpp-tests/Classes/LabelTest/LabelTestNew.h @@ -484,6 +484,17 @@ private: 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 d59fb25e2ab74f1cdb24c039978755910dd451d6 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 f7680a4a00..dbd963d0bd 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 c8cd070826..7ea2f570e3 100644 --- a/tests/cpp-tests/Classes/LabelTest/LabelTestNew.h +++ b/tests/cpp-tests/Classes/LabelTest/LabelTestNew.h @@ -484,12 +484,12 @@ private: 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 a286ed8374f5829910f5f73a55ebba250d9de872 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 | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/cocos/2d/CCLabel.cpp b/cocos/2d/CCLabel.cpp index b964f4e132..0b7a5f6dd5 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; + 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(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 = 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; }