Add SetFirstDisplayPositionX & support cursor move to row, culomn
authorChoongeun Hong <cheun.hong@samsung.com>
Tue, 4 Jun 2013 08:25:50 +0000 (17:25 +0900)
committerChoongeun Hong <cheun.hong@samsung.com>
Wed, 5 Jun 2013 06:20:37 +0000 (15:20 +0900)
Change-Id: I588505bc453c07b9f0e4cdbbc5119d10c7c6e95a
Signed-off-by: Choongeun Hong <cheun.hong@samsung.com>
src/graphics/inc/FGrp_TextTextObject.h
src/graphics/text/FGrp_TextTextColumn.cpp
src/graphics/text/FGrp_TextTextColumn.h
src/graphics/text/FGrp_TextTextComposite.cpp
src/graphics/text/FGrp_TextTextComposite.h
src/graphics/text/FGrp_TextTextObject.cpp

index 6cb39c7..071dad6 100644 (file)
@@ -100,6 +100,8 @@ public:
 
        int GetTextIndexFromPosition(float x, float y, bool cursorMode = true) const;
 
+       int GetTextIndexFromPosition(float x, float y, int& row, int& column, bool cursorMode = true) const;
+
        int GetTextIndexFromPositionAtLine(int lineIndex, int x, bool cursorMode = true) const;
 
        int GetTextIndexFromPositionAtLine(int lineIndex, float x, bool cursorMode = true) const;
@@ -327,6 +329,8 @@ public:
 
        result GetTextPositionInfoAt(int textIndex, float& width, float& height, float& absX, float& absY, float& logicalX, float& logicalY) const;
 
+       result GetTextPositionInfoAt(int row, int column, float& width, float& height, float& absX, float& absY, float& logicalX, float& logicalY) const;
+       
        result GetBlockTextPositionInfoAt(int textIndex, int& width, int& height, int& absX, int& absY, int& logicalX, int& logicalY) const;
 
        result GetBlockTextPositionInfoAt(int textIndex, float& width, float& height, float& absX, float& absY, float& logicalX, float& logicalY) const;
@@ -357,6 +361,18 @@ public:
 
        TextBidiHint GetTextBidiHint(void) const;
 
+       result SetFirstDisplayPositionX(int x);
+
+       result SetFirstDisplayPositionX(float x);
+
+       int GetFirstDisplayPositionX(void) const;
+
+       float GetFirstDisplayPositionXF(void) const;
+
+       result ConvertToRowColumn(int textIndex, int& row, int& column) const;
+
+       int ConvertToTextIndex(int row, int column) const;
+
        result SetDisplayBoundsExpandEnabled(bool enable);
 
        bool IsDisplayBoundsExpandEnabled(void) const;
@@ -376,6 +392,9 @@ private:
        result GetTextPositionInfoInWrapAt(int textIndex, float& width, float& height, float& absX, float& absY,
                        float& logicalX, float& logicalY) const;
 
+       result GetTextPositionInfoInWrapAt(int row, int clomn, float& width, float& height, float& absX, float& absY,
+                       float& logicalX, float& logicalY) const;
+
        result GetBlockTextPositionInfoInWrapAt(int textIndex, int& width, int& height, int& absX, int& absY,
                        int& logicalX, int& logicalY) const;
 
@@ -388,14 +407,21 @@ private:
        result GetTextPositionInfoInNoneWrapAt(int textIndex, float& width, float& height, float& absX, float& absY,
                        float& logicalX, float& logicalY) const;
 
+       result GetTextPositionInfoInNoneWrapAt(int row, int clomn, float& width, float& height, float& absX, float& absY,
+                       float& logicalX, float& logicalY) const;
+
        int GetTextIndexFromPositionInWrap(int x, int y, bool cursorMode = true) const;
 
        int GetTextIndexFromPositionInWrap(float x, float y, bool cursorMode = true) const;
 
+       int GetTextIndexFromPositionInWrap(float x, float y, int& row, int& column, bool cursorMode = true) const;
+
        int GetTextIndexFromPositionInNoneWrap(int x, int y, bool cursorMode = true) const;
 
        int GetTextIndexFromPositionInNoneWrap(float x, float y, bool cursorMode = true) const;
 
+       int GetTextIndexFromPositionInNoneWrap(float x, float y, int& row, int& column, bool cursorMode = true) const;
+
        result UpdateChangedInfo(int startTextIndex, int textLength = -1);
 
        result NotifyTextAdded(int textIndex, int textLength);
index c2e2991..dfb7948 100644 (file)
@@ -51,6 +51,7 @@ TextColumn::TextColumn(TextComposite* pCompositeText)
        __displayLineCount = 0;
        __firstDisplayLineIndex = 0;
        __firstDisplayPositionY = -1;
+       __firstDisplayPositionX = -1;
        __displayHeight = -1;
        __slidingPosition = 0;
        __pCompositeText = pCompositeText;
@@ -198,6 +199,11 @@ TextColumn::Draw(_CanvasImpl& canvasImpl, FloatRectangle& displayRect, int start
                __displayHeight -= __firstDisplayPositionY - lineBounds.y;
        }
 
