Multiple text background color support for left-to-right text only in TextField
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller-impl.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 6a90595..fa48e52
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/adaptor-framework/key.h>
+#include <dali/public-api/rendering/renderer.h>
 #include <dali/integration-api/debug.h>
 #include <limits>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/internal/text/bidirectional-support.h>
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/color-segmentation.h>
@@ -34,6 +36,8 @@
 #include <dali-toolkit/internal/text/text-control-interface.h>
 #include <dali-toolkit/internal/text/text-run-container.h>
 
+using namespace Dali;
+
 namespace
 {
 
@@ -56,6 +60,44 @@ const float MAX_FLOAT = std::numeric_limits<float>::max();
 const float MIN_FLOAT = std::numeric_limits<float>::min();
 const Dali::Toolkit::Text::CharacterDirection LTR = false; ///< Left To Right direction
 
+#define MAKE_SHADER(A)#A
+
+const char* VERTEX_SHADER_BACKGROUND = MAKE_SHADER(
+attribute mediump vec2    aPosition;
+attribute mediump vec4    aColor;
+varying   mediump vec4    vColor;
+uniform   highp mat4      uMvpMatrix;
+
+void main()
+{
+  mediump vec4 position = vec4( aPosition, 0.0, 1.0 );
+  gl_Position = uMvpMatrix * position;
+  vColor = aColor;
+}
+);
+
+const char* FRAGMENT_SHADER_BACKGROUND = MAKE_SHADER(
+varying mediump vec4      vColor;
+uniform lowp    vec4      uColor;
+
+void main()
+{
+  gl_FragColor = vColor * uColor;
+}
+);
+
+struct BackgroundVertex
+{
+  Vector2 mPosition;        ///< Vertex posiiton
+  Vector4 mColor;           ///< Vertex color
+};
+
+struct BackgroundMesh
+{
+  Vector< BackgroundVertex > mVertices;    ///< container of vertices
+  Vector< unsigned short > mIndices;       ///< container of indices
+};
+
 } // namespace
 
 namespace Dali
@@ -67,14 +109,13 @@ namespace Toolkit
 namespace Text
 {
 
-EventData::EventData( DecoratorPtr decorator )
+EventData::EventData( DecoratorPtr decorator, InputMethodContext& inputMethodContext )
 : mDecorator( decorator ),
-  mImfManager(),
+  mInputMethodContext( inputMethodContext ),
   mPlaceholderFont( NULL ),
-  mPlaceholderText(),
   mPlaceholderTextActive(),
   mPlaceholderTextInactive(),
-  mPlaceholderTextColor( 0.8f, 0.8f, 0.8f, 0.8f ),
+  mPlaceholderTextColor( 0.8f, 0.8f, 0.8f, 0.8f ), // This color has been published in the Public API (placeholder-properties.h).
   mEventQueue(),
   mInputStyleChangedQueue(),
   mPreviousState( INACTIVE ),
@@ -107,9 +148,13 @@ EventData::EventData( DecoratorPtr decorator )
   mAllTextSelected( false ),
   mUpdateInputStyle( false ),
   mPasswordInput( false ),
-  mIsPlaceholderPixelSize( false )
+  mCheckScrollAmount( false ),
+  mIsPlaceholderPixelSize( false ),
+  mIsPlaceholderElideEnabled( false ),
+  mPlaceholderEllipsisFlag( false ),
+  mShiftSelectionFlag( true ),
+  mUpdateAlignment( false )
 {
-  mImfManager = ImfManager::Get();
 }
 
 EventData::~EventData()
@@ -177,7 +222,7 @@ bool Controller::Impl::ProcessInputEvents()
   if( mEventData->mUpdateCursorPosition ||
       mEventData->mUpdateHighlightBox )
   {
-    NotifyImfManager();
+    NotifyInputMethodContext();
   }
 
   // The cursor must also be repositioned after inserts into the model
@@ -326,9 +371,9 @@ bool Controller::Impl::ProcessInputEvents()
   return decoratorUpdated;
 }
 
-void Controller::Impl::NotifyImfManager()
+void Controller::Impl::NotifyInputMethodContext()
 {
-  if( mEventData && mEventData->mImfManager )
+  if( mEventData && mEventData->mInputMethodContext )
   {
     CharacterIndex cursorPosition = GetLogicalCursorPosition();
 
@@ -344,17 +389,17 @@ void Controller::Impl::NotifyImfManager()
       cursorPosition -= numberOfWhiteSpaces;
     }
 
-    mEventData->mImfManager.SetCursorPosition( cursorPosition );
-    mEventData->mImfManager.NotifyCursorPosition();
+    mEventData->mInputMethodContext.SetCursorPosition( cursorPosition );
+    mEventData->mInputMethodContext.NotifyCursorPosition();
   }
 }
 
