private Rect CalculateCaretDrawRect(
            ITextComponentWrapper text,
            Vector2 offset,
            int relativeIndex)
        {
            Vector2 localCursorPos = text.CursorPositionAt(relativeIndex);
            int     line           = text.GetLineByCharIndex(relativeIndex);
            float   height         = text.LineHeight(line);

            return(new Rect(localCursorPos.x + offset.x,
                            localCursorPos.y - height + offset.y, 1,
                            height));
        }
        private List <Rect> CalculateSelectionRects(ICaret caret, ITextComponentWrapper text, Vector2 offset)
        {
            List <Rect> highlightRects = new List <Rect>();

            int start = Mathf.Min(caret.GetIndex(), caret.GetSelectionIndex()) - _drawStart;

            start = Mathf.Clamp(start, 0, text.DisplayedTextLength);
            int end = Mathf.Max(caret.GetIndex(), caret.GetSelectionIndex()) - _drawStart;

            end = Mathf.Clamp(end, 0, text.DisplayedTextLength);

            int startLine = text.GetLineByCharIndex(start);
            int endLine   = text.GetLineByCharIndex(end);

            if (startLine == endLine)
            {
                highlightRects.Add(HightedLineRect(start, end, text.LineHeight(startLine), text));
            }
            else
            {
                int currentLineEndIndex = text.LineEndIndex(startLine);
                highlightRects.Add(HightedLineRect(start, currentLineEndIndex, text.LineHeight(startLine), text));

                while (startLine < endLine - 1)
                {
                    startLine++;
                    highlightRects.Add(HightedLineRect(
                                           text.LineStartIndex(startLine),
                                           text.LineEndIndex(startLine),
                                           text.LineHeight(startLine),
                                           text));
                }

                highlightRects.Add(HightedLineRect(
                                       text.LineStartIndex(endLine), end, text.LineHeight(endLine), text));
            }
            return(highlightRects);
        }
        private Rect CalculateCaretDrawRect(
            ITextComponentWrapper text,
            Vector2 offset,
            int index,
            int selectionIndex)
        {
            Vector2 localCursorPos    = text.CursorPositionAt(index);
            Vector2 localSelectionPos = text.CursorPositionAt(selectionIndex);
            float   height            = text.LineHeight(0);

            if (index > selectionIndex)
            {
                Vector2 temp = localSelectionPos;
                localSelectionPos = localCursorPos;
                localCursorPos    = temp;
            }

            return(new Rect(localCursorPos.x + offset.x,
                            localCursorPos.y - height + offset.y,
                            index != selectionIndex ? Mathf.Abs(localSelectionPos.x - localCursorPos.x) : 1,
                            height));
        }
        protected override string ProcessText(ITextComponentWrapper text, ICaret caret)
        {
            Vector2 extents = text.DisplayRect.size;

            int caretLine = text.GetLineByCharIndex(caret.GetIndex());

            if (caret.GetIndex() > _drawEnd)
            {
                _drawEnd = text.LineEndIndex(caretLine);
                float bottomY = text.LineTop(caretLine) - text.LineHeight(caretLine);
                // TODO: Remove interline spacing on last line.
                int startLine = caretLine;
                while (startLine > 0)
                {
                    float topY = text.LineTop(startLine - 1);
                    if (topY - bottomY > extents.y)
                    {
                        break;
                    }
                    startLine--;
                }
                _drawStart = text.LineStartIndex(startLine);
            }
            else
            {
                if (caret.GetIndex() < _drawStart)
                {
                    _drawStart = text.LineStartIndex(caretLine);
                }

                int startLine = text.GetLineByCharIndex(_drawStart);
                int endLine   = startLine;

                float topY    = text.LineTop(startLine);
                float bottomY = text.LineTop(endLine) - text.LineHeight(endLine);

                // TODO: Remove interline spacing on last line.

                while (endLine < text.LineCount - 1)
                {
                    bottomY = text.LineTop(endLine + 1) - text.LineHeight(endLine + 1);
                    // TODO: Remove interline spacing on last line.
                    if (topY - bottomY > extents.y)
                    {
                        break;
                    }
                    ++endLine;
                }

                _drawEnd = text.LineEndIndex(endLine);

                while (startLine > 0)
                {
                    topY = text.LineTop(startLine - 1);
                    if (topY - bottomY > extents.y)
                    {
                        break;
                    }

                    startLine--;
                }

                _drawStart = text.LineStartIndex(startLine);
            }
            return(TextValue.Substring(_drawStart, _drawEnd - _drawStart));
        }