bool Label::multilineTextWrapByWord() { int textLen = getStringLength(); int lineIndex = 0; float nextWordX = 0.f; float nextWordY = 0.f; float longestLine = 0.f; float letterRight = 0.f; auto contentScaleFactor = CC_CONTENT_SCALE_FACTOR(); float highestY = 0.f; float lowestY = 0.f; FontLetterDefinition letterDef; Vec2 letterPosition; for (int index = 0; index < textLen; ) { auto character = _utf16Text[index]; if (character == '\n') { _linesWidth.push_back(letterRight); letterRight = 0.f; lineIndex++; nextWordX = 0.f; nextWordY -= _lineHeight; recordPlaceholderInfo(index, character); index++; continue; } auto wordLen = getFirstWordLen(_utf16Text, index, textLen); float wordHighestY = highestY;; float wordLowestY = lowestY; float wordRight = letterRight; float nextLetterX = nextWordX; bool newLine = false; for (int tmp = 0; tmp < wordLen;++tmp) { int letterIndex = index + tmp; character = _utf16Text[letterIndex]; if (_fontAtlas->getLetterDefinitionForChar(character, letterDef) == false) { recordPlaceholderInfo(letterIndex, character); CCLOG("LabelTextFormatter error:can't find letter definition in font file for letter: %c", character); continue; } auto letterX = (nextLetterX + letterDef.offsetX) / contentScaleFactor; if (_maxLineWidth > 0.f && nextWordX > 0.f && letterX + letterDef.width > _maxLineWidth) { _linesWidth.push_back(letterRight); letterRight = 0.f; lineIndex++; nextWordX = 0.f; nextWordY -= _lineHeight; newLine = true; break; } else { letterPosition.x = letterX; } letterPosition.y = (nextWordY - letterDef.offsetY) / contentScaleFactor; recordLetterInfo(letterPosition, character, letterIndex, lineIndex); if (_horizontalKernings && letterIndex < textLen - 1) nextLetterX += _horizontalKernings[letterIndex + 1]; nextLetterX += letterDef.xAdvance + _additionalKerning; wordRight = letterPosition.x + letterDef.width; if (wordHighestY < letterPosition.y) wordHighestY = letterPosition.y; if (wordLowestY > letterPosition.y - letterDef.height) wordLowestY = letterPosition.y - letterDef.height; } if (newLine) { continue; } nextWordX = nextLetterX; letterRight = wordRight; if (highestY < wordHighestY) highestY = wordHighestY; if (lowestY > wordLowestY) lowestY = wordLowestY; if (longestLine < letterRight) longestLine = letterRight; index += wordLen; } _linesWidth.push_back(letterRight); _numberOfLines = lineIndex + 1; _textDesiredHeight = (_numberOfLines * _lineHeight) / contentScaleFactor; Size contentSize(_labelWidth, _labelHeight); if (_labelWidth <= 0.f) contentSize.width = longestLine; if (_labelHeight <= 0.f) contentSize.height = _textDesiredHeight; setContentSize(contentSize); _tailoredTopY = contentSize.height; _tailoredBottomY = 0.f; if (highestY > 0.f) _tailoredTopY = contentSize.height + highestY; if (lowestY < -_textDesiredHeight) _tailoredBottomY = _textDesiredHeight + lowestY; return true; }
bool Label::multilineTextWrap(const std::function<int(const std::u16string&, int, int)>& nextTokenLen) { int textLen = getStringLength(); int lineIndex = 0; float nextTokenX = 0.f; float nextTokenY = 0.f; float longestLine = 0.f; float letterRight = 0.f; auto contentScaleFactor = CC_CONTENT_SCALE_FACTOR(); float lineSpacing = _lineSpacing * contentScaleFactor; float highestY = 0.f; float lowestY = 0.f; FontLetterDefinition letterDef; Vec2 letterPosition; bool nextChangeSize = true; this->updateBMFontScale(); for (int index = 0; index < textLen; ) { auto character = _utf16Text[index]; if (character == (char16_t)TextFormatter::NewLine) { _linesWidth.push_back(letterRight); letterRight = 0.f; lineIndex++; nextTokenX = 0.f; nextTokenY -= _lineHeight*_bmfontScale + lineSpacing; recordPlaceholderInfo(index, character); index++; continue; } auto tokenLen = nextTokenLen(_utf16Text, index, textLen); float tokenHighestY = highestY;; float tokenLowestY = lowestY; float tokenRight = letterRight; float nextLetterX = nextTokenX; bool newLine = false; for (int tmp = 0; tmp < tokenLen;++tmp) { int letterIndex = index + tmp; character = _utf16Text[letterIndex]; if (character == (char16_t)TextFormatter::CarriageReturn) { recordPlaceholderInfo(letterIndex, character); continue; } // \b - Next char not change x position if (character == (char16_t)TextFormatter::NextCharNoChangeX) { nextChangeSize = false; recordPlaceholderInfo(letterIndex, character); continue; } if (_fontAtlas->getLetterDefinitionForChar(character, letterDef) == false) { recordPlaceholderInfo(letterIndex, character); CCLOG("LabelTextFormatter error:can't find letter definition in font file for letter: %c", character); continue; } auto letterX = (nextLetterX + letterDef.offsetX * _bmfontScale) / contentScaleFactor; if (_enableWrap && _maxLineWidth > 0.f && nextTokenX > 0.f && letterX + letterDef.width * _bmfontScale > _maxLineWidth && !StringUtils::isUnicodeSpace(character) && nextChangeSize) { _linesWidth.push_back(letterRight); letterRight = 0.f; lineIndex++; nextTokenX = 0.f; nextTokenY -= (_lineHeight*_bmfontScale + lineSpacing); newLine = true; break; } else { letterPosition.x = letterX; } letterPosition.y = (nextTokenY - letterDef.offsetY * _bmfontScale) / contentScaleFactor; recordLetterInfo(letterPosition, character, letterIndex, lineIndex); if (nextChangeSize) { if (_horizontalKernings && letterIndex < textLen - 1) nextLetterX += _horizontalKernings[letterIndex + 1]; nextLetterX += letterDef.xAdvance * _bmfontScale + _additionalKerning; tokenRight = nextLetterX / contentScaleFactor; } nextChangeSize = true; if (tokenHighestY < letterPosition.y) tokenHighestY = letterPosition.y; if (tokenLowestY > letterPosition.y - letterDef.height * _bmfontScale) tokenLowestY = letterPosition.y - letterDef.height * _bmfontScale; } if (newLine) { continue; } nextTokenX = nextLetterX; letterRight = tokenRight; if (highestY < tokenHighestY) highestY = tokenHighestY; if (lowestY > tokenLowestY) lowestY = tokenLowestY; if (longestLine < letterRight) longestLine = letterRight; index += tokenLen; } _linesWidth.push_back(letterRight); _numberOfLines = lineIndex + 1; _textDesiredHeight = (_numberOfLines * _lineHeight * _bmfontScale) / contentScaleFactor; if (_numberOfLines > 1) _textDesiredHeight += (_numberOfLines - 1) * _lineSpacing; Size contentSize(_labelWidth, _labelHeight); if (_labelWidth <= 0.f) contentSize.width = longestLine; if (_labelHeight <= 0.f) contentSize.height = _textDesiredHeight; setContentSize(contentSize); _tailoredTopY = contentSize.height; _tailoredBottomY = 0.f; if (highestY > 0.f) _tailoredTopY = contentSize.height + highestY; if (lowestY < -_textDesiredHeight) _tailoredBottomY = _textDesiredHeight + lowestY; return true; }