protected List <TextRange> GetTextLines()
        {
            Font             textFont      = this.Font;
            Rect             absArea       = this.TextRenderArea;
            string           allTextString = GetAllText();
            List <TextRange> lines         =
                TextWrapHelper.GetLineBreaks(textFont, allTextString, absArea.Width, nonSpaceWrap);

            return(lines);
        }
        protected float GetTextWidth()
        {
            Font             textFont      = this.Font;
            Rect             absArea       = this.TextRenderArea;
            string           allTextString = GetAllText();
            float            maxWidth      = 0.0f;
            List <TextRange> lines         =
                TextWrapHelper.GetLineBreaks(textFont, allTextString, absArea.Width, nonSpaceWrap);

            foreach (TextRange range in lines)
            {
                float extent = font.GetTextExtent(allTextString.Substring(range.start, range.Length));
                maxWidth = (float)Math.Max(maxWidth, extent);
            }
            return(maxWidth);
        }
        protected void DrawText(float z)
        {
            Rect absRect  = GetVisibleTextArea();
            Rect clipRect = absRect.GetIntersection(this.PixelRect);
            Font textFont = this.Font;

            // textColors.SetAlpha(EffectiveAlpha);
            string           allText = GetAllText();
            List <TextRange> lines   =
                TextWrapHelper.GetLineBreaks(textFont, allText, absRect.Width, nonSpaceWrap);

            Vector3 drawPos = new Vector3();

            drawPos.x = absRect.left;
            drawPos.y = absRect.top;
            drawPos.z = z;

            switch (vertFormat)
            {
            case VerticalTextFormat.Top:
                drawPos.y += 0.0f;                         // start at the top
                break;

            case VerticalTextFormat.Bottom:
                drawPos.y += absRect.Height - lines.Count * textFont.LineSpacing;
                break;

            case VerticalTextFormat.Centered:
                drawPos.y += (absRect.Height - lines.Count * textFont.LineSpacing) / 2;
                break;
            }

            List <TextChunk> .Enumerator chunkEnum = textChunks.GetEnumerator();
            // the offset of the last character that we have drawn
            int lastChar = 0;
            // the offset of the first character in the chunk we are working with
            int chunkStart = 0;
            // the offset of the last character in the chunk we are working with
            int chunkEnd = 0;
            // offset into the active chunk of the first undrawn character
            int       startOffset;
            string    portion;
            TextChunk chunk = chunkEnum.Current;

            foreach (TextRange range in lines)
            {
                drawPos.x = absRect.left;
                string line = allText.Substring(range.start, range.Length);
                switch (horzFormat)
                {
                case HorizontalTextFormat.Left:
                case HorizontalTextFormat.WordWrapLeft:
                    drawPos.x += 0.0f;                             // start at the left
                    break;

                case HorizontalTextFormat.Right:
                case HorizontalTextFormat.WordWrapRight:
                    drawPos.x += absRect.Width - textFont.GetTextExtent(line);
                    break;

                case HorizontalTextFormat.Center:
                case HorizontalTextFormat.WordWrapCentered:
                    drawPos.x += (absRect.Width - textFont.GetTextExtent(line)) / 2;
                    break;
                }
                // while the rest of the current chunk fits completely on this line
                while (chunkEnd <= range.end)
                {
                    // offset into this chunk of the first undrawn character
                    startOffset = lastChar - chunkStart;
                    // do we have anything to process in this chunk?
                    if (chunkEnd - lastChar > 0)
                    {
                        portion = chunk.text.Substring(startOffset, chunkEnd - lastChar);
                        DrawText(portion, drawPos, clipRect, chunk.style);
                        drawPos.x += textFont.GetTextExtent(portion);
                        lastChar   = chunkEnd;
                    }

                    if (!chunkEnum.MoveNext())
                    {
                        // we have finished processing the last chunk
                        return;
                    }
                    chunk      = chunkEnum.Current;
                    chunkStart = chunkEnd;
                    chunkEnd  += chunk.text.Length;
                }
                // at this point, chunk end > range end, so the whole chunk
                // does not belong on this line
                startOffset = lastChar - chunkStart;
                portion     = chunk.text.Substring(startOffset, range.end - lastChar);

                DrawText(portion, drawPos, clipRect, chunk.style);
                drawPos.x += textFont.GetTextExtent(portion);
                lastChar   = range.end;

                drawPos.y += font.LineSpacing;
            }
        }
        public Point GetOffset(int textIndex)
        {
            Rect absRect  = GetVisibleTextArea();
            Font textFont = this.Font;

            // textColors.SetAlpha(EffectiveAlpha);
            string           allText = GetAllText();
            List <TextRange> lines   =
                TextWrapHelper.GetLineBreaks(textFont, allText, absRect.Width, nonSpaceWrap);

            Point drawPos;

            drawPos.x = absRect.left;
            drawPos.y = absRect.top;

            switch (vertFormat)
            {
            case VerticalTextFormat.Top:
                drawPos.y += 0.0f;                         // start at the top
                break;

            case VerticalTextFormat.Bottom:
                drawPos.y += absRect.Height - lines.Count * textFont.LineSpacing;
                break;

            case VerticalTextFormat.Centered:
                drawPos.y += (absRect.Height - lines.Count * textFont.LineSpacing) / 2;
                break;
            }


            for (int i = 0; i < lines.Count; ++i)
            {
                TextRange range = lines[i];
                if (range.end <= textIndex && (i < (lines.Count - 1)))
                {
                    drawPos.y += font.LineSpacing;
                    continue;
                }
                string line = allText.Substring(range.start, range.Length);
                switch (horzFormat)
                {
                case HorizontalTextFormat.Left:
                case HorizontalTextFormat.WordWrapLeft:
                    drawPos.x += 0.0f;                             // start at the left
                    break;

                case HorizontalTextFormat.Right:
                case HorizontalTextFormat.WordWrapRight:
                    drawPos.x += absRect.Width - textFont.GetTextExtent(line);
                    break;

                case HorizontalTextFormat.Center:
                case HorizontalTextFormat.WordWrapCentered:
                    drawPos.x += (absRect.Width - textFont.GetTextExtent(line)) / 2;
                    break;
                }
                if (range.start > textIndex)
                {
                    return(drawPos);
                }
                // some of the text precedes the offset
                string portion = line.Substring(0, textIndex - range.start);
                drawPos.x += textFont.GetTextExtent(portion);
            }
            return(drawPos);
        }