-void Controller::Impl::NotifyImfMultiLineStatus()
+void Controller::Impl::NotifyInputMethodContextMultiLineStatus()
 {
-  if ( mEventData )
+  if ( mEventData && mEventData->mInputMethodContext )
   {
     Text::Layout::Engine::Type layout = mLayoutEngine.GetLayout();
-    mEventData->mImfManager.NotifyTextInputMultiLine( layout == Text::Layout::Engine::MULTI_LINE_BOX );
+    mEventData->mInputMethodContext.NotifyTextInputMultiLine( layout == Text::Layout::Engine::MULTI_LINE_BOX );
   }
 }
 
@@ -502,11 +547,6 @@ void Controller::Impl::ClearFullModelData( OperationsMask operations )
     mModel->mLogicalModel->mParagraphInfo.Clear();
   }
 
-  if( NO_OPERATION != ( GET_WORD_BREAKS & operations ) )
-  {
-    mModel->mLogicalModel->mLineBreakInfo.Clear();
-  }
-
   if( NO_OPERATION != ( GET_SCRIPTS & operations ) )
   {
     mModel->mLogicalModel->mScriptRuns.Clear();
@@ -560,6 +600,7 @@ void Controller::Impl::ClearFullModelData( OperationsMask operations )
   if( NO_OPERATION != ( COLOR & operations ) )
   {
     mModel->mVisualModel->mColorIndices.Clear();
+    mModel->mVisualModel->mBackgroundColorIndices.Clear();
   }
 }
 
@@ -581,15 +622,6 @@ void Controller::Impl::ClearCharacterModelData( CharacterIndex startIndex, Chara
                         mModel->mLogicalModel->mParagraphInfo );
   }
 
-  if( NO_OPERATION != ( GET_WORD_BREAKS & operations ) )
-  {
-    // Clear the word break info.
-    WordBreakInfo* wordBreakInfoBuffer = mModel->mLogicalModel->mWordBreakInfo.Begin();
-
-    mModel->mLogicalModel->mWordBreakInfo.Erase( wordBreakInfoBuffer + startIndex,
-                                         wordBreakInfoBuffer + endIndexPlusOne );
-  }
-
   if( NO_OPERATION != ( GET_SCRIPTS & operations ) )
   {
     // Clear the scripts.
@@ -752,6 +784,13 @@ void Controller::Impl::ClearGlyphModelData( CharacterIndex startIndex, Character
       mModel->mVisualModel->mColorIndices.Erase( colorIndexBuffer + mTextUpdateInfo.mStartGlyphIndex,
                                                  colorIndexBuffer + endGlyphIndexPlusOne );
     }
+
+    if( 0u != mModel->mVisualModel->mBackgroundColorIndices.Count() )
+    {
+      ColorIndex* backgroundColorIndexBuffer = mModel->mVisualModel->mBackgroundColorIndices.Begin();
+      mModel->mVisualModel->mBackgroundColorIndices.Erase( backgroundColorIndexBuffer + mTextUpdateInfo.mStartGlyphIndex,
+                                                           backgroundColorIndexBuffer + endGlyphIndexPlusOne );
+    }
   }
 }
 
@@ -809,6 +848,36 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
   Length paragraphCharacters = 0u;
 
   CalculateTextUpdateIndices( paragraphCharacters );
+
+  // Check whether the indices for updating the text is valid
+  if ( numberOfCharacters > 0u &&
+       ( mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters ||
+         mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters ) )
+  {
+    std::string currentText;
+    Utf32ToUtf8( mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText );
+
+    DALI_LOG_ERROR( "Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n" );
+    DALI_LOG_ERROR( "Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str() );
+
+    // Dump mTextUpdateInfo
+    DALI_LOG_ERROR( "Dump mTextUpdateInfo:\n" );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mCharacterIndex = %u\n", mTextUpdateInfo.mCharacterIndex );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", mTextUpdateInfo.mNumberOfCharactersToRemove );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", mTextUpdateInfo.mNumberOfCharactersToAdd );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", mTextUpdateInfo.mPreviousNumberOfCharacters );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mParagraphCharacterIndex = %u\n", mTextUpdateInfo.mParagraphCharacterIndex );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", mTextUpdateInfo.mRequestedNumberOfCharacters );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mStartGlyphIndex = %u\n", mTextUpdateInfo.mStartGlyphIndex );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mStartLineIndex = %u\n", mTextUpdateInfo.mStartLineIndex );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", mTextUpdateInfo.mEstimatedNumberOfLines );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mClearAll = %d\n", mTextUpdateInfo.mClearAll );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mFullRelayoutNeeded = %d\n", mTextUpdateInfo.mFullRelayoutNeeded );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", mTextUpdateInfo.mIsLastCharacterNewParagraph );
+
+    return false;
+  }
+
   startIndex = mTextUpdateInfo.mParagraphCharacterIndex;
 
   if( mTextUpdateInfo.mClearAll ||
@@ -844,19 +913,6 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
     updated = true;
   }
 
