Ejemplo n.º 1
0
 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));
 }
Ejemplo n.º 2
0
        /// <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());
        }