public int DrawText(string text, float textScale, TextAlign textAlign, Vector4 color, idRectangle rectDraw, bool wrap, int cursor = -1, bool calcOnly = false, List<int> breaks = null, int limit = 0)
{
float textWidth = 0;
float charSkip = MaxCharacterWidth(textScale) + 1;
float lineSkip = MaxCharacterHeight(textScale);
float cursorSkip = (cursor >= 0) ? charSkip : 0;
SetFontByScale(textScale);
// TODO: edit cursor
/*if (!calcOnly && !(text && *text)) {
if (cursor == 0) {
renderSystem->SetColor(color);
DrawEditCursor(rectDraw.x, lineSkip + rectDraw.y, textScale);
}
return idMath::FtoiFast( rectDraw.w / charSkip );
}*/
char c;
int textPosition = 0;
int length = 0, newLine = 0, newLineWidth = 0, newLinePosition = 0, count = 0;
bool lineBreak = false;
bool wordBreak = false;
float y = lineSkip + rectDraw.Y;
StringBuilder buffer = new StringBuilder();
if(breaks != null)
{
breaks.Add(0);
}
while(true)
{
c = idHelper.GetBufferCharacter(text, textPosition);
if((c == '\n') || (c == '\r') || (c == '\0'))
{
lineBreak = true;
if(((c == '\n') && (idHelper.GetBufferCharacter(text, textPosition + 1) == '\r'))
|| ((c == '\r') && (idHelper.GetBufferCharacter(text, textPosition + 1) == '\n')))
{
textPosition++;
c = idHelper.GetBufferCharacter(text, textPosition);
}
}
int nextCharWidth = (int) ((idHelper.CharacterIsPrintable(c) == true) ? GetCharacterWidth(c, textScale) : cursorSkip);
// FIXME: this is a temp hack until the guis can be fixed not not overflow the bounding rectangles
// the side-effect is that list boxes and edit boxes will draw over their scroll bars
// The following line and the !linebreak in the if statement below should be removed
nextCharWidth = 0;
if((lineBreak == false) && ((textWidth + nextCharWidth) > rectDraw.Width))
{
// the next character will cause us to overflow, if we haven't yet found a suitable
// break spot, set it to be this character
if((length > 0) && (newLine == 0))
{
newLine = length;
newLinePosition = textPosition;
newLineWidth = (int) textWidth;
}
wordBreak = true;
}
else if((lineBreak == true) || ((wrap == true) && ((c == ' ') || (c == '\t'))))
{
// The next character is in view, so if we are a break character, store our position
newLine = length;
newLinePosition = textPosition + 1;
newLineWidth = (int) textWidth;
}
if((lineBreak == true) || (wordBreak == true))
{
float x = rectDraw.X;
if(textAlign == TextAlign.Right)
{
x = rectDraw.X + rectDraw.Width - newLineWidth;
}
else if(textAlign == TextAlign.Center)
{
x = rectDraw.X + ((rectDraw.Width - newLineWidth) / 2);
}
if((wrap == true) || (newLine > 0))
{
// this is a special case to handle breaking in the middle of a word.
// if we didn't do this, the cursor would appear on the end of this line
// and the beginning of the next
if((wordBreak == true) && (cursor >= newLine) && (newLine == length))
{
cursor++;
}
}
if(calcOnly == false)
{
count += DrawText(x, y, textScale, color, buffer.ToString(0, (newLine > 0) ? newLine : length), 0, 0, 0, cursor);
buffer.Clear();
}
if(cursor < newLine)
{
cursor = -1;
}
else if(cursor >= 0)
{
cursor -= (newLine + 1);
}
if(wrap == false)
{
return newLine;
}
if(((limit > 0) && (count > limit)) || (c == '\0'))
{
break;
}
y += lineSkip + 5;
if((calcOnly == false) && (y > rectDraw.Bottom))
{
break;
}
textPosition = newLinePosition;
if(breaks != null)
{
breaks.Add(textPosition);
}
length = 0;
newLine = 0;
newLineWidth = 0;
textWidth = 0;
lineBreak = false;
wordBreak = false;
}
else
{
length++;
buffer.Append(idHelper.GetBufferCharacter(text, textPosition++));
// update the width
if((buffer[length - 1] != (int) idColorIndex.Escape)
&& ((length <= 1) || (buffer[length - 2] != (int) idColorIndex.Escape)))
{
byte c2 = (byte) buffer[length - 1];
textWidth += textScale * _currentFont.GlyphScale * _currentFont.Glyphs[(char) c2].SkipX;
}
}
}
return (int) (rectDraw.Width / charSkip);
}