-  Vector<WordBreakInfo>& wordBreakInfo = mModel->mLogicalModel->mWordBreakInfo;
-  if( NO_OPERATION != ( GET_WORD_BREAKS & operations ) )
-  {
-    // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines).
-    wordBreakInfo.Resize( numberOfCharacters, TextAbstraction::WORD_NO_BREAK );
-
-    SetWordBreakInfo( utf32Characters,
-                      startIndex,
-                      requestedNumberOfCharacters,
-                      wordBreakInfo );
-    updated = true;
-  }
-
   const bool getScripts = NO_OPERATION != ( GET_SCRIPTS & operations );
   const bool validateFonts = NO_OPERATION != ( VALIDATE_FONTS & operations );
 
@@ -887,7 +943,7 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
       TextAbstraction::FontDescription defaultFontDescription;
       TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
 
-      if( IsShowingPlaceholderText() && ( NULL != mEventData->mPlaceholderFont ) )
+      if( IsShowingPlaceholderText() && mEventData && ( NULL != mEventData->mPlaceholderFont ) )
       {
         // If the placeholder font is set specifically, only placeholder font is changed.
         defaultFontDescription = mEventData->mPlaceholderFont->mFontDescription;
@@ -900,7 +956,15 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
       {
         // Set the normal font and the placeholder font.
         defaultFontDescription = mFontDefaults->mFontDescription;
-        defaultPointSize = mFontDefaults->mDefaultPointSize * 64u;
+
+        if( mTextFitEnabled )
+        {
+          defaultPointSize = mFontDefaults->mFitPointSize * 64u;
+        }
+        else
+        {
+          defaultPointSize = mFontDefaults->mDefaultPointSize * 64u;
+        }
       }
 
       // Validates the fonts. If there is a character with no assigned font it sets a default one.
@@ -931,7 +995,9 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
                           lineBreakInfo,
                           startIndex,
                           requestedNumberOfCharacters,
-                          bidirectionalInfo );
+                          bidirectionalInfo,
+                          mModel->mMatchSystemLanguageDirection,
+                          mLayoutDirection );
 
     if( 0u != bidirectionalInfo.Count() )
     {
@@ -1010,6 +1076,41 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
     updated = true;
   }
 
+  if( ( NULL != mEventData ) &&
+      mEventData->mPreEditFlag &&
+      ( 0u != mModel->mVisualModel->mCharactersToGlyph.Count() ) )
+  {
+    Dali::InputMethodContext::PreeditStyle type = mEventData->mInputMethodContext.GetPreeditStyle();
+
+    switch( type )
+    {
+      case Dali::InputMethodContext::PreeditStyle::UNDERLINE:
+      {
+        // Add the underline for the pre-edit text.
+        const GlyphIndex* const charactersToGlyphBuffer = mModel->mVisualModel->mCharactersToGlyph.Begin();
+        const Length* const glyphsPerCharacterBuffer = mModel->mVisualModel->mGlyphsPerCharacter.Begin();
+
+        const GlyphIndex glyphStart = *( charactersToGlyphBuffer + mEventData->mPreEditStartPosition );
+        const CharacterIndex lastPreEditCharacter = mEventData->mPreEditStartPosition + ( ( mEventData->mPreEditLength > 0u ) ? mEventData->mPreEditLength - 1u : 0u );
+        const Length numberOfGlyphsLastCharacter = *( glyphsPerCharacterBuffer + lastPreEditCharacter );
+        const GlyphIndex glyphEnd = *( charactersToGlyphBuffer + lastPreEditCharacter ) + ( numberOfGlyphsLastCharacter > 1u ? numberOfGlyphsLastCharacter - 1u : 0u );
+
+        GlyphRun underlineRun;
+        underlineRun.glyphIndex = glyphStart;
+        underlineRun.numberOfGlyphs = 1u + glyphEnd - glyphStart;
+
+        mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
+        break;
+      }
+      // TODO :  At this moment, other styles for preedit are not implemented yet.
+      case Dali::InputMethodContext::PreeditStyle::REVERSE:
+      case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
+      case Dali::InputMethodContext::PreeditStyle::NONE:
+      default:
+        break;
+    }
+  }
+
   if( NO_OPERATION != ( COLOR & operations ) )
   {
     // Set the color runs in glyphs.
@@ -1022,29 +1123,19 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
                               mModel->mVisualModel->mColors,
                               mModel->mVisualModel->mColorIndices );
 
+    // Set the background color runs in glyphs.
+    SetColorSegmentationInfo( mModel->mLogicalModel->mBackgroundColorRuns,
+                              mModel->mVisualModel->mCharactersToGlyph,
+                              mModel->mVisualModel->mGlyphsPerCharacter,
+                              startIndex,
+                              mTextUpdateInfo.mStartGlyphIndex,
+                              requestedNumberOfCharacters,
+                              mModel->mVisualModel->mBackgroundColors,
+                              mModel->mVisualModel->mBackgroundColorIndices );
+
     updated = true;
   }
 
