mirror of https://github.com/axmolengine/axmol.git
Merge pull request #15863 from zilongshanren/fix-word-clamp-with-only-one-word-left
fix TTF and BMFont word wrap
This commit is contained in:
commit
0db0a45fa0
|
@ -676,6 +676,8 @@ protected:
|
||||||
bool isHorizontalClamped(float letterPositionX, int lineInex);
|
bool isHorizontalClamped(float letterPositionX, int lineInex);
|
||||||
void restoreFontSize();
|
void restoreFontSize();
|
||||||
void updateLetterSpriteScale(Sprite* sprite);
|
void updateLetterSpriteScale(Sprite* sprite);
|
||||||
|
int getFirstCharLen(const std::u16string& utf16Text, int startIndex, int textLen);
|
||||||
|
int getFirstWordLen(const std::u16string& utf16Text, int startIndex, int textLen);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Copyright (c) 2013 Zynga Inc.
|
Copyright (c) 2013 Zynga Inc.
|
||||||
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
||||||
|
|
||||||
http://www.cocos2d-x.org
|
http://www.cocos2d-x.org
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in
|
||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
@ -72,12 +72,12 @@ void Label::computeAlignmentOffset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getFirstCharLen(const std::u16string& utf16Text, int startIndex, int textLen)
|
int Label::getFirstCharLen(const std::u16string& utf16Text, int startIndex, int textLen)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getFirstWordLen(const std::u16string& utf16Text, int startIndex, int textLen)
|
int Label::getFirstWordLen(const std::u16string& utf16Text, int startIndex, int textLen)
|
||||||
{
|
{
|
||||||
auto character = utf16Text[startIndex];
|
auto character = utf16Text[startIndex];
|
||||||
if (StringUtils::isCJKUnicode(character) || StringUtils::isUnicodeSpace(character) || character == (char16_t)TextFormatter::NewLine)
|
if (StringUtils::isCJKUnicode(character) || StringUtils::isUnicodeSpace(character) || character == (char16_t)TextFormatter::NewLine)
|
||||||
|
@ -86,16 +86,35 @@ static int getFirstWordLen(const std::u16string& utf16Text, int startIndex, int
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = 1;
|
int len = 1;
|
||||||
|
FontLetterDefinition letterDef;
|
||||||
|
auto nextLetterX = 0;
|
||||||
|
auto contentScaleFactor = CC_CONTENT_SCALE_FACTOR();
|
||||||
for (int index = startIndex + 1; index < textLen; ++index)
|
for (int index = startIndex + 1; index < textLen; ++index)
|
||||||
{
|
{
|
||||||
character = utf16Text[index];
|
character = utf16Text[index];
|
||||||
|
if (_fontAtlas->getLetterDefinitionForChar(character, letterDef) == false)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto letterX = (nextLetterX + letterDef.offsetX * _bmfontScale) / contentScaleFactor;
|
||||||
|
if (_maxLineWidth > 0.f && letterX + letterDef.width * _bmfontScale > _maxLineWidth
|
||||||
|
&& !StringUtils::isUnicodeSpace(character))
|
||||||
|
{
|
||||||
|
if(len >= 2) {
|
||||||
|
return len -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nextLetterX += letterDef.xAdvance * _bmfontScale + _additionalKerning;
|
||||||
|
|
||||||
if (character == (char16_t)TextFormatter::NewLine || StringUtils::isUnicodeSpace(character) || StringUtils::isCJKUnicode(character))
|
if (character == (char16_t)TextFormatter::NewLine || StringUtils::isUnicodeSpace(character) || StringUtils::isCJKUnicode(character))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +138,7 @@ bool Label::multilineTextWrap(std::function<int(const std::u16string&, int, int)
|
||||||
float nextTokenY = 0.f;
|
float nextTokenY = 0.f;
|
||||||
float longestLine = 0.f;
|
float longestLine = 0.f;
|
||||||
float letterRight = 0.f;
|
float letterRight = 0.f;
|
||||||
|
|
||||||
auto contentScaleFactor = CC_CONTENT_SCALE_FACTOR();
|
auto contentScaleFactor = CC_CONTENT_SCALE_FACTOR();
|
||||||
float lineSpacing = _lineSpacing * contentScaleFactor;
|
float lineSpacing = _lineSpacing * contentScaleFactor;
|
||||||
float highestY = 0.f;
|
float highestY = 0.f;
|
||||||
|
@ -127,9 +146,9 @@ bool Label::multilineTextWrap(std::function<int(const std::u16string&, int, int)
|
||||||
FontLetterDefinition letterDef;
|
FontLetterDefinition letterDef;
|
||||||
Vec2 letterPosition;
|
Vec2 letterPosition;
|
||||||
bool nextChangeSize = true;
|
bool nextChangeSize = true;
|
||||||
|
|
||||||
this->updateBMFontScale();
|
this->updateBMFontScale();
|
||||||
|
|
||||||
for (int index = 0; index < textLen; )
|
for (int index = 0; index < textLen; )
|
||||||
{
|
{
|
||||||
auto character = _utf16Text[index];
|
auto character = _utf16Text[index];
|
||||||
|
@ -144,7 +163,7 @@ bool Label::multilineTextWrap(std::function<int(const std::u16string&, int, int)
|
||||||
index++;
|
index++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tokenLen = nextTokenLen(_utf16Text, index, textLen);
|
auto tokenLen = nextTokenLen(_utf16Text, index, textLen);
|
||||||
float tokenHighestY = highestY;;
|
float tokenHighestY = highestY;;
|
||||||
float tokenLowestY = lowestY;
|
float tokenLowestY = lowestY;
|
||||||
|
@ -173,7 +192,7 @@ bool Label::multilineTextWrap(std::function<int(const std::u16string&, int, int)
|
||||||
CCLOG("LabelTextFormatter error:can't find letter definition in font file for letter: %c", character);
|
CCLOG("LabelTextFormatter error:can't find letter definition in font file for letter: %c", character);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto letterX = (nextLetterX + letterDef.offsetX * _bmfontScale) / contentScaleFactor;
|
auto letterX = (nextLetterX + letterDef.offsetX * _bmfontScale) / contentScaleFactor;
|
||||||
if (_enableWrap && _maxLineWidth > 0.f && nextTokenX > 0.f && letterX + letterDef.width * _bmfontScale > _maxLineWidth
|
if (_enableWrap && _maxLineWidth > 0.f && nextTokenX > 0.f && letterX + letterDef.width * _bmfontScale > _maxLineWidth
|
||||||
&& !StringUtils::isUnicodeSpace(character) && nextChangeSize)
|
&& !StringUtils::isUnicodeSpace(character) && nextChangeSize)
|
||||||
|
@ -192,28 +211,28 @@ bool Label::multilineTextWrap(std::function<int(const std::u16string&, int, int)
|
||||||
}
|
}
|
||||||
letterPosition.y = (nextTokenY - letterDef.offsetY * _bmfontScale) / contentScaleFactor;
|
letterPosition.y = (nextTokenY - letterDef.offsetY * _bmfontScale) / contentScaleFactor;
|
||||||
recordLetterInfo(letterPosition, character, letterIndex, lineIndex);
|
recordLetterInfo(letterPosition, character, letterIndex, lineIndex);
|
||||||
|
|
||||||
if (nextChangeSize)
|
if (nextChangeSize)
|
||||||
{
|
{
|
||||||
if (_horizontalKernings && letterIndex < textLen - 1)
|
if (_horizontalKernings && letterIndex < textLen - 1)
|
||||||
nextLetterX += _horizontalKernings[letterIndex + 1];
|
nextLetterX += _horizontalKernings[letterIndex + 1];
|
||||||
nextLetterX += letterDef.xAdvance * _bmfontScale + _additionalKerning;
|
nextLetterX += letterDef.xAdvance * _bmfontScale + _additionalKerning;
|
||||||
|
|
||||||
tokenRight = letterPosition.x + letterDef.width * _bmfontScale;
|
tokenRight = letterPosition.x + letterDef.width * _bmfontScale;
|
||||||
}
|
}
|
||||||
nextChangeSize = true;
|
nextChangeSize = true;
|
||||||
|
|
||||||
if (tokenHighestY < letterPosition.y)
|
if (tokenHighestY < letterPosition.y)
|
||||||
tokenHighestY = letterPosition.y;
|
tokenHighestY = letterPosition.y;
|
||||||
if (tokenLowestY > letterPosition.y - letterDef.height * _bmfontScale)
|
if (tokenLowestY > letterPosition.y - letterDef.height * _bmfontScale)
|
||||||
tokenLowestY = letterPosition.y - letterDef.height * _bmfontScale;
|
tokenLowestY = letterPosition.y - letterDef.height * _bmfontScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newLine)
|
if (newLine)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextTokenX = nextLetterX;
|
nextTokenX = nextLetterX;
|
||||||
letterRight = tokenRight;
|
letterRight = tokenRight;
|
||||||
if (highestY < tokenHighestY)
|
if (highestY < tokenHighestY)
|
||||||
|
@ -222,12 +241,12 @@ bool Label::multilineTextWrap(std::function<int(const std::u16string&, int, int)
|
||||||
lowestY = tokenLowestY;
|
lowestY = tokenLowestY;
|
||||||
if (longestLine < letterRight)
|
if (longestLine < letterRight)
|
||||||
longestLine = letterRight;
|
longestLine = letterRight;
|
||||||
|
|
||||||
index += tokenLen;
|
index += tokenLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
_linesWidth.push_back(letterRight);
|
_linesWidth.push_back(letterRight);
|
||||||
|
|
||||||
_numberOfLines = lineIndex + 1;
|
_numberOfLines = lineIndex + 1;
|
||||||
_textDesiredHeight = (_numberOfLines * _lineHeight * _bmfontScale) / contentScaleFactor;
|
_textDesiredHeight = (_numberOfLines * _lineHeight * _bmfontScale) / contentScaleFactor;
|
||||||
if (_numberOfLines > 1)
|
if (_numberOfLines > 1)
|
||||||
|
@ -238,25 +257,25 @@ bool Label::multilineTextWrap(std::function<int(const std::u16string&, int, int)
|
||||||
if (_labelHeight <= 0.f)
|
if (_labelHeight <= 0.f)
|
||||||
contentSize.height = _textDesiredHeight;
|
contentSize.height = _textDesiredHeight;
|
||||||
setContentSize(contentSize);
|
setContentSize(contentSize);
|
||||||
|
|
||||||
_tailoredTopY = contentSize.height;
|
_tailoredTopY = contentSize.height;
|
||||||
_tailoredBottomY = 0.f;
|
_tailoredBottomY = 0.f;
|
||||||
if (highestY > 0.f)
|
if (highestY > 0.f)
|
||||||
_tailoredTopY = contentSize.height + highestY;
|
_tailoredTopY = contentSize.height + highestY;
|
||||||
if (lowestY < -_textDesiredHeight)
|
if (lowestY < -_textDesiredHeight)
|
||||||
_tailoredBottomY = _textDesiredHeight + lowestY;
|
_tailoredBottomY = _textDesiredHeight + lowestY;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Label::multilineTextWrapByWord()
|
bool Label::multilineTextWrapByWord()
|
||||||
{
|
{
|
||||||
return multilineTextWrap(std::bind(getFirstWordLen, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
return multilineTextWrap(std::bind(CC_CALLBACK_3(Label::getFirstWordLen, this), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Label::multilineTextWrapByChar()
|
bool Label::multilineTextWrapByChar()
|
||||||
{
|
{
|
||||||
return multilineTextWrap(std::bind(getFirstCharLen, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
return multilineTextWrap(std::bind(CC_CALLBACK_3(Label::getFirstCharLen, this) , std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Label::isVerticalClamp()
|
bool Label::isVerticalClamp()
|
||||||
|
@ -279,7 +298,7 @@ bool Label::isHorizontalClamp()
|
||||||
if (_lettersInfo[ctr].valid)
|
if (_lettersInfo[ctr].valid)
|
||||||
{
|
{
|
||||||
auto& letterDef = _fontAtlas->_letterDefinitions[_lettersInfo[ctr].utf16Char];
|
auto& letterDef = _fontAtlas->_letterDefinitions[_lettersInfo[ctr].utf16Char];
|
||||||
|
|
||||||
auto px = _lettersInfo[ctr].positionX + letterDef.width/2 * _bmfontScale;
|
auto px = _lettersInfo[ctr].positionX + letterDef.width/2 * _bmfontScale;
|
||||||
auto lineIndex = _lettersInfo[ctr].lineIndex;
|
auto lineIndex = _lettersInfo[ctr].lineIndex;
|
||||||
|
|
||||||
|
@ -298,18 +317,18 @@ bool Label::isHorizontalClamp()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return letterClamp;
|
return letterClamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Label::shrinkLabelToContentSize(std::function<bool(void)> lambda)
|
void Label::shrinkLabelToContentSize(std::function<bool(void)> lambda)
|
||||||
{
|
{
|
||||||
float fontSize = this->getRenderingFontSize();
|
float fontSize = this->getRenderingFontSize();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
auto letterDefinition = _fontAtlas->_letterDefinitions;
|
auto letterDefinition = _fontAtlas->_letterDefinitions;
|
||||||
auto tempLetterDefinition = letterDefinition;
|
auto tempLetterDefinition = letterDefinition;
|
||||||
|
|
Loading…
Reference in New Issue