private Quad CreateQuad(bool isEmpty, ColourDefinition color, RectangleF rect, RectangleF uvrect) { rect = rect.ToScreenCoordinates(this.TextFormatterSettings.ViewportSize); return(isEmpty ? Quad.CreateDummy(rect) : new Quad(color, rect, uvrect)); }
/// <summary> /// Creates the text quads. /// </summary> /// <param name="rect">A <see cref="Rectangle"/> representing the bounds of the text.</param> /// <param name="text">The text.</param> /// <returns>The text quads.</returns> public Quad[] CreateTextQuads(Rectangle rect, string text) { // return a dummy if the text is empty if (string.IsNullOrEmpty(text)) { return(new[] { Quad.CreateDummy(rect.ToScreenCoordinates(this.TextFormatterSettings.ViewportSize)) }); } var retValue = new List <Quad>(text.Length); var colour = this.TextFormatterSettings.ColourDefinition; var alignment = this.TextFormatterSettings.Alignment; bool multiline = this.TextFormatterSettings.Multiline; bool wordWrap = this.TextFormatterSettings.WordWrap && multiline; var font = this.TextFormatterSettings.Font; int lineSpacing = font.Leading; if (!multiline && font is TrueTypeFont) { lineSpacing = ((TrueTypeFont)font).Size; } int availableHeight = rect.Height; int cursorY = rect.Top; // split the text into lines var lineNodes = new LinkedList <string>(text.Split(new[] { Environment.NewLine }, StringSplitOptions.None)); var lineNode = lineNodes.First; while (lineNode != null) { availableHeight -= lineSpacing; if (availableHeight >= 0) { float availableWidth = rect.Width; float cursorX = rect.Left; string currentLine = lineNode.Value; int lastWordStartIndex = 0; float wordWidth = 0; var lineQuads = new List <Quad>(); // split the line into chars for (int currentCharIndex = 0; currentCharIndex < currentLine.Length; currentCharIndex++) { char c = currentLine[currentCharIndex]; bool isWhiteSpace = char.IsWhiteSpace(c); RectangleF uvRect; float charWidth = font.GetCharWidth(c, out uvRect); if (wordWrap) { // buffer start index of latest word if (!char.IsWhiteSpace(c) && currentCharIndex > 0 && char.IsWhiteSpace(currentLine[currentCharIndex - 1])) { lastWordStartIndex = currentCharIndex; wordWidth = 0; } // ...and its width wordWidth += charWidth; } // check whether we're running out of horizontal space availableWidth -= charWidth; if (availableWidth < 0) { if (wordWrap && lastWordStartIndex > 0) { // remove last word from quads and add as next line lineQuads.RemoveRange(lastWordStartIndex, lineQuads.Count - lastWordStartIndex); lineNodes.AddAfter(lineNode, currentLine.Substring(lastWordStartIndex)); availableWidth += wordWidth; } else { // add rest of line as new line lineNodes.AddAfter(lineNode, currentLine.Substring(currentCharIndex)); availableWidth += charWidth; } break; } // create the position rectangle var posRect = new RectangleF(cursorX, cursorY, charWidth, uvRect.Height * font.TextureSize.Height); var quad = this.CreateQuad(isWhiteSpace, colour, posRect, uvRect); lineQuads.Add(quad); cursorX += charWidth; // add additional spacing cursorX += font.Tracking; availableWidth -= font.Tracking; } this.AlignQuadsHorizontally(lineQuads, alignment, rect, rect.Width - availableWidth); retValue.AddRange(lineQuads); cursorY += lineSpacing; } else { availableHeight += lineSpacing; break; } // take only the first line if we are not multiline if (!multiline) { break; } lineNode = lineNode.Next; } this.AlignQuadsVertically(retValue, alignment, rect, rect.Height - availableHeight); return(retValue.ToArray()); }