-  if( ( NULL != mEventData ) &&
-      mEventData->mPreEditFlag &&
-      ( 0u != mModel->mVisualModel->mCharactersToGlyph.Count() ) )
-  {
-    // Add the underline for the pre-edit text.
-    const GlyphIndex* const charactersToGlyphBuffer = mModel->mVisualModel->mCharactersToGlyph.Begin();
-    const Length* const glyphsPerCharacterBuffer = mModel->mVisualModel->mGlyphsPerCharacter.Begin();
-
-    const GlyphIndex glyphStart = *( charactersToGlyphBuffer + mEventData->mPreEditStartPosition );
-    const CharacterIndex lastPreEditCharacter = mEventData->mPreEditStartPosition + ( ( mEventData->mPreEditLength > 0u ) ? mEventData->mPreEditLength - 1u : 0u );
-    const Length numberOfGlyphsLastCharacter = *( glyphsPerCharacterBuffer + lastPreEditCharacter );
-    const GlyphIndex glyphEnd = *( charactersToGlyphBuffer + lastPreEditCharacter ) + ( numberOfGlyphsLastCharacter > 1u ? numberOfGlyphsLastCharacter - 1u : 0u );
-
-    GlyphRun underlineRun;
-    underlineRun.glyphIndex = glyphStart;
-    underlineRun.numberOfGlyphs = 1u + glyphEnd - glyphStart;
-
-    // TODO: At the moment the underline runs are only for pre-edit.
-    mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
-  }
 
   // The estimated number of lines. Used to avoid reallocations when layouting.
   mTextUpdateInfo.mEstimatedNumberOfLines = std::max( mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count() );
@@ -1143,30 +1234,49 @@ float Controller::Impl::GetDefaultFontLineHeight()
 
 void Controller::Impl::OnCursorKeyEvent( const Event& event )
 {
-  if( NULL == mEventData )
+  if( NULL == mEventData || !IsShowingRealText() )
   {
     // Nothing to do if there is no text input.
     return;
   }
 
   int keyCode = event.p1.mInt;
+  bool isShiftModifier = event.p2.mBool;
+
+  CharacterIndex previousPrimaryCursorPosition = mEventData->mPrimaryCursorPosition;
 
   if( Dali::DALI_KEY_CURSOR_LEFT == keyCode )
   {
     if( mEventData->mPrimaryCursorPosition > 0u )
     {
-      mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition - 1u );
+      if ( !isShiftModifier && mEventData->mDecorator->IsHighlightVisible() )
+      {
+        mEventData->mPrimaryCursorPosition = std::min(mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
+      }
+      else
+      {
+        mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition - 1u );
+      }
     }
   }
   else if( Dali::DALI_KEY_CURSOR_RIGHT == keyCode )
   {
     if( mModel->mLogicalModel->mText.Count() > mEventData->mPrimaryCursorPosition )
     {
-      mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition );
+      if ( !isShiftModifier && mEventData->mDecorator->IsHighlightVisible() )
+      {
+        mEventData->mPrimaryCursorPosition = std::max(mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
+      }
+      else
+      {
+        mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition );
+      }
     }
   }
-  else if( Dali::DALI_KEY_CURSOR_UP == keyCode )
+  else if( Dali::DALI_KEY_CURSOR_UP == keyCode && !isShiftModifier )
   {
+    // Ignore Shift-Up for text selection for now.
+
     // Get first the line index of the current cursor position index.
     CharacterIndex characterIndex = 0u;
 
@@ -1199,8 +1309,10 @@ void Controller::Impl::OnCursorKeyEvent( const Event& event )
                                                                       CharacterHitTest::TAP,
                                                                       matchedCharacter );
   }
-  else if( Dali::DALI_KEY_CURSOR_DOWN == keyCode )
+  else if( Dali::DALI_KEY_CURSOR_DOWN == keyCode && !isShiftModifier )
   {
+    // Ignore Shift-Down for text selection for now.
+
     // Get first the line index of the current cursor position index.
     CharacterIndex characterIndex = 0u;
 
@@ -1236,7 +1348,64 @@ void Controller::Impl::OnCursorKeyEvent( const Event& event )
     }
   }
 
