/// <summary>
/// Text wrapping functionality. The 'width' and 'height' should be in pixels.
/// </summary>
static public bool WrapText (string text, out string finalText, bool keepCharCount)
{
if (rectWidth < 1 || rectHeight < 1 || finalLineHeight < 1f)
{
finalText = "";
return false;
}
float height = (maxLines > 0) ? Mathf.Min(rectHeight, finalLineHeight * maxLines) : rectHeight;
int maxLineCount = (maxLines > 0) ? maxLines : 1000000;
maxLineCount = Mathf.FloorToInt(Mathf.Min(maxLineCount, height / finalLineHeight) + 0.01f);
if (maxLineCount == 0)
{
finalText = "";
return false;
}
if (string.IsNullOrEmpty(text)) text = " ";
Prepare(text);
StringBuilder sb
= new StringBuilder
(); int textLength = text.Length;
float remainingWidth = rectWidth;
int start = 0, offset = 0, lineCount = 1, prev = 0;
bool lineIsEmpty = true;
// Run through all characters
for (; offset < textLength; ++offset)
{
char ch = text[offset];
// New line character -- start a new line
if (ch == '\n')
{
if (lineCount == maxLineCount) break;
remainingWidth = rectWidth;
// Add the previous word to the final string
if (start < offset) sb.Append(text.Substring(start, offset - start + 1));
else sb.Append(ch);
lineIsEmpty = true;
++lineCount;
start = offset + 1;
prev = 0;
continue;
}
// When encoded symbols such as [RrGgBb] or [-] are encountered, skip past them
if (encoding && ParseSymbol(text, ref offset)) { --offset; continue; }
// See if there is a symbol matching this text
BMSymbol symbol = useSymbols ? GetSymbol(text, offset, textLength) : null;
// Calculate how wide this symbol or character is going to be
float glyphWidth;
if (symbol == null)
{
// Find the glyph for this character
float w = GetGlyphWidth(ch, prev);
if (w == 0f) continue;
glyphWidth = finalSpacingX + w;
}
else glyphWidth = finalSpacingX + symbol.advance * fontScale;
// Reduce the width
remainingWidth -= glyphWidth;
// If this marks the end of a word, add it to the final string.
if (ch == ' ')
{
if (prev == ' ')
{
sb.Append(' ');
start = offset + 1;
}
else if (prev != ' ' && start < offset)
{
int end = offset - start + 1;
// Last word on the last line should not include an invisible character
if (lineCount == maxLineCount && remainingWidth <= 0f && offset < textLength && text[offset] <= ' ') --end;
sb.Append(text.Substring(start, end));
lineIsEmpty = false;
start = offset + 1;
prev = ch;
}
}
// Doesn't fit?
if (remainingWidth < 0f)
{
// Can't start a new line
if (lineIsEmpty || lineCount == maxLineCount)
{
// This is the first word on the line -- add it up to the character that fits
sb.Append(text.Substring(start, Mathf.Max(0, offset - start)));
if (lineCount++ == maxLineCount)
{
start = offset;
break;
}
if (keepCharCount) ReplaceSpaceWithNewline(ref sb);
else EndLine(ref sb);
// Start a brand-new line
lineIsEmpty = true;
if (ch == ' ')
{
start = offset + 1;
remainingWidth = rectWidth;
}
else
{
start = offset;
remainingWidth = rectWidth - glyphWidth;
}
prev = 0;
}
else
{
// Revert the position to the beginning of the word and reset the line
lineIsEmpty = true;
remainingWidth = rectWidth;
offset = start - 1;
prev = 0;
if (lineCount++ == maxLineCount) break;
if (keepCharCount) ReplaceSpaceWithNewline(ref sb);
else EndLine(ref sb);
continue;
}
}
else prev = ch;
// Advance the offset past the symbol
if (symbol != null)
{
offset += symbol.length - 1;
prev = 0;
}
}
if (start < offset) sb.Append(text.Substring(start, offset - start));
finalText = sb.ToString();
return (offset == textLength) || (lineCount <= Mathf.Min(maxLines, maxLineCount));
}