/** Draws text into a QuadBatch. */ public void FillMeshBatch(MeshBatch meshBatch, float width, float height, string text, TextFormat format, TextOptions options = null) { List <CharLocation> charLocations = ArrangeChars( width, height, text, format, options); int numChars = charLocations.Count; _helperImage.Color = format.Color; for (int i = 0; i < numChars; ++i) { CharLocation charLocation = charLocations[i]; _helperImage.Texture = charLocation.Char.Texture; _helperImage.ReadjustSize(); _helperImage.X = charLocation.X; _helperImage.Y = charLocation.Y; _helperImage.Scale = charLocation.Scale; meshBatch.AddMesh(_helperImage); } }
private List <CharLocation> ArrangeChars(float width, float height, string text, TextFormat format, TextOptions options) { if (text.Length == 0) { return(new List <CharLocation>()); } if (options == null) { options = sDefaultOptions; } bool kerning = format.Kerning; float leading = format.Leading; HAlign hAlign = format.HorizontalAlign; VAlign vAlign = format.VerticalAlign; float fontSize = format.Size; bool autoScale = options.AutoScale; bool wordWrap = options.WordWrap; bool finished = false; CharLocation charLocation; int numChars; float containerWidth = 0; float containerHeight = 0; float scale = 0; int i; if (fontSize < 0f) { fontSize *= -Size; } float currentY = 0; while (!finished) { sLines.Clear(); scale = fontSize / Size; containerWidth = (width - 2 * Padding) / scale; containerHeight = (height - 2 * Padding) / scale; if (LineHeight <= containerHeight) { int lastWhiteSpace = -1; int lastCharId = -1; float currentX = 0; currentY = 0; List <CharLocation> currentLine = new List <CharLocation>(); numChars = text.Length; for (i = 0; i < numChars; i++) { bool lineFull = false; int charId = text[i]; // casting to int automatically returns the ASCII value BitmapChar bitmapChar = GetChar(charId); if (charId == CHAR_NEWLINE || charId == CHAR_CARRIAGE_RETURN) { lineFull = true; } else if (bitmapChar == null) { Debug.WriteLine("font " + Name + " missing character: " + text[i] + " ID:" + charId); } else { if (charId == CHAR_SPACE || charId == CHAR_TAB) { lastWhiteSpace = i; } if (kerning) { currentX += bitmapChar.GetKerning(lastCharId); } 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) { if (wordWrap) { // when autoscaling, we must not split a word in half -> restart if (autoScale && lastWhiteSpace == -1) { break; } // remove characters and add them again to next line int numCharsToRemove = lastWhiteSpace == -1 ? 1 : i - lastWhiteSpace; currentLine.RemoveRange(currentLine.Count - numCharsToRemove, numCharsToRemove); if (currentLine.Count == 0) { break; } i -= numCharsToRemove; } else { if (autoScale) { break; } currentLine.RemoveAt(currentLine.Count - 1); // continue with next line, if there is one while (i < numChars - 1 && text[i] != CHAR_NEWLINE) { ++i; } } lineFull = true; } } if (i == numChars - 1) { sLines.Add(currentLine); finished = true; } else if (lineFull) { sLines.Add(currentLine); if (lastWhiteSpace == i) { currentLine.RemoveAt(currentLine.Count - 1); } if (currentY + leading + 2 * LineHeight <= containerHeight) { currentLine = new List <CharLocation>(); currentX = 0; currentY += LineHeight + leading; lastWhiteSpace = -1; lastCharId = -1; } else { break; } } } } if (autoScale && !finished && fontSize > 3) { fontSize -= 1; } else { finished = true; } } List <CharLocation> finalLocations = new List <CharLocation>(); int numLines = sLines.Count; float bottom = currentY + LineHeight; int yOffset = 0; if (vAlign == VAlign.Bottom) { yOffset = (int)(containerHeight - bottom); } else if (vAlign == VAlign.Center) { yOffset = (int)((containerHeight - bottom) / 2); } for (int lineId = 0; lineId < numLines; ++lineId) { var line = sLines[lineId]; numChars = line.Count; if (numChars == 0) { continue; } int xOffset = 0; CharLocation lastLocation = line[line.Count - 1]; float right = lastLocation.X - lastLocation.Char.XOffset + lastLocation.Char.XAdvance; if (hAlign == HAlign.Right) { xOffset = (int)(containerWidth - right); } else if (hAlign == HAlign.Center) { xOffset = (int)((containerWidth - right) / 2); } for (int c = 0; c < numChars; ++c) { charLocation = line[c]; charLocation.X = scale * (charLocation.X + xOffset + OffsetX) + Padding; charLocation.Y = scale * (charLocation.Y + yOffset + OffsetY) + Padding; charLocation.Scale = scale; if (charLocation.Char.Width > 0 && charLocation.Char.Height > 0) { finalLocations.Add(charLocation); } } } return(finalLocations); }