-  mEventData->mUpdateCursorPosition = true;
+  if ( !isShiftModifier && mEventData->mState != EventData::SELECTING )
+  {
+    // Update selection position after moving the cursor
+    mEventData->mLeftSelectionPosition = mEventData->mPrimaryCursorPosition;
+    mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
+  }
+
+  if ( isShiftModifier && IsShowingRealText() && mEventData->mShiftSelectionFlag )
+  {
+    // Handle text selection
+    bool selecting = false;
+
+    if ( Dali::DALI_KEY_CURSOR_LEFT == keyCode || Dali::DALI_KEY_CURSOR_RIGHT == keyCode )
+    {
+      // Shift-Left/Right to select the text
+      int cursorPositionDelta = mEventData->mPrimaryCursorPosition - previousPrimaryCursorPosition;
+      if ( cursorPositionDelta > 0 || mEventData->mRightSelectionPosition > 0u ) // Check the boundary
+      {
+        mEventData->mRightSelectionPosition += cursorPositionDelta;
+      }
+      selecting = true;
+    }
+    else if ( mEventData->mLeftSelectionPosition != mEventData->mRightSelectionPosition )
+    {
+      // Show no grab handles and text highlight if Shift-Up/Down pressed but no selected text
+      selecting = true;
+    }
+
+    if ( selecting )
+    {
+      // Notify the cursor position to the InputMethodContext.
+      if( mEventData->mInputMethodContext )
+      {
+        mEventData->mInputMethodContext.SetCursorPosition( mEventData->mPrimaryCursorPosition );
+        mEventData->mInputMethodContext.NotifyCursorPosition();
+      }
+
+      ChangeState( EventData::SELECTING );
+
+      mEventData->mUpdateLeftSelectionPosition = true;
+      mEventData->mUpdateRightSelectionPosition = true;
+      mEventData->mUpdateGrabHandlePosition = true;
+      mEventData->mUpdateHighlightBox = true;
+
+      // Hide the text selection popup if select the text using keyboard instead of moving grab handles
+      if( mEventData->mGrabHandlePopupEnabled )
+      {
+        mEventData->mDecorator->SetPopupActive( false );
+      }
+    }
+  }
+  else
+  {
+    // Handle normal cursor move
+    ChangeState( EventData::EDITING );
+    mEventData->mUpdateCursorPosition = true;
+  }
+
   mEventData->mUpdateInputStyle = true;
   mEventData->mScrollAfterUpdatePosition = true;
 }
@@ -1276,16 +1445,20 @@ void Controller::Impl::OnTapEvent( const Event& event )
         mEventData->mPrimaryCursorPosition = 0u;
       }
 
+      // Update selection position after tapping
+      mEventData->mLeftSelectionPosition = mEventData->mPrimaryCursorPosition;
+      mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
+
       mEventData->mUpdateCursorPosition = true;
       mEventData->mUpdateGrabHandlePosition = true;
       mEventData->mScrollAfterUpdatePosition = true;
       mEventData->mUpdateInputStyle = true;
 
-      // Notify the cursor position to the imf manager.
-      if( mEventData->mImfManager )
+      // Notify the cursor position to the InputMethodContext.
+      if( mEventData->mInputMethodContext )
       {
-        mEventData->mImfManager.SetCursorPosition( mEventData->mPrimaryCursorPosition );
-        mEventData->mImfManager.NotifyCursorPosition();
+        mEventData->mInputMethodContext.SetCursorPosition( mEventData->mPrimaryCursorPosition );
+        mEventData->mInputMethodContext.NotifyCursorPosition();
       }
     }
     else if( 2u == tapCount )
@@ -1731,15 +1904,13 @@ void Controller::Impl::OnSelectAllEvent()
 
   if( mEventData->mSelectionEnabled )
   {
-    ChangeState( EventData::SELECTING );
+    // Calculates the logical position from the start.
+    RepositionSelectionHandles( 0.f - mModel->mScrollPosition.x,
+                                0.f - mModel->mScrollPosition.y,
+                                Controller::NoTextTap::HIGHLIGHT );
 
     mEventData->mLeftSelectionPosition = 0u;
     mEventData->mRightSelectionPosition = mModel->mLogicalModel->mText.Count();
-
-    mEventData->mScrollAfterUpdatePosition = true;
-    mEventData->mUpdateLeftSelectionPosition = true;
-    mEventData->mUpdateRightSelectionPosition = true;
-    mEventData->mUpdateHighlightBox = true;
   }
 }
 
@@ -1789,8 +1960,18 @@ void Controller::Impl::RetrieveSelection( std::string& selectedText, bool delete
       mModel->mLogicalModel->UpdateTextStyleRuns( startOfSelectedText, -static_cast<int>( lengthOfSelectedText ) );
 
       // Mark the paragraphs to be updated.
-      mTextUpdateInfo.mCharacterIndex = startOfSelectedText;
-      mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+      if( Layout::Engine::SINGLE_LINE_BOX == mLayoutEngine.GetLayout() )
+      {
+        mTextUpdateInfo.mCharacterIndex = 0;
+        mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
+        mTextUpdateInfo.mNumberOfCharactersToAdd = mTextUpdateInfo.mPreviousNumberOfCharacters - lengthOfSelectedText;
+        mTextUpdateInfo.mClearAll = true;
+      }
+      else
+      {
+        mTextUpdateInfo.mCharacterIndex = startOfSelectedText;
+        mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+      }
 
       // Delete text between handles
       Vector<Character>::Iterator first = utf32Characters.Begin() + startOfSelectedText;
@@ -1861,6 +2042,8 @@ void Controller::Impl::RepositionSelectionHandles()
   if( selectionStart == selectionEnd )
   {
     // Nothing to select if handles are in the same place.
+    // So, deactive Highlight box.
+    mEventData->mDecorator->SetHighlightActive( false );
     return;
   }
 
@@ -2212,7 +2395,7 @@ void Controller::Impl::RepositionSelectionHandles()
   const SelectionBoxInfo& firstSelectionBoxLineInfo = *( selectionBoxLinesInfo.Begin() );
   highLightPosition.y = firstSelectionBoxLineInfo.lineOffset;
 
-  mEventData->mDecorator->SetHighLightBox( highLightPosition, highLightSize );
+  mEventData->mDecorator->SetHighLightBox( highLightPosition, highLightSize, static_cast<float>( mModel->GetOutlineWidth() ) );
 
   if( !mEventData->mDecorator->IsSmoothHandlePanEnabled() )
   {
@@ -2239,9 +2422,6 @@ void Controller::Impl::RepositionSelectionHandles()
                                          secondaryCursorInfo.lineHeight );
   }
 