+       if (__firstDisplayPositionX > 0)
+       {
+               displayRect.x -= __firstDisplayPositionX;
+       }
+
        while (pTextLineNode != null && 0 <= displayRect.height)
        {
                if (action == TEXT_OBJECT_ACTION_TYPE_ABBREV)
@@ -218,6 +224,11 @@ TextColumn::Draw(_CanvasImpl& canvasImpl, FloatRectangle& displayRect, int start
                                {
                                        lineAction = TEXT_OBJECT_ACTION_TYPE_ABBREV;
                                }
+
+                               if (displayRect.width < lineBounds.width)
+                               {
+                                       lineAction = TEXT_OBJECT_ACTION_TYPE_ABBREV;
+                               }
                        }
                        else
                        {
@@ -1669,6 +1680,18 @@ TextColumn::GetFirstDisplayPositionYF(void) const
 }
 
 void
+TextColumn::SetFirstDisplayPositionX(float x)
+{
+       __firstDisplayPositionX = x;
+}
+
+float
+TextColumn::GetFirstDisplayPositionX(void) const
+{
+       return __firstDisplayPositionX;
+}
+
+void
 TextColumn::SetDisplayHeight(int height)
 {
        __displayHeight = _CoordinateSystemUtils::ConvertToFloat(height);
index 2606bb3..1b08256 100644 (file)
@@ -143,6 +143,10 @@ public:
 
        float GetFirstDisplayPositionYF(void) const;
 
+       void SetFirstDisplayPositionX(float x);
+
+       float GetFirstDisplayPositionX(void) const;
+
        int GetTextLengthAt(int lineIndex) const;
 
        int GetFirstTextIndexAt(int lineIndex) const;
@@ -242,6 +246,7 @@ private:
        int __totalLineCount;
        int __firstDisplayLineIndex;
        float __firstDisplayPositionY;
+       float __firstDisplayPositionX;
        int __displayLineCount;
        float __displayHeight;
        Tizen::Graphics::FloatDimension __slidingDimension;
index d872047..d760cd0 100644 (file)
@@ -1872,7 +1872,6 @@ TextComposite::DrawLine(_CanvasImpl& canvasImpl, TextLine* pTextLine, const Floa
        pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
 
        adjustedRect = displayRect;
-       adjustedRect.width = lineBounds.width;
        adjustedRect.height = lineBounds.height;
 
        if (action == TEXT_OBJECT_ACTION_TYPE_ABBREV)
@@ -3228,7 +3227,7 @@ TextComposite::NotifyTextChanged(wchar_t* pText, int startTextIndex, int textLen
        int textIndexFromElementOffset = 0;
        bool isOptimized = false;
 
-       SetWorkWidth(pFont, pText, __workStart, gap);
+       //SetWorkWidth(pFont, pText, __workStart, gap);
 
        if (gap > 0)
        {
@@ -3952,201 +3951,30 @@ TextComposite::ComposeInNoneWrap(FloatRectangle& rect, NoneWrapComposeInfo* pNon
 {
        SysTryReturn(NID_GRP, __pCurrentTextColumn, -1, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
 
-       TextLine* pTextLine = null;
+       TextLine* pTextLine = new (std::nothrow)TextLine(this);
+       SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
+
        FloatRectangle lineBounds;
-       FloatDimension textSize;
-       int lineOffset = 0;
-       int lineLength = 0;
-       int endType = TEXT_RETBY_NORMAL;
-       bool isChanged = false;
+       FloatDimension lineTextSize;
+       int lineLength = __length;
        float baseline = 0;
-       int textIndex = 0;
-
-       textIndex = (__workStart < 0) ? 0 : __workStart;
-       textIndex = (textIndex > __length) ? __length : textIndex;
-       bool forwardSearch = (textIndex == __length) ? false : true;
-
-       if (__pCurrentTextColumn->GetTotalLineCount() > 0)
-       {
-               pTextLine = __pCurrentTextColumn->GetTextLine(0);
-               SysTryReturn(NID_GRP, pTextLine, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
-
-               lineBounds = pTextLine->GetBoundsF();
-               endType = pTextLine->GetEndType();
-
-               if (lineBounds.width != rect.width)
-               {
-                       isChanged = true;
-               }
-
-               lineOffset = pTextLine->GetTextOffset();
-               lineLength = pTextLine->GetTextLength();
-
-               if (lineOffset <= textIndex && textIndex < lineOffset + lineLength)
-               {
-                       isChanged = true;
-               }
-       }
-       else
-       {
-               pTextLine = new (std::nothrow)TextLine(this);
-               SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
-
-               if (forwardSearch)
-               {
-                       if (pNoneWrapComposeInfo != null)
-                       {
-                               lineOffset = pNoneWrapComposeInfo->prevTextOffset;
-                       }
-                       else
-                       {
-                               lineOffset = 0;
-                       }
-               }
-               else
-               {
-                       lineOffset = __length - 1;
-               }
-
-               lineLength = 0;
-               lineBounds.width = rect.width;
-               lineBounds.x = 0;
-               lineBounds.y = 0;
-               lineBounds.height = 0;
 
-               __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
+       GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
 
-               isChanged = true;
-       }
-
-       if (isChanged)
-       {
-               lineBounds.width = rect.width;
-               lineBounds.x = 0;
-               lineBounds.y = 0;
-
-               if (forwardSearch)
-               {
-                       endType = ForwardAnalyzeWithBaseline(lineOffset, __length - lineOffset, lineBounds.width, __wrap,
-                                                                         lineLength, textSize.width, textSize.height, baseline);
-
-                       lineBounds.height = textSize.height;
-                       pTextLine->SetBounds(lineBounds);
-                       pTextLine->SetTextOffset(lineOffset);
-                       pTextLine->SetTextLength(lineLength);
-                       pTextLine->SetRegion(textSize.width, textSize.height);
-                       pTextLine->SetEndType(endType);
-                       pTextLine->SetBaseline(baseline);
-                       GetTextExtentList(pTextLine);
-               }
-               else
-               {
-                       int textCount = 0;
-
-                       BackwardAnalyze(lineOffset, lineBounds.width, &textCount, &textSize.width, &textSize.height);
-
-                       lineBounds.height = textSize.height;
-                       lineOffset -= (textCount - 1);
-                       lineLength = textCount;
-                       endType = (lineOffset == 0) ? TEXT_RETBY_NORMAL : TEXT_RETBY_LIMITWIDTH;
-
-                       pTextLine->SetBounds(lineBounds);
-                       pTextLine->SetTextOffset(lineOffset);
-                       pTextLine->SetTextLength(lineLength);
-                       pTextLine->SetRegion(textSize.width, textSize.height);
-                       pTextLine->SetEndType(endType);
-                       pTextLine->SetBaseline(baseline);
-                       GetTextExtentList(pTextLine);
-               }
-       }
-
-       if (__length == 0)
-       {
-               pTextLine->SetEndType(TEXT_RETBY_NORMAL);
-               return 1;
-       }
-
-       rect.height = lineBounds.height;
-
-       if (textIndex < lineOffset)
-       {
-               lineOffset = textIndex;
-               endType = ForwardAnalyze(lineOffset, __length - lineOffset, lineBounds.width, __wrap,
-                                                                 lineLength, textSize.width, textSize.height);
-
-               lineBounds.height = textSize.height;
-       }
-       else if (forwardSearch && textIndex >= lineOffset + lineLength)
-       {
-               FloatDimension needDim;
-               GetRegion(lineOffset + lineLength, textIndex - (lineOffset + lineLength) + 1, needDim.width, needDim.height);
-
-               int index = 0;
-               float remainingWidth = needDim.width - (lineBounds.width - textSize.width);
-
-               FloatDimension charDim;
-               textSize.width += needDim.width;
-               lineLength += textIndex - (lineOffset + lineLength) + 1;
-
-               while (1)
-               {
-                       GetRegion(lineOffset, 1, charDim.width, charDim.height);
-                       lineOffset++;
-                       index++;
-                       remainingWidth -= charDim.width;
-                       textSize.width -= charDim.width;
-
-                       if (remainingWidth <= 0)
-                       {
-                               break;
-                       }
-               }
-
-               lineLength -= index;
-       }
-       else if (endType != TEXT_RETBY_LIMITWIDTH && lineLength != __length)
-       {
-               if (lineOffset > 0)
-               {
-                       FloatDimension lineTextSize;
-                       int textCount = 0;
-                       float remainingWidth = 0;
-
-                       pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
-                       remainingWidth = lineBounds.width - lineTextSize.width;
-                       BackwardAnalyze(lineOffset - 1, remainingWidth, &textCount, &textSize.width, &textSize.height);
-
-                       if (textSize.width > 0)
-                       {
-                               lineOffset -= textCount;
-                               lineLength += textCount;
-                               textSize.width += lineTextSize.width;
-                               lineBounds.height = textSize.height;
-                               endType = TEXT_RETBY_LIMITLENGTH;
-                       }
-                       else
-                       {
-                               return 1;
-                       }
-               }
-               else
-               {
-                       return 1;
-               }
-       }
-       else
-       {
-               return 1;
-       }
+       lineBounds.width = (rect.width < lineTextSize.width) ? lineTextSize.width :rect.width;
+       lineBounds.height = lineTextSize.height;
+       baseline = lineBounds.height / 3.0f;
 
        pTextLine->SetBounds(lineBounds);
-       pTextLine->SetRegion(textSize.width, textSize.height);
-       pTextLine->SetTextLength(lineLength);
-       pTextLine->SetTextOffset(lineOffset);
-       pTextLine->SetEndType(endType);
+       pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
+       pTextLine->SetTextOffset(0);
+       pTextLine->SetTextLength(lineLength);   
+       pTextLine->SetEndType(TEXT_RETBY_NORMAL);
        pTextLine->SetBaseline(baseline);
        GetTextExtentList(pTextLine);
 
+       __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
+
        return 1;
 }
 
@@ -4963,8 +4791,7 @@ TextComposite::ComposeInNoneWrapMiddleEllipsis(FloatRectangle& rect)
 
        maxHeight = textSize.height;
 
-       ForwardAnalyze(__middleEllipsisTextLengthInHead, __length - __middleEllipsisTextLengthInHead, lineBounds.width - __middleEllipsisWidth -
-                                  __middleEllipsisHeadWidth, __wrap, length, textSize.width, textSize.height);
+       BackwardAnalyze(__length - 1, lineBounds.width - __middleEllipsisWidth - __middleEllipsisHeadWidth, length, textSize.width, textSize.height);
 
        __middleEllipsisTextLengthInTail = length;
        maxHeight = (maxHeight < textSize.height) ? textSize.height : maxHeight;
@@ -5032,7 +4859,8 @@ TextComposite::ComposeInNoneWrapHeadEllipsis(FloatRectangle& rect)
        __pAbbrevTextElement->GetRegion(0, 1, abbrevTextDim.width, abbrevTextDim.height);
        __headEllipsisWidth = abbrevTextDim.width;
 
-       BackwardAnalyze(__length - 1, lineBounds.width - abbrevTextDim.width, &__headEllipsisTextLength, &textSize.width, &textSize.height);
+       BackwardAnalyze(__length - 1, lineBounds.width - abbrevTextDim.width, __headEllipsisTextLength, textSize.width, textSize.height);
+       
        maxHeight = textSize.height;
 
        TextLine* pTextLine = new (std::nothrow)TextLine(this);
@@ -5110,15 +4938,15 @@ TextComposite::GetValue(int textIndex, TextComponentInfoValueType type, unsigned
 }
 
 bool
-TextComposite::BackwardAnalyze(int startTextIndex, float maxWidth, int* actualLength, float* width, float* height)
+TextComposite::BackwardAnalyze(int startTextIndex, float maxWidth, int& actualLength, float& width, float& height)
 {
        float remainingWidth = 0;
        int length = 0;
        FloatDimension textSize;
 
-       *actualLength = 0;
-       *width = 0;
-       *height = 0;
+       actualLength = 0;
+       width = 0;
+       height = 0;
 
        remainingWidth = maxWidth;
        length = 1;
@@ -5129,9 +4957,9 @@ TextComposite::BackwardAnalyze(int startTextIndex, float maxWidth, int* actualLe
 
                if (textSize.width <= remainingWidth)
                {
-                       *actualLength = length;
-                       *width = textSize.width;
-                       *height = textSize.height;
+                       actualLength = length;
+                       width = textSize.width;
+                       height = textSize.height;
                }
 
                startTextIndex--;
index 562f37f..af6f58c 100644 (file)
@@ -301,7 +301,7 @@ private:
 
        int ComposeInPartialMode(FloatRectangle& rect);
 
-       bool BackwardAnalyze(int startTextIndex, float maxWidth, int* actualLength, float* width, float* height);
+       bool BackwardAnalyze(int startTextIndex, float maxWidth, int& actualLength, float& width, float& height);
 
        result DrawAbbrevInMiddleEllipsis(_CanvasImpl& canvasImpl, const FloatRectangle& displayRect, const TextObjectAlignment alignment);
 
index df0175c..e7b5961 100644 (file)
@@ -737,6 +737,7 @@ TextObject::Compose(void)
                __pTextColumn->SetChangeAction(TextColumn::TEXT_CHANGE_UNKONWN, 0, 0);
                __pTextColumn->SetFirstDisplayLineIndex(0);
                __pTextColumn->SetFirstDisplayPositionY(0.0f);
+               __pTextColumn->SetFirstDisplayPositionX(0.0f);
        }
 
        ResetSweepInfo();
@@ -749,10 +750,11 @@ TextObject::Compose(void)
                TextLine* pTextLine = __pTextColumn->GetTextLine(0);
                if (pTextLine != null)
                {
+                       FloatRectangle lineBounds = pTextLine->GetBoundsF();
                        int lineLength = pTextLine->GetTextLength();
                        int totalLength = __pCompositeText->GetTextLength();
 
-                       if (lineLength < totalLength)
+                       if (lineLength < totalLength || __rect.width < lineBounds.width)
                        {
                                __isActionOn = true;
                                __pTextColumn->SetSlidingPosition(0.0f);
@@ -902,6 +904,48 @@ CATCH:
 }
 
 result
+TextObject::SetFirstDisplayPositionX(int x)
+{
+       return SetFirstDisplayPositionX(_CoordinateSystemUtils::ConvertToFloat(x));
+}
+
+result
+TextObject::SetFirstDisplayPositionX(float x)
+{
+       IF_NOT_CONSTRUCTED(return E_INVALID_STATE);
+       SysTryReturn(NID_GRP, __wrap == TEXT_OBJECT_WRAP_TYPE_NONE
+               , E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] The argument is invalid.");
+
+       TextLine* pTextLine = __pTextColumn->GetTextLine(0);
+       SysTryReturn(NID_GRP, pTextLine, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
+
+       FloatRectangle lineBounds = pTextLine->GetBoundsF();
+
+       if (x < 0)
+       {
+               x = 0;
+       }
+       
+       __pTextColumn->SetFirstDisplayPositionX(x);
+
+       return E_SUCCESS;
+}
+
+int
+TextObject::GetFirstDisplayPositionX(void) const
+{
+       return _CoordinateSystemUtils::ConvertToInteger(GetFirstDisplayPositionXF());
+}
+
+float
+TextObject::GetFirstDisplayPositionXF(void) const
+{
+       IF_NOT_CONSTRUCTED(return -1);
+
+       return __pTextColumn->GetFirstDisplayPositionX();
+}
+
+result
 TextObject::SetFirstDisplayPositionY(int y)
 {
        return SetFirstDisplayPositionY(_CoordinateSystemUtils::ConvertToFloat(y));
@@ -1926,6 +1970,27 @@ TextObject::GetTextIndexFromPosition(float x, float y, bool cursorMode) const
 }
 
 int
+TextObject::GetTextIndexFromPosition(float x, float y, int& row, int& column, bool cursorMode) const
+{
+       IF_NOT_CONSTRUCTED(return -1);
+
+       int lineCount = __pTextColumn->GetTotalLineCount();
+       if (lineCount <= 0)
+       {
+               return -1;
+       }
+
+       if (__wrap == TEXT_OBJECT_WRAP_TYPE_NONE)
+       {
+               return GetTextIndexFromPositionInNoneWrap(x, y, row, column, !cursorMode);
+       }
+       else
+       {
+               return GetTextIndexFromPositionInWrap(x, y, row, column, !cursorMode);
+       }
+}
+
+int
 TextObject::GetTextIndexFromPositionAtLine(int lineIndex, int x, bool cursorMode) const
 {
        return GetTextIndexFromPositionAtLine(lineIndex, _CoordinateSystemUtils::ConvertToFloat(x), cursorMode);
@@ -2402,6 +2467,115 @@ TextObject::GetTextPositionInfoAt(int textIndex, float& width, float& height, fl
 }
 
 result
+TextObject::GetTextPositionInfoAt(int row, int column, float& width, float& height, float& absX, float& absY, float& logicalX, float& logicalY) const
+{
+       IF_NOT_CONSTRUCTED(return E_INVALID_STATE);
+
+       result r = E_SUCCESS;
+       TextBidiHint bidiHint = _GetTextBidiHint();
+       _SetTextBidiHint(__bidiHint);
+
+       int lineCount = __pTextColumn->GetTotalLineCount();
+
+       if (lineCount < 1)
+       {
+               _FontImpl* pFont = _FontImpl::GetInstance(*__pDefaultFont);
+               SysTryReturn(NID_GRP, pFont, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get native font instance.");
+
+               float maxHeight = TextUtility::GetFontMaxHeightF(pFont);
+               float posX = 0.0f;
+               float posY = 0.0f;
+               absX = 0.0f;
+               absY = 0.0f;
+
+               if (__wrap == TEXT_OBJECT_WRAP_TYPE_NONE)
+               {
+                       switch (__align & TEXT_ALIGNMASK_VERT)
+                       {
+                       case TEXT_OBJECT_ALIGNMENT_TOP:
+                               break;
+
+                       case TEXT_OBJECT_ALIGNMENT_MIDDLE:
+                               posY += (__rect.height - maxHeight) / 2.0f;
+                               break;
+
+                       case TEXT_OBJECT_ALIGNMENT_BOTTOM:
+                               posY += (__rect.height - maxHeight);
+                               break;
+                       }
+                       logicalY = __rect.y + posY;
+
+                       switch (__align & TEXT_ALIGNMASK_HORIZ)
+                       {
+                       case TEXT_OBJECT_ALIGNMENT_LEFT:
+                               break;
+
+                       case TEXT_OBJECT_ALIGNMENT_CENTER:
+                               posX += __rect.width / 2.0f;
+                               break;
+
+                       case TEXT_OBJECT_ALIGNMENT_RIGHT:
+                               posX += __rect.width;
+                               break;
+                       }
+                       logicalX = __rect.x + posX;
+               }
+               else
+               {
+                       float lineHeight = maxHeight + __pCompositeText->GetLineSpaceF();
+                       TextObjectAlignment alignment = __pCompositeText->GetElementVerticalAlignment();
+                       switch (alignment & TEXT_ALIGNMASK_VERT)
+                       {
+                       case TEXT_OBJECT_ALIGNMENT_TOP:
+                               // fall through
+                       default:
+                               break;
+
+                       case TEXT_OBJECT_ALIGNMENT_MIDDLE:
+                               posY += (lineHeight - maxHeight) / 2.0f;
+                               break;
+
+                       case TEXT_OBJECT_ALIGNMENT_BOTTOM:
+                               posY += lineHeight - maxHeight;
+                               break;
+                       }
+
+                       switch (__align & TEXT_ALIGNMASK_HORIZ)
+                       {
+                       case TEXT_OBJECT_ALIGNMENT_LEFT:
+                               break;
+
+                       case TEXT_OBJECT_ALIGNMENT_CENTER:
+                               posX += __rect.width / 2.0f;
+                               break;
+
+                       case TEXT_OBJECT_ALIGNMENT_RIGHT:
+                               posX += __rect.width;
+                               break;
+                       }
+
+                       logicalX = posX + __rect.x;
+                       logicalY = posY + __rect.y;
+               }
+
+               width = 0.0f;
+               height = maxHeight;
+               absX = posX;
+               absY = posY;
+       }
+       else
+       {
+               r = (__wrap == TEXT_OBJECT_WRAP_TYPE_NONE) ? GetTextPositionInfoInNoneWrapAt(row, column, width, height, absX, absY, logicalX, logicalY)
+                               : GetTextPositionInfoInWrapAt(row, column, width, height, absX, absY, logicalX, logicalY);
+               SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
+       }
+
+       _SetTextBidiHint(bidiHint);
+
+       return E_SUCCESS;
+}
+
+result
 TextObject::GetBlockTextPositionInfoAt(int textIndex, int& width, int& height, int& absX, int& absY, int& logicalX, int& logicalY) const
 {
        float widthF = _CoordinateSystemUtils::ConvertToFloat(width);
@@ -2675,6 +2849,110 @@ TextObject::GetTextIndexFromPositionInWrap(float x, float y, bool cursorMode) co
 }
 
 int
+TextObject::GetTextIndexFromPositionInWrap(float x, float y, int& row, int& column, bool cursorMode) const
+{
+       TextLine* pTextLine = null;
+       FloatRectangle lineBounds;
+       int firstDisplayLineIndex = __pTextColumn->GetFirstDisplayLineIndex();
+       float firstDisplayPositionY = __pTextColumn->GetFirstDisplayPositionYF();
+       int lineCount = __pTextColumn->GetTotalLineCount();
+       int lineIndex = 0;
+       float totalHeight = __pTextColumn->GetTotalHeightF();
+
+       TextBidiHint bidiHint = _GetTextBidiHint();
+       _SetTextBidiHint(__bidiHint);
+
+       switch (__align & TEXT_ALIGNMASK_VERT)
+       {
+       case TEXT_OBJECT_ALIGNMENT_TOP:
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_MIDDLE:
+               y -= (__rect.height - totalHeight) / 2.0f;
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_BOTTOM:
+               y -= (__rect.height - totalHeight);
+               break;
+       }
+
+       for (lineIndex = firstDisplayLineIndex; lineIndex < lineCount; lineIndex++)
+       {
+               pTextLine = __pTextColumn->GetTextLine(lineIndex);
+               SysTryReturn(NID_GRP, pTextLine, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
+
+               lineBounds = pTextLine->GetBoundsF();
+
+               if (lineIndex == firstDisplayLineIndex)
+               {
+                       if (y < lineBounds.y - firstDisplayPositionY)
+                       {
+                               return -1;
+                       }
+               }
+
+               if ((lineBounds.y - firstDisplayPositionY <= y) && (y < lineBounds.y + lineBounds.height - firstDisplayPositionY))
+               {
+                       break;
+               }
+
+               if (lineIndex == lineCount - 1)
+               {
+                       if (cursorMode)
+                       {
+                               return pTextLine->GetTextLength() + pTextLine->GetTextOffset();
+                       }
+                       else
+                       {
+                               return -1;
+                       }
+               }
+       }
+
+       SysTryReturn(NID_GRP, pTextLine, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
+
+       int lineLength = pTextLine->GetTextLength();
+       Dimension lineTextSize;
+       pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
+
+       switch (__align & TEXT_ALIGNMASK_HORIZ)
+       {
+       case TEXT_OBJECT_ALIGNMENT_LEFT:
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_CENTER:
+               x -= (lineBounds.width - lineTextSize.width) / 2.0f;
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_RIGHT:
+               x -= (lineBounds.width - lineTextSize.width);
+               break;
+       }
+
+       if (x < 0.0f)
+       {
+               x = 0.0f;
+       }
+
+       int index = pTextLine->GetTextIndexFromPosition(x);
+       row = pTextLine->GetIndex();
+       column = index - pTextLine->GetTextOffset();
+
+       int endType = pTextLine->GetEndType();
+       if (endType == TEXT_RETBY_LINEFEED && column == lineLength)
+       {
+               index -= 1;
+               column -= 1;
+       }
+
+       _SetTextBidiHint(bidiHint);
+
+       SetLastResult(E_SUCCESS);
+
+       return index;
+}
+
+int
 TextObject::GetTextIndexFromPositionInNoneWrap(int x, int y, bool cursorMode) const
 {
        return GetTextIndexFromPositionInNoneWrap(_CoordinateSystemUtils::ConvertToFloat(x), _CoordinateSystemUtils::ConvertToFloat(y), cursorMode);
@@ -2687,6 +2965,7 @@ TextObject::GetTextIndexFromPositionInNoneWrap(float x, float y, bool cursorMode
        FloatRectangle lineBounds;
        int lineOffset = 0;
        int lineLength = 0;
+       float firstDisplayPositionX = __pTextColumn->GetFirstDisplayPositionX();
        TextLine* pTextLine = null;
 
        pTextLine = __pTextColumn->GetTextLine(0);
@@ -2700,6 +2979,8 @@ TextObject::GetTextIndexFromPositionInNoneWrap(float x, float y, bool cursorMode
        lineBounds = pTextLine->GetBoundsF();
        pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
 
+       x += firstDisplayPositionX;
+
        switch (__align & TEXT_ALIGNMASK_HORIZ)
        {
        case TEXT_OBJECT_ALIGNMENT_LEFT:
@@ -2741,10 +3022,76 @@ TextObject::GetTextIndexFromPositionInNoneWrap(float x, float y, bool cursorMode
        return index;
 }
 
-result
-TextObject::SetFirstDisplayLineIndexFromTextIndexInWrap(int textIndex)
+int
+TextObject::GetTextIndexFromPositionInNoneWrap(float x, float y, int& row, int& column, bool cursorMode) const
 {
-       result r = E_SUCCESS;
+       FloatDimension lineTextSize;
+       FloatRectangle lineBounds;
+       int lineOffset = 0;
+       int lineLength = 0;
+       float firstDisplayPositionX = __pTextColumn->GetFirstDisplayPositionX();
+       TextLine* pTextLine = null;
+
+       pTextLine = __pTextColumn->GetTextLine(0);
+       SysTryReturn(NID_GRP, pTextLine, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
+
+       TextBidiHint bidiHint = _GetTextBidiHint();
+       _SetTextBidiHint(__bidiHint);
+
+       lineOffset = pTextLine->GetTextOffset();
+       lineLength = pTextLine->GetTextLength();
+       lineBounds = pTextLine->GetBoundsF();
+       pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
+
+       x += firstDisplayPositionX;
+
+       switch (__align & TEXT_ALIGNMASK_HORIZ)
+       {
+       case TEXT_OBJECT_ALIGNMENT_LEFT:
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_CENTER:
+               x -= (lineBounds.width - lineTextSize.width) / 2.0f;
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_RIGHT:
+               x -= (lineBounds.width - lineTextSize.width);
+               break;
+       }
+
+       switch (__align & TEXT_ALIGNMASK_VERT)
+       {
+       case TEXT_OBJECT_ALIGNMENT_TOP:
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_MIDDLE:
+               y -= (__rect.height - lineTextSize.height) / 2.0f;
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_BOTTOM:
+               y -= (__rect.height - lineTextSize.height);
+               break;
+       }
+
+       if (x < 0.0f)
+       {
+               x = 0.0f;
+       }
+
+       int index = pTextLine->GetTextIndexFromPosition(x);
+       row = 0;
+       column = index;
+
+       _SetTextBidiHint(bidiHint);
+
+       SetLastResult(E_SUCCESS);
+       return index;
+}
+
+result
+TextObject::SetFirstDisplayLineIndexFromTextIndexInWrap(int textIndex)
+{
+       result r = E_SUCCESS;
        FloatRectangle lineBounds;
        float firstDisplayPositionY = 0.0f;
        int currentTextIndex = textIndex;
@@ -2929,13 +3276,15 @@ TextObject::SetFirstDisplayLineIndexFromTextIndexInWrap(int textIndex)
 result
 TextObject::SetFirstDisplayLineIndexFromTextIndexInNoneWrap(int textIndex)
 {
-       result r = E_SUCCESS;
-       int currentTextIndex = textIndex;
        int lineOffset = 0;
        int lineEndIndex = 0;
        int lineLength = 0;
+       int count = 0;
+       float firstDisplayPositionX = __pTextColumn->GetFirstDisplayPositionX();
        FloatRectangle lineBounds;
        FloatDimension lineTextSize;
+       FloatDimension currentLinetextSize;
+       FloatDimension prevTextSize;
 
        _FontImpl* pFont = _FontImpl::GetInstance(*__pDefaultFont);
        SysTryReturn(NID_GRP, pFont, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get native font instance.");
@@ -2946,71 +3295,66 @@ TextObject::SetFirstDisplayLineIndexFromTextIndexInNoneWrap(int textIndex)
        lineOffset = pTextLine->GetTextOffset();
        lineLength = pTextLine->GetTextLength();
        lineEndIndex = pTextLine->GetTextOffset() + pTextLine->GetTextLength();
-
        lineBounds = pTextLine->GetBoundsF();
-       pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
 
-       if (currentTextIndex < pTextLine->GetTextOffset() + 1)
-       {
-               lineOffset = currentTextIndex;
-               pTextLine->SetTextOffset(lineOffset);
-               lineOffset = pTextLine->GetTextOffset();
-               if (lineOffset > 0)
-               {
-                       lineOffset--;
-                       pTextLine->SetTextOffset(lineOffset);
-               }
+       pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
 
-               __pCompositeText->ForwardAnalyze(lineOffset, __pCompositeText->GetTextLength() - lineOffset, lineBounds.width,
-                                                                               __wrap, lineLength, lineTextSize.width, lineTextSize.height);
+       __pCompositeText->ForwardAnalyze(lineOffset, textIndex, lineBounds.width, __wrap, count, currentLinetextSize.width, currentLinetextSize.height);
+       __pCompositeText->ForwardAnalyze(lineOffset, textIndex - 1, lineBounds.width,__wrap, count, prevTextSize.width, prevTextSize.height);
 
-               lineBounds.height = (lineBounds.height > lineTextSize.height) ? lineBounds.height : lineTextSize.height;
-               if (lineBounds.height == 0.0f)
-               {
-                       lineBounds.height = TextUtility::GetFontMaxHeightF(pFont);
-               }
+       if (prevTextSize.width < firstDisplayPositionX)
+       {
+               SetFirstDisplayPositionX(prevTextSize.width);
 
                pTextLine->SetBounds(lineBounds);
                pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
                pTextLine->SetTextLength(lineLength);
                __pCompositeText->GetTextExtentList(pTextLine);
        }
-       else if (lineEndIndex <= currentTextIndex)
+       else if (firstDisplayPositionX + __rect.width <= currentLinetextSize.width) // 글자가 display 영역 뒤로 계속 쓸 때
        {
-               float gapWidth = 0.0f;
-               float gapHeight = 0.0f;
                float tempWidth = 0.0f;
+               float tempHeight = 0.0f;
                int textCount = 0;
 
-               r = __pCompositeText->GetRegion(lineEndIndex, currentTextIndex - lineEndIndex, gapWidth, gapHeight);
-               SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
+               __pCompositeText->ForwardAnalyze(0, textIndex, lineBounds.width, __wrap, textCount, tempWidth, tempHeight);
+               SetFirstDisplayPositionX(tempWidth - __rect.width);
 
-               gapWidth -= lineBounds.width - lineTextSize.width;
+               pTextLine->SetBounds(lineBounds);
+               pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
+               pTextLine->SetTextOffset(0);
+               pTextLine->SetTextLength(lineLength);
+               __pCompositeText->GetTextExtentList(pTextLine);
+       }
+       else if (lineBounds.width < firstDisplayPositionX + __rect.width && lineLength <= textIndex) // 글 꽉 채운 후 한글자씩 지울 때
+       {
+               float tempWidth = 0.0f;
+               float tempHeight = 0.0f;
+               int textCount = 0;
 
-               __pCompositeText->ForwardAnalyze(lineOffset, __pCompositeText->GetTextLength() - lineOffset, gapWidth, __wrap,
-                               textCount, tempWidth, gapHeight);
+               __pCompositeText->ForwardAnalyze(0, textIndex, lineBounds.width, __wrap, textCount, tempWidth, tempHeight);
+               SetFirstDisplayPositionX(tempWidth - __rect.width);
 
-               if (tempWidth < gapWidth)
-               {
-                       lineOffset += (textCount + 1);
-               }
-               else
-               {
-                       lineOffset += textCount;
-               }
+               pTextLine->SetBounds(lineBounds);
+               pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
+               pTextLine->SetTextOffset(0);
+               pTextLine->SetTextLength(lineLength);
+               __pCompositeText->GetTextExtentList(pTextLine);
+       }
+       else if (lineBounds.width < firstDisplayPositionX + __rect.width) // 글 꽉 채운 후에, 중간에 글자를 지울 때,
+       {
+               float tempWidth = 0.0f;
+               float tempHeight = 0.0f;
+               int textCount = 0;
 
-               __pCompositeText->ForwardAnalyze(lineOffset, __pCompositeText->GetTextLength() - lineOffset, lineBounds.width,
-                                                                               __wrap, lineLength, lineTextSize.width, lineTextSize.height);
+               float gap = __rect.width - (lineBounds.width - currentLinetextSize.width);
 
-               lineBounds.height = (lineBounds.height > lineTextSize.height) ? lineBounds.height: lineTextSize.height;
-               if (lineBounds.height == 0.0f)
-               {
-                       lineBounds.height = TextUtility::GetFontMaxHeightF(pFont);
-               }
+               __pCompositeText->ForwardAnalyze(0, textIndex, lineBounds.width, __wrap, textCount, tempWidth, tempHeight);
+               SetFirstDisplayPositionX(tempWidth - gap);
 
                pTextLine->SetBounds(lineBounds);
                pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
-               pTextLine->SetTextOffset(lineOffset);
+               pTextLine->SetTextOffset(0);
                pTextLine->SetTextLength(lineLength);
                __pCompositeText->GetTextExtentList(pTextLine);
        }
@@ -3187,6 +3531,122 @@ TextObject::GetTextPositionInfoInWrapAt(int textIndex, float& width, float& heig
 }
 
 result
+TextObject::GetTextPositionInfoInWrapAt(int row, int column, float& width, float& height, float& absX, float& absY,
+                                                                                                                                       float& logicalX, float& logicalY) const
+{
+       TextLine* pTextLine = null;
+       float firstDisplayPositionY = __pTextColumn->GetFirstDisplayPositionYF();
+       int lineCount = __pTextColumn->GetTotalLineCount();
+       float posX = 0.0f;
+       float posY = 0.0f;
+
+       _FontImpl* pFont = _FontImpl::GetInstance(*__pDefaultFont);
+       SysTryReturn(NID_GRP, pFont, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get native font instance.");
+
+       pTextLine = __pTextColumn->GetTextLine(row);
+       SysTryReturn(NID_GRP, pTextLine, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
+
+       FloatRectangle lineBounds = pTextLine->GetBoundsF();
+       int lineOffset = pTextLine->GetTextOffset();
+       int lineLength = pTextLine->GetTextLength();
+       int textIndex = pTextLine->GetTextOffset() + column;
+       float lineY = lineBounds.y;
+
+       SysTryReturn(NID_GRP, lineOffset <= textIndex && textIndex <= lineOffset + lineLength
+               , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid. (row = %d column = %d)", row, column);
+
+       FloatDimension lineTextSize;
+       pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
+
+       if (lineTextSize.height == 0)
+       {
+               lineTextSize.height = TextUtility::GetFontMaxHeightF(pFont);
+       }
+
+       switch (__align & TEXT_ALIGNMASK_HORIZ)
+       {
+       case TEXT_OBJECT_ALIGNMENT_LEFT:
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_CENTER:
+               posX += (lineBounds.width - lineTextSize.width) / 2.0f;
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_RIGHT:
+               posX += (lineBounds.width - lineTextSize.width);
+               break;
+       }
+
+       switch (__align & TEXT_ALIGNMASK_VERT)
+       {
+       case TEXT_OBJECT_ALIGNMENT_TOP:
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_MIDDLE:
+               posY += (__rect.height - __pTextColumn->GetDisplayHeightF()) / 2.0f;
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_BOTTOM:
+               posY += (__rect.height - __pTextColumn->GetDisplayHeightF());
+               break;
+       }
+
+       if (posX < 0.0f)
+       {
+               posX = 0.0f;
+       }
+
+       if (posY < 0.0f)
+       {
+               posY = 0.0f;
+       }
+
+       FloatRectangle textExtent = pTextLine->GetTextExtentF(column, 1);
+
+       if (row == lineCount)
+       {
+               textExtent.width = 0.0f;
+       }
+
+       if (textIndex >= 1)
+       {
+               Font* pTextFont = __pCompositeText->GetFont(textIndex - 1);
+               textExtent.height = TextUtility::GetFontMaxHeightF(pTextFont);
+       }
+
+       if (textExtent.height < 0.0f)
+       {
+               textExtent.height = TextUtility::GetFontMaxHeightF(pFont);
+       }
+
+       TextObjectAlignment alignment = __pCompositeText->GetElementVerticalAlignment();
+       switch (alignment & TEXT_ALIGNMASK_VERT)
+       {
+       case TEXT_OBJECT_ALIGNMENT_TOP:
+               // fall through
+       default:
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_MIDDLE:
+               lineY = lineY + (lineBounds.height - textExtent.height) / 2.0f;
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_BOTTOM:
+               lineY = lineY + (lineBounds.height - textExtent.height);
+               break;
+       }
+
+       width =  textExtent.width;
+       height =  textExtent.height;
+       absX = posX + textExtent.x;
+       logicalX = absX + __rect.x;
+       absY = lineY;
+       logicalY = absY - firstDisplayPositionY + __rect.y + posY;
+
+       return E_SUCCESS;
+}
+
+result
 TextObject::GetBlockTextPositionInfoInWrapAt(int textIndex, int& width, int& height, int& absX, int& absY,
                                                                                                                                        int& logicalX, int& logicalY) const
 {
@@ -3384,6 +3844,7 @@ TextObject::GetTextPositionInfoInNoneWrapAt(int textIndex, float& width, float&
        SysTryReturn(NID_GRP, pTextLine, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
 
        int lineLength = pTextLine->GetTextLength();
+       float firstDisplayPositionX = __pTextColumn->GetFirstDisplayPositionX();
        float posX = 0.0f;
        float posY = 0.0f;
 
@@ -3461,7 +3922,104 @@ TextObject::GetTextPositionInfoInNoneWrapAt(int textIndex, float& width, float&
                break;
        }
 
-       absX = posX + textExtent.x;
+       absX = posX + textExtent.x - firstDisplayPositionX;
+       logicalX = (absX >= 0.0f) ? absX + __rect.x : absX;
+       absY = posY;
+       logicalY = absY + __rect.y;
+       width = textExtent.width;
+       height = textExtent.height;
+
+       return E_SUCCESS;
+}
+
+result
+TextObject::GetTextPositionInfoInNoneWrapAt(int row, int column, float& width, float& height, float& absX, float& absY,
+                                                                                                                               float& logicalX, float& logicalY) const
+{
+       TextLine* pTextLine = null;
+       pTextLine = __pTextColumn->GetTextLine(row);
+       SysTryReturn(NID_GRP, pTextLine, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
+
+       int lineLength = pTextLine->GetTextLength();
+       float firstDisplayPositionX = __pTextColumn->GetFirstDisplayPositionX();
+       float posX = 0.0f;
+       float posY = 0.0f;
+
+       _FontImpl* pFont = _FontImpl::GetInstance(*__pDefaultFont);
+       SysTryReturn(NID_GRP, pFont, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get native font instance.");
+
+       FloatDimension lineTextSize;
+       FloatRectangle lineBounds;
+       lineBounds = pTextLine->GetBoundsF();
+       pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
+
+       if (lineTextSize.height == 0.0f || pTextLine->GetTextLength() == 0.0f)
+       {
+               lineTextSize.height = TextUtility::GetFontMaxHeightF(pFont);
+       }
+
+       switch (__align & TEXT_ALIGNMASK_HORIZ)
+       {
+       case TEXT_OBJECT_ALIGNMENT_LEFT:
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_CENTER:
+               posX += (lineBounds.width - lineTextSize.width) / 2.0f;
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_RIGHT:
+               posX += (lineBounds.width - lineTextSize.width);
+               break;
+       }
+
+       switch (__align & TEXT_ALIGNMASK_VERT)
+       {
+       case TEXT_OBJECT_ALIGNMENT_TOP:
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_MIDDLE:
+               posY += (__rect.height - lineTextSize.height) / 2.0f;
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_BOTTOM:
+               posY += (__rect.height - lineTextSize.height);
+               break;
+       }
+
+       posX = (posX < 0.0f) ? 0.0f : posX;
+       posY = (posY < 0.0f) ? 0.0f : posY;
+
+       FloatRectangle textExtent = pTextLine->GetTextExtentF(column - pTextLine->GetTextOffset(), 1);
+
+       if (column >= 1)
+       {
+               Font* pTextFont = __pCompositeText->GetFont(column - 1);
+               textExtent.height = TextUtility::GetFontMaxHeightF(pTextFont);
+       }
+
+       if (textExtent.height < 0.0f)
+       {
+               textExtent.height = TextUtility::GetFontMaxHeightF(pFont);
+       }
+
+       TextObjectAlignment alignment = __pCompositeText->GetElementVerticalAlignment();
+       switch (alignment & TEXT_ALIGNMASK_VERT)
+       {
+       case TEXT_OBJECT_ALIGNMENT_TOP:
+               // fall through
+       default:
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_MIDDLE:
+               posY = posY + (lineBounds.height - textExtent.height) / 2.0f;
+               break;
+
+       case TEXT_OBJECT_ALIGNMENT_BOTTOM:
+               posY = posY + (lineBounds.height - textExtent.height);
+               break;
+       }
+
+       absX = posX + textExtent.x - firstDisplayPositionX;
        logicalX = (absX >= 0.0f) ? absX + __rect.x : absX;
        absY = posY;
        logicalY = absY + __rect.y;
@@ -4190,6 +4748,59 @@ TextObject::GetTextBidiHint(void) const
 }
 
 result
+TextObject::ConvertToRowColumn(int textIndex, int& row, int& column) const
+{
+       IF_NOT_CONSTRUCTED(return E_INVALID_STATE);
+
+       SysTryReturn(NID_GRP, textIndex >= 0 && textIndex <= GetTextLength(), E_INVALID_ARG, E_INVALID_ARG
+               , "[E_INVALID_ARG] The argument is invalid. (textIndex = %d)", textIndex);
+
+       TextLine* pTextLine = null;
+       int lineIndex = 0;
+       int lineOffset = 0;
+       int lineLength = 0;
+       int lineCount = GetTotalLineCount();
+
+       for (lineIndex = 0; lineIndex < lineCount; lineIndex++)
+       {
+               pTextLine = __pTextColumn->GetTextLine(lineIndex);
+               SysTryReturn(NID_GRP, pTextLine, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
+
+               lineOffset = pTextLine->GetTextOffset();
+               lineLength = pTextLine->GetTextLength();
+
+               if (lineOffset <= textIndex && textIndex < lineOffset + lineLength)
+               {
+                       break;
+               }
+       }
+       
+       column = (lineIndex == lineCount) ? lineLength : textIndex - lineOffset;
+       row = (lineIndex == lineCount) ? lineIndex - 1 : lineIndex;
+
+       return E_SUCCESS;
+}
+
+int
+TextObject::ConvertToTextIndex(int row, int column) const
+{
+       IF_NOT_CONSTRUCTED(return -1);
+
+       TextLine* pTextLine = __pTextColumn->GetTextLine(row);
+       SysTryReturn(NID_GRP, pTextLine, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
+
+       int lineOffset = pTextLine->GetTextOffset();
+       int lineLength = pTextLine->GetTextLength();
+
+       SysTryReturn(NID_GRP, column <= lineLength, -1, E_INVALID_ARG
+               , "[E_INVALID_ARG] The argument is invalid. (row = %d, column = %d)", row, column);
+
+       SetLastResult(E_SUCCESS);
+
+       return lineOffset + column;
+}
+
+result
 TextObject::SetDisplayBoundsExpandEnabled(bool enable)
 {
        IF_NOT_CONSTRUCTED(return E_INVALID_STATE);