private List <CharLocation> ArrangeCharsInArea(float width, float height, string text, float size, HAlign hAlign, VAlign vAlign, bool autoScale, bool kerning)
{
if (text.Length == 0)
{
return(new List <CharLocation>());
}
if (size < 0)
{
size *= -_size;
}
bool isFinished = false;
float scale = 0;
float containerWidth = 0;
float containerHeight = 0;
List <List <CharLocation> > lines = new List <List <CharLocation> >();
while (!isFinished)
{
scale = size / _size;
containerWidth = width / scale;
containerHeight = height / scale;
if (_lineHeight <= containerHeight)
{
int lastWhiteSpace = -1;
int lastCharId = -1;
int numChars = text.Length;
float currentX = 0;
float currentY = 0;
List <CharLocation> currentLine = new List <CharLocation>();
for (int i = 0; i < numChars; i++)
{
bool isLineFull = false;
int charId = text[i];
BitmapChar bitmapChar = CharById(charId);
if (charId == NewLineAsciiCode || charId == CarriageReturnAsciiCode)
{
isLineFull = true;
}
else if (bitmapChar == null)
{
Console.WriteLine("Missing character: " + charId);
}
else
{
if (charId == SpaceAsciiCode || charId == TabAsciiCode)
{
lastWhiteSpace = i;
}
if (kerning)
{
currentX += bitmapChar.KerningToChar(lastCharId);
}
CharLocation charLocation = CharLocation.Create(bitmapChar, 1.0f, currentX + bitmapChar.XOffset, currentY + bitmapChar.YOffset);
currentLine.Add(charLocation);
currentX += bitmapChar.XAdvance;
lastCharId = charId;
if (charLocation.X + bitmapChar.Width > containerWidth)
{
int numCharsToRemove = (lastWhiteSpace == -1) ? 1 : i - lastWhiteSpace;
int removeIndex = currentLine.Count - numCharsToRemove;
currentLine.RemoveRange(removeIndex, numCharsToRemove);
if (currentLine.Count == 0)
{
break;
}
i -= numCharsToRemove;
isLineFull = true;
}
}
if (i == numChars - 1)
{
lines.Add(currentLine);
isFinished = true;
}
else if (isLineFull)
{
lines.Add(currentLine);
if (lastWhiteSpace == i)
{
currentLine.RemoveAt(currentLine.Count - 1);
}
if (currentY + 2 * _lineHeight <= containerHeight)
{
currentLine = new List <CharLocation>();
currentX = 0;
currentY += _lineHeight;
lastWhiteSpace = -1;
lastCharId = -1;
}
else
{
break;
}
}
}
}
if (autoScale && !isFinished)
{
size -= 1;
lines.Clear();
}
else
{
isFinished = true;
}
}
List <CharLocation> finalLocations = new List <CharLocation>();
int numLines = lines.Count;
float bottom = numLines * _lineHeight;
int yOffset = 0;
if (vAlign == VAlign.Bottom)
{
yOffset = (int)(containerHeight - bottom);
}
else if (vAlign == VAlign.Center)
{
yOffset = (int)((containerHeight - bottom) / 2);
}
List <CharLocation> line;
for (int i = 0; i < lines.Count; i++)
{
line = lines[i];
int numChars = line.Count;
if (numChars == 0)
{
continue;
}
int xOffset = 0;
CharLocation lastLocation = line[line.Count - 1];
float right = lastLocation.X - lastLocation.BitmapChar.XOffset + lastLocation.BitmapChar.XAdvance;
if (hAlign == HAlign.Right)
{
xOffset = (int)(containerWidth - right);
}
else if (hAlign == HAlign.Center)
{
xOffset = (int)((containerWidth - right) / 2);
}
CharLocation charLocation;
for (int j = 0; j < line.Count; j++)
{
charLocation = line[j];
charLocation.X = scale * (charLocation.X + xOffset);
charLocation.Y = scale * (charLocation.Y + yOffset);
charLocation.Scale = scale;
if (charLocation.BitmapChar.Width > 0 && charLocation.BitmapChar.Height > 0)
{
finalLocations.Add(charLocation);
}
}
}
return(finalLocations);
}