-  // Cursor to be positioned at end of selection so if selection interrupted and edit mode restarted the cursor will be at end of selection
-  mEventData->mPrimaryCursorPosition = ( indicesSwapped ) ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition;
-
   // Set the flag to update the decorator.
   mEventData->mDecoratorUpdated = true;
 }
@@ -2294,13 +2474,16 @@ void Controller::Impl::RepositionSelectionHandles( float visualX, float visualY,
     mEventData->mUpdateRightSelectionPosition = true;
     mEventData->mUpdateHighlightBox = true;
 
-    // It may happen an IMF commit event arrives before the selection event
-    // if the IMF manager is in pre-edit state. The commit event will set the
+    // It may happen an InputMethodContext commit event arrives before the selection event
+    // if the InputMethodContext is in pre-edit state. The commit event will set the
     // mEventData->mUpdateCursorPosition flag to true. If it's not set back
     // to false, the highlight box won't be updated.
     mEventData->mUpdateCursorPosition = false;
 
     mEventData->mScrollAfterUpdatePosition = ( mEventData->mLeftSelectionPosition != mEventData->mRightSelectionPosition );
+
+    // Cursor to be positioned at end of selection so if selection interrupted and edit mode restarted the cursor will be at end of selection
+    mEventData->mPrimaryCursorPosition = std::max( mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition );
   }
   else if( Controller::NoTextTap::SHOW_SELECTION_POPUP == action )
   {
@@ -2422,8 +2605,11 @@ void Controller::Impl::ChangeState( EventData::State newState )
         mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
         mEventData->mDecorator->StopCursorBlink();
         mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
-        mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
-        mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+        if ( mEventData->mGrabHandleEnabled )
+        {
+          mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
+          mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+        }
         mEventData->mDecorator->SetHighlightActive( true );
         if( mEventData->mGrabHandlePopupEnabled )
         {
@@ -2467,7 +2653,7 @@ void Controller::Impl::ChangeState( EventData::State newState )
           mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
           mEventData->mDecorator->SetHighlightActive( false );
         }
-        else
+        else if ( mEventData->mGrabHandleEnabled )
         {
           mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
         }
@@ -2489,7 +2675,10 @@ void Controller::Impl::ChangeState( EventData::State newState )
           mEventData->mDecorator->StartCursorBlink();
         }
         // Grab handle is not shown until a tap is received whilst EDITING
-        mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+        if ( mEventData->mGrabHandleEnabled )
+        {
+          mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+        }
         mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHighlightActive( false );
@@ -2505,8 +2694,11 @@ void Controller::Impl::ChangeState( EventData::State newState )
         mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
         mEventData->mDecorator->StopCursorBlink();
         mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
-        mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
-        mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+        if ( mEventData->mGrabHandleEnabled )
+        {
+          mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
+          mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+        }
         mEventData->mDecorator->SetHighlightActive( true );
         if( mEventData->mGrabHandlePopupEnabled )
         {
@@ -2524,7 +2716,10 @@ void Controller::Impl::ChangeState( EventData::State newState )
         {
           mEventData->mDecorator->StartCursorBlink();
         }
-        mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+        if ( mEventData->mGrabHandleEnabled )
+        {
+          mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+        }
         mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHighlightActive( false );
@@ -2545,7 +2740,10 @@ void Controller::Impl::ChangeState( EventData::State newState )
           mEventData->mDecorator->StartCursorBlink();
         }
 
-        mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+        if ( mEventData->mGrabHandleEnabled )
+        {
+          mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+        }
         mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHighlightActive( false );
@@ -2598,21 +2796,41 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical,
     cursorInfo.lineHeight = GetDefaultFontLineHeight();
     cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
 
