diff --git a/cocos/2d/CCLabel.cpp b/cocos/2d/CCLabel.cpp index 24d6e1cb11..eda91b92f8 100644 --- a/cocos/2d/CCLabel.cpp +++ b/cocos/2d/CCLabel.cpp @@ -50,6 +50,54 @@ Label* Label::create() return ret; } +Label* Label::createWithFontDefinition(const std::string& text, const FontDefinition &textDefinition) +{ + auto ret = new Label(); + + if (ret) + { + ret->setFontDefinition(textDefinition); + ret->setString(text); + ret->autorelease(); + } + + return ret; +} + +Label* Label::create(const std::string& text, const std::string& fontName, float fontSize, const Size& dimensions /* = Size::ZERO */, TextHAlignment hAlignment /* = TextHAlignment::LEFT */, TextVAlignment vAlignment /* = TextVAlignment::TOP */) +{ + auto ret = new Label(nullptr,hAlignment); + + if (ret) + { + do + { + if (fontName.find('.') != fontName.npos) + { + TTFConfig ttfConfig(fontName.c_str(),fontSize,GlyphCollection::DYNAMIC); + if (ret->setTTFConfig(ttfConfig)) + { + break; + } + } + + FontDefinition fontDef; + fontDef._fontName = fontName; + fontDef._fontSize = fontSize; + fontDef._dimensions = dimensions; + fontDef._alignment = hAlignment; + fontDef._vertAlignment = vAlignment; + ret->setFontDefinition(fontDef); + } while (0); + + ret->setDimensions(dimensions.width,dimensions.height); + ret->setString(text); + ret->autorelease(); + } + + return ret; +} + Label* Label::createWithTTF(const TTFConfig& ttfConfig, const std::string& text, TextHAlignment alignment /* = TextHAlignment::CENTER */, int lineSize /* = 0 */) { Label *ret = new Label(nullptr,alignment); @@ -162,7 +210,13 @@ bool Label::setCharMap(const std::string& plistFile) if (!newAtlas) return false; - return initWithFontAtlas(newAtlas); + if (initWithFontAtlas(newAtlas)) + { + _currentLabelType = LabelType::CHARMAP; + return true; + } + + return false; } bool Label::setCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap) @@ -172,7 +226,13 @@ bool Label::setCharMap(Texture2D* texture, int itemWidth, int itemHeight, int st if (!newAtlas) return false; - return initWithFontAtlas(newAtlas); + if (initWithFontAtlas(newAtlas)) + { + _currentLabelType = LabelType::CHARMAP; + return true; + } + + return false; } bool Label::setCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap) @@ -182,7 +242,13 @@ bool Label::setCharMap(const std::string& charMapFile, int itemWidth, int itemHe if (!newAtlas) return false; - return initWithFontAtlas(newAtlas); + if (initWithFontAtlas(newAtlas)) + { + _currentLabelType = LabelType::CHARMAP; + return true; + } + + return false; } Label::Label(FontAtlas *atlas, TextHAlignment alignment, bool useDistanceField,bool useA8Shader) @@ -192,6 +258,7 @@ Label::Label(FontAtlas *atlas, TextHAlignment alignment, bool useDistanceField,b , _maxLineWidth(0) , _labelWidth(0) , _labelHeight(0) +, _labelDimensions(Size::ZERO) , _hAlignment(alignment) , _currentUTF16String(nullptr) , _originalUTF16String(nullptr) @@ -203,9 +270,16 @@ Label::Label(FontAtlas *atlas, TextHAlignment alignment, bool useDistanceField,b , _fontScale(1.0f) , _uniformEffectColor(0) ,_currNumLines(-1) +,_textSprite(nullptr) +,_contentDirty(false) { _cascadeColorEnabled = true; _batchNodes.push_back(this); + + _fontDefinition._fontName = "Helvetica"; + _fontDefinition._fontSize = 32; + _fontDefinition._alignment = TextHAlignment::LEFT; + _fontDefinition._vertAlignment = TextVAlignment::TOP; } Label::~Label() @@ -301,11 +375,7 @@ bool Label::initWithFontAtlas(FontAtlas* atlas,bool distanceFieldEnabled /* = fa if (_fontAtlas) { _commonLineHeight = _fontAtlas->getCommonLineHeight(); - if(_currentUTF16String) - { - resetCurrentString(); - alignText(); - } + _contentDirty = true; } return ret; @@ -333,6 +403,7 @@ bool Label::setTTFConfig(const TTFConfig& ttfConfig) { this->setFontScale(1.0f * ttfConfig.fontSize / DefultFontSize); } + _currentLabelType = LabelType::TTF; return true; } else @@ -348,101 +419,74 @@ bool Label::setBMFontFilePath(const std::string& bmfontFilePath, const Point& im if (!newAtlas) return false; - return initWithFontAtlas(newAtlas); + if (initWithFontAtlas(newAtlas)) + { + _currentLabelType = LabelType::BMFONT; + return true; + } + + return false; +} + +void Label::setFontDefinition(const FontDefinition& textDefinition) +{ + _fontDefinition = textDefinition; + _currentLabelType = LabelType::STRING_TEXTURE; + _contentDirty = true; } void Label::setString(const std::string& text) { - auto utf16String = cc_utf8_to_utf16(text.c_str()); - if(utf16String) - { - _originalUTF8String = text; - setCurrentString(utf16String); - setOriginalString(utf16String); - alignText(); - } + _originalUTF8String = text; + _contentDirty = true; } -void Label::setAlignment(TextHAlignment hAlignment,bool aligntext /* = true */) -{ - setAlignment(hAlignment,_vAlignment,aligntext); -} - -inline void Label::setHorizontalAlignment(TextHAlignment hAlignment,bool aligntext /* = true */) -{ - setAlignment(hAlignment,_vAlignment,aligntext); -} - -inline void Label::setVerticalAlignment(TextVAlignment vAlignment,bool aligntext /* = true */) -{ - setAlignment(_hAlignment,vAlignment,aligntext); -} - -void Label::setAlignment(TextHAlignment hAlignment,TextVAlignment vAlignment,bool aligntext /* = true */) +void Label::setAlignment(TextHAlignment hAlignment,TextVAlignment vAlignment) { if (hAlignment != _hAlignment || vAlignment != _vAlignment) { + _fontDefinition._alignment = hAlignment; + _fontDefinition._vertAlignment = vAlignment; + _hAlignment = hAlignment; _vAlignment = vAlignment; - if (_currentUTF16String && aligntext) - { - resetCurrentString(); - alignText(); - } + + _contentDirty = true; } } void Label::setMaxLineWidth(unsigned int maxLineWidth) { - if (_maxLineWidth != maxLineWidth) + if (_labelWidth == 0 && _maxLineWidth != maxLineWidth) { _maxLineWidth = maxLineWidth; - if (_currentUTF16String) - { - resetCurrentString(); - alignText(); - } + _contentDirty = true; } } -inline void Label::setWidth(unsigned int width) -{ - setDimensions(width,_labelHeight); -} - -inline void Label::setHeight(unsigned int height) -{ - setDimensions(_labelWidth,height); -} - void Label::setDimensions(unsigned int width,unsigned int height) { if (height != _labelHeight || width != _labelWidth) { - _labelHeight = height; + _fontDefinition._dimensions.width = width; + _fontDefinition._dimensions.height = height; + _labelWidth = width; + _labelHeight = height; + _labelDimensions.width = width; + _labelDimensions.height = height; + _maxLineWidth = width; - if (_currentUTF16String) - { - resetCurrentString(); - alignText(); - } - } + _contentDirty = true; + } } void Label::setLineBreakWithoutSpace(bool breakWithoutSpace) { if (breakWithoutSpace != _lineBreakWithoutSpaces) { - // store _lineBreakWithoutSpaces = breakWithoutSpace; - - // need to align text again - if(_currentUTF16String) - { - resetCurrentString(); - alignText(); - } + _contentDirty = true; } } @@ -525,7 +569,7 @@ void Label::alignText() if(_maxLineWidth > 0 && _contentSize.width > _maxLineWidth && LabelTextFormatter::multilineText(this) ) LabelTextFormatter::createStringSprites(this); - if(_labelWidth >0 || (_currNumLines > 1 && _hAlignment != TextHAlignment::LEFT)) + if(_labelWidth > 0 || (_currNumLines > 1 && _hAlignment != TextHAlignment::LEFT)) LabelTextFormatter::alignText(this); int strLen = cc_wcslen(_currentUTF16String); @@ -613,26 +657,11 @@ bool Label::setCurrentString(unsigned short *stringToSet) computeStringNumLines(); // compute the advances - return computeHorizontalKernings(stringToSet); -} - -void Label::resetCurrentString() -{ - if ((!_currentUTF16String) && (!_originalUTF16String)) - return; - - // set the new string - if (_currentUTF16String) + if (_fontAtlas) { - delete [] _currentUTF16String; - _currentUTF16String = 0; + computeHorizontalKernings(stringToSet); } - - int stringLenght = cc_wcslen(_originalUTF16String); - _currentUTF16String = new unsigned short int [stringLenght + 1]; - memcpy(_currentUTF16String, _originalUTF16String, stringLenght * 2); - _currentUTF16String[stringLenght] = 0; - + return true; } void Label::updateSpriteWithLetterDefinition(const FontLetterDefinition &theDefinition, Texture2D *theTexture) @@ -706,7 +735,7 @@ void Label::setLabelEffect(LabelEffect effect,const Color3B& effectColor) void Label::enableGlow(const Color3B& glowColor) { - if(_useDistanceField == false) + if(! _useDistanceField) return; _currLabelEffect = LabelEffect::GLOW; _effectColor = glowColor; @@ -716,16 +745,26 @@ void Label::enableGlow(const Color3B& glowColor) void Label::enableOutline(const Color4B& outlineColor,int outlineSize /* = 1 */) { _outlineColor = outlineColor; + if (outlineSize > 0) { - _currLabelEffect = LabelEffect::OUTLINE; - if (_fontConfig.outlineSize != outlineSize) + if (_currentLabelType == LabelType::TTF) { - _fontConfig.outlineSize = outlineSize; - setTTFConfig(_fontConfig); + if (_fontConfig.outlineSize != outlineSize) + { + auto config = _fontConfig; + config.outlineSize = outlineSize; + setTTFConfig(config); + initProgram(); + } } - initProgram(); - } + _fontDefinition._stroke._strokeEnabled = true; + _fontDefinition._stroke._strokeSize = outlineSize; + _fontDefinition._stroke._strokeColor = Color3B(outlineColor.r,outlineColor.g,outlineColor.b); + + _currLabelEffect = LabelEffect::OUTLINE; + _contentDirty = true; + } } void Label::enableShadow(const Color3B& shadowColor /* = Color3B::BLACK */,const Size &offset /* = Size(2 ,-2)*/, float opacity /* = 0.75f */, int blurRadius /* = 0 */) @@ -736,6 +775,13 @@ void Label::enableShadow(const Color3B& shadowColor /* = Color3B::BLACK */,const //todo:support blur for shadow _shadowBlurRadius = 0; _currLabelEffect = LabelEffect::SHADOW; + + _fontDefinition._shadow._shadowEnabled = true; + _fontDefinition._shadow._shadowBlur = blurRadius; + _fontDefinition._shadow._shadowOffset = offset; + _fontDefinition._shadow._shadowOpacity = opacity; + + _contentDirty = true; } void Label::disableEffect() @@ -747,6 +793,7 @@ void Label::disableEffect() } _currLabelEffect = LabelEffect::NORMAL; initProgram(); + _contentDirty = true; } void Label::setFontScale(float fontScale) @@ -845,14 +892,61 @@ void Label::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpda renderer->addCommand(&_customCommand); } +void Label::createSpriteWithFontDefinition() +{ + _currentLabelType = LabelType::STRING_TEXTURE; + auto texture = new Texture2D; +#if (CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID) && (CC_TARGET_PLATFORM != CC_PLATFORM_IOS) + if (_fontDefinition._shadow._shadowEnabled || _fontDefinition._stroke._strokeEnabled) + { + CCLOGERROR("Currently only supported on iOS and Android!"); + } + _fontDefinition._shadow._shadowEnabled = false; + _fontDefinition._stroke._strokeEnabled = false; +#endif + texture->initWithString(_originalUTF8String.c_str(),_fontDefinition); + + _textSprite = Sprite::createWithTexture(texture); + _textSprite->setAnchorPoint(Point::ANCHOR_BOTTOM_LEFT); + this->setContentSize(_textSprite->getContentSize()); + texture->release(); + + Node::addChild(_textSprite,0,Node::INVALID_TAG); +} + +void Label::updateContent() +{ + auto utf16String = cc_utf8_to_utf16(_originalUTF8String.c_str()); + setCurrentString(utf16String); + setOriginalString(utf16String); + if (_textSprite) + { + Node::removeChild(_textSprite,true); + _textSprite = nullptr; + } + if (_fontAtlas) + { + alignText(); + } + else + { + createSpriteWithFontDefinition(); + } + _contentDirty = false; +} + void Label::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) { if (! _visible) { return; } + if (_contentDirty) + { + updateContent(); + } - if (_currLabelEffect == LabelEffect::SHADOW && _shadowBlurRadius <= 0) + if (! _textSprite && _currLabelEffect == LabelEffect::SHADOW && _shadowBlurRadius <= 0) { _parentTransform = parentTransform; draw(renderer, _modelViewTransform, true); @@ -871,7 +965,14 @@ void Label::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parent kmGLPushMatrix(); kmGLLoadMatrix(&_modelViewTransform); - draw(renderer, _modelViewTransform, dirty); + if (_textSprite) + { + _textSprite->visit(); + } + else + { + draw(renderer, _modelViewTransform, dirty); + } kmGLPopMatrix(); } @@ -879,12 +980,53 @@ void Label::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parent setOrderOfArrival(0); } +void Label::setFontName(const std::string& fontName) +{ + _fontDefinition._fontName = fontName; + if (fontName.find('.') != fontName.npos) + { + auto config = _fontConfig; + config.fontFilePath = fontName; + setTTFConfig(config); + } + _contentDirty = true; +} + +void Label::setFontSize(int fontSize) +{ + if (_currentLabelType == LabelType::TTF) + { + if (_fontConfig.distanceFieldEnabled) + { + _fontConfig.fontSize = fontSize; + this->setFontScale(1.0f * fontSize / DefultFontSize); + } + else + { + auto fontConfig = _fontConfig; + fontConfig.fontSize = fontSize; + setTTFConfig(fontConfig); + } + } + else + { + _fontDefinition._fontSize = fontSize; + _fontConfig.fontSize = fontSize; + _contentDirty = true; + } +} + ///// PROTOCOL STUFF Sprite * Label::getLetter(int lettetIndex) { - if (lettetIndex < _limitShowCount) + if (_contentDirty) { - if(_lettersInfo[lettetIndex].def.validDefinition == false) + updateContent(); + } + + if (! _textSprite && lettetIndex < _limitShowCount) + { + if(! _lettersInfo[lettetIndex].def.validDefinition) return nullptr; Sprite* sp = static_cast(this->getChildByTag(lettetIndex)); @@ -913,13 +1055,7 @@ Sprite * Label::getLetter(int lettetIndex) int Label::getCommonLineHeight() const { - return _commonLineHeight; -} - -// string related stuff -int Label::getStringNumLines() const -{ - return _currNumLines; + return _textSprite ? 0 : _commonLineHeight; } void Label::computeStringNumLines() @@ -969,6 +1105,11 @@ void Label::setOpacityModifyRGB(bool isOpacityModifyRGB) void Label::setColor(const Color3B& color) { + _fontDefinition._fontFillColor = color; + if (_textSprite) + { + updateContent(); + } _reusedLetter->setColor(color); SpriteBatchNode::setColor(color); } @@ -1014,4 +1155,12 @@ std::string Label::getDescription() const return StringUtils::format("