+    bool isRTL = false;
+    if( mModel->mMatchSystemLanguageDirection )
+    {
+      isRTL = mLayoutDirection == LayoutDirection::RIGHT_TO_LEFT;
+    }
+
     switch( mModel->mHorizontalAlignment )
     {
-      case Layout::HORIZONTAL_ALIGN_BEGIN:
+      case Text::HorizontalAlignment::BEGIN :
       {
-        cursorInfo.primaryPosition.x = 0.f;
+        if( isRTL )
+        {
+          cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
+        }
+        else
+        {
+          cursorInfo.primaryPosition.x = 0.f;
+        }
         break;
       }
-      case Layout::HORIZONTAL_ALIGN_CENTER:
+      case Text::HorizontalAlignment::CENTER:
       {
         cursorInfo.primaryPosition.x = floorf( 0.5f * mModel->mVisualModel->mControlSize.width );
         break;
       }
-      case Layout::HORIZONTAL_ALIGN_END:
+      case Text::HorizontalAlignment::END:
       {
-        cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
+        if( isRTL )
+        {
+          cursorInfo.primaryPosition.x = 0.f;
+        }
+        else
+        {
+          cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
+        }
         break;
       }
     }
@@ -2621,13 +2839,25 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical,
     return;
   }
 
-  Text::GetCursorPosition( mModel->mVisualModel,
-                           mModel->mLogicalModel,
-                           mMetrics,
-                           logical,
+  const bool isMultiLine = ( Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout() );
+  GetCursorPositionParameters parameters;
+  parameters.visualModel = mModel->mVisualModel;
+  parameters.logicalModel = mModel->mLogicalModel;
+  parameters.metrics = mMetrics;
+  parameters.logical = logical;
+  parameters.isMultiline = isMultiLine;
+
+  Text::GetCursorPosition( parameters,
                            cursorInfo );
 
-  if( Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout() )
+  // Adds Outline offset.
+  const float outlineWidth = static_cast<float>( mModel->GetOutlineWidth() );
+  cursorInfo.primaryPosition.x += outlineWidth;
+  cursorInfo.primaryPosition.y += outlineWidth;
+  cursorInfo.secondaryPosition.x += outlineWidth;
+  cursorInfo.secondaryPosition.y += outlineWidth;
+
+  if( isMultiLine )
   {
     // If the text is editable and multi-line, the cursor position after a white space shouldn't exceed the boundaries of the text control.
 
@@ -2845,13 +3075,16 @@ void Controller::Impl::ScrollToMakePositionVisible( const Vector2& position, flo
     mModel->mScrollPosition.x = mModel->mVisualModel->mControlSize.width - positionEndX;
   }
 
-  if( decoratorPositionBeginY < 0.f )
-  {
-    mModel->mScrollPosition.y = -position.y;
-  }
-  else if( decoratorPositionEndY > mModel->mVisualModel->mControlSize.height )
+  if( Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout() )
   {
-    mModel->mScrollPosition.y = mModel->mVisualModel->mControlSize.height - positionEndY;
+    if( decoratorPositionBeginY < 0.f )
+    {
+      mModel->mScrollPosition.y = -position.y;
+    }
+    else if( decoratorPositionEndY > mModel->mVisualModel->mControlSize.height )
+    {
+      mModel->mScrollPosition.y = mModel->mVisualModel->mControlSize.height - positionEndY;
+    }
   }
 }
 
@@ -2890,6 +3123,169 @@ void Controller::Impl::RequestRelayout()
   }
 }
 
+Actor Controller::Impl::CreateBackgroundActor()
+{
+  // NOTE: Currently we only support background color for one line left-to-right text,
+  //       so the following calculation is based on one line left-to-right text only!
+
+  Actor actor;
+
+  Length numberOfGlyphs = mView.GetNumberOfGlyphs();
+  if( numberOfGlyphs > 0u )
+  {
+    Vector<GlyphInfo> glyphs;
+    glyphs.Resize( numberOfGlyphs );
+
+    Vector<Vector2> positions;
+    positions.Resize( numberOfGlyphs );
+
+    // Get the line where the glyphs are laid-out.
+    const LineRun* lineRun = mModel->mVisualModel->mLines.Begin();
+    float alignmentOffset = lineRun->alignmentOffset;
+    numberOfGlyphs = mView.GetGlyphs( glyphs.Begin(),
+                                      positions.Begin(),
+                                      alignmentOffset,
+                                      0u,
+                                      numberOfGlyphs );
+
+    glyphs.Resize( numberOfGlyphs );
+    positions.Resize( numberOfGlyphs );
+
+    const GlyphInfo* const glyphsBuffer = glyphs.Begin();
+    const Vector2* const positionsBuffer = positions.Begin();
+
+    BackgroundMesh mesh;
+    mesh.mVertices.Reserve( 4u * glyphs.Size() );
+    mesh.mIndices.Reserve( 6u * glyphs.Size() );
+
+    const Vector2 textSize = mView.GetLayoutSize();
+
+    const float offsetX = textSize.width * 0.5f;
+    const float offsetY = textSize.height * 0.5f;
+
+    const Vector4* const backgroundColorsBuffer = mView.GetBackgroundColors();
+    const ColorIndex* const backgroundColorIndicesBuffer = mView.GetBackgroundColorIndices();
+
+    Vector4 quad;
+    uint32_t numberOfQuads = 0u;
+
+    for( uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i )
+    {
+      const GlyphInfo& glyph = *( glyphsBuffer + i );
+
+      // Get the background color of the character.
+      // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT)
+      const ColorIndex backgroundColorIndex = ( nullptr == backgroundColorsBuffer ) ? 0u : *( backgroundColorIndicesBuffer + i );
+      const Vector4& backgroundColor = ( 0u == backgroundColorIndex ) ? Color::TRANSPARENT : *( backgroundColorsBuffer + backgroundColorIndex - 1u );
+
+      // Only create quads for glyphs with a background color
+      if ( backgroundColor != Color::TRANSPARENT )
+      {
+        const Vector2 position = *( positionsBuffer + i );
+
+        if ( i == 0u && glyphSize == 1u ) // Only one glyph in the whole text
+        {
+          quad.x = position.x;
+          quad.y = 0.0f;
+          quad.z = quad.x + std::max( glyph.advance, glyph.xBearing + glyph.width );
+          quad.w = textSize.height;
+        }
+        else if ( i == 0u ) // The first glyph in the whole text
+        {
+          quad.x = position.x;
+          quad.y = 0.0f;
+          quad.z = quad.x - glyph.xBearing + glyph.advance;
+          quad.w = textSize.height;
+        }
+        else if ( i == glyphSize - 1u ) // The last glyph in the whole text
+        {
+          quad.x = position.x - glyph.xBearing;
+          quad.y = 0.0f;
+          quad.z = quad.x + std::max( glyph.advance, glyph.xBearing + glyph.width );
+          quad.w = textSize.height;
+        }
+        else // The glyph in the middle of the text
+        {
+          quad.x = position.x - glyph.xBearing;
+          quad.y = 0.0f;
+          quad.z = quad.x + glyph.advance;
+          quad.w = textSize.height;
+        }
+
+        BackgroundVertex vertex;
+
+        // Top left
+        vertex.mPosition.x = quad.x - offsetX;
+        vertex.mPosition.y = quad.y - offsetY;
+        vertex.mColor = backgroundColor;
+        mesh.mVertices.PushBack( vertex );
+
+        // Top right
+        vertex.mPosition.x = quad.z - offsetX;
+        vertex.mPosition.y = quad.y - offsetY;
+        vertex.mColor = backgroundColor;
+        mesh.mVertices.PushBack( vertex );
+
+        // Bottom left
+        vertex.mPosition.x = quad.x - offsetX;
+        vertex.mPosition.y = quad.w - offsetY;
+        vertex.mColor = backgroundColor;
+        mesh.mVertices.PushBack( vertex );
+
+        // Bottom right
+        vertex.mPosition.x = quad.z - offsetX;
+        vertex.mPosition.y = quad.w - offsetY;
+        vertex.mColor = backgroundColor;
+        mesh.mVertices.PushBack( vertex );
+
+        // Six indices in counter clockwise winding
+        mesh.mIndices.PushBack( 1u + 4 * numberOfQuads );
+        mesh.mIndices.PushBack( 0u + 4 * numberOfQuads );
+        mesh.mIndices.PushBack( 2u + 4 * numberOfQuads );
+        mesh.mIndices.PushBack( 2u + 4 * numberOfQuads );
+        mesh.mIndices.PushBack( 3u + 4 * numberOfQuads );
+        mesh.mIndices.PushBack( 1u + 4 * numberOfQuads );
+
+        numberOfQuads++;
+      }
+    }
+
+    // Only create the background actor if there are glyphs with background color
+    if ( mesh.mVertices.Count() > 0u )
+    {
+      Property::Map quadVertexFormat;
+      quadVertexFormat[ "aPosition" ] = Property::VECTOR2;
+      quadVertexFormat[ "aColor" ] = Property::VECTOR4;
+
+      PropertyBuffer quadVertices = PropertyBuffer::New( quadVertexFormat );
+      quadVertices.SetData( &mesh.mVertices[ 0 ], mesh.mVertices.Size() );
+
+      Geometry quadGeometry = Geometry::New();
+      quadGeometry.AddVertexBuffer( quadVertices );
+      quadGeometry.SetIndexBuffer( &mesh.mIndices[ 0 ], mesh.mIndices.Size() );
+
+      if( !mShaderBackground )
+      {
+        mShaderBackground = Shader::New( VERTEX_SHADER_BACKGROUND, FRAGMENT_SHADER_BACKGROUND );
+      }
+
+      Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, mShaderBackground );
+      renderer.SetProperty( Dali::Renderer::Property::BLEND_MODE, BlendMode::ON );
+      renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT );
+
+      actor = Actor::New();
+      actor.SetName( "TextBackgroundColorActor" );
+      actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+      actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+      actor.SetSize( textSize );
+      actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
+      actor.AddRenderer( renderer );
+    }
+  }
+
+  return actor;
+}
+
 } // namespace Text
 
 } // namespace Toolkit