Merge "Improved block detection for new atlases in text atlas renderer" into new_text
authorPaul Wisbey <p.wisbey@samsung.com>
Tue, 17 Mar 2015 19:00:22 +0000 (12:00 -0700)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Tue, 17 Mar 2015 19:00:22 +0000 (12:00 -0700)
16 files changed:
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.h
dali-toolkit/internal/file.list
dali-toolkit/internal/text/clipping/text-clipper.cpp
dali-toolkit/internal/text/logical-model-impl.cpp [moved from dali-toolkit/internal/text/logical-model.cpp with 52% similarity]
dali-toolkit/internal/text/logical-model-impl.h [moved from dali-toolkit/internal/text/logical-model.h with 89% similarity]
dali-toolkit/internal/text/multi-language-support-impl.cpp
dali-toolkit/internal/text/shaper.cpp
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-definitions.h
dali-toolkit/internal/text/text-view.h
dali-toolkit/internal/text/visual-model-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/text/visual-model-impl.h [moved from dali-toolkit/internal/text/visual-model.h with 86% similarity]
dali-toolkit/internal/text/visual-model.cpp [deleted file]
dali-toolkit/styles/tizen-dark-theme.json

index 5f8d498..09a5ecc 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali/public-api/object/type-registry.h>
 #include <dali/public-api/object/type-registry-helper.h>
 #include <dali/integration-api/debug.h>
+#include <dali/public-api/adaptor-framework/virtual-keyboard.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/text/rendering-backend.h>
@@ -210,7 +211,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mController )
         {
-          //impl.mController->SetEnableCursorBlink( value.Get< bool >() ); TODO
+          impl.mController->SetEnableCursorBlink( value.Get< bool >() );
         }
         break;
       }
@@ -324,7 +325,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
       }
       case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK:
       {
-        //value = impl.mController->GetEnableCursorBlink(); TODO
+        value = impl.mController->GetEnableCursorBlink();
         break;
       }
       case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL:
@@ -450,8 +451,53 @@ void TextField::OnRelayout( const Vector2& size, ActorSizeContainer& container )
   }
 }
 
+void TextField::OnKeyInputFocusGained()
+{
+  VirtualKeyboard::StatusChangedSignal().Connect( this, &TextField::KeyboardStatusChanged );
+
+  ImfManager imfManager = ImfManager::Get();
+
+  if ( imfManager )
+  {
+    imfManager.EventReceivedSignal().Connect( this, &TextField::OnImfEvent );
+
+    // Notify that the text editing start.
+    imfManager.Activate();
+
+    // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated.
+    imfManager.SetRestoreAfterFocusLost( true );
+  }
+
+  mController->KeyboardFocusGainEvent();
+}
+
+void TextField::OnKeyInputFocusLost()
+{
+  VirtualKeyboard::StatusChangedSignal().Disconnect( this, &TextField::KeyboardStatusChanged );
+
+  ImfManager imfManager = ImfManager::Get();
+  if ( imfManager )
+  {
+    // The text editing is finished. Therefore the imf manager don't have restore activation.
+    imfManager.SetRestoreAfterFocusLost( false );
+
+    // Notify that the text editing finish.
+    imfManager.Deactivate();
+
+    imfManager.EventReceivedSignal().Disconnect( this, &TextField::OnImfEvent );
+  }
+
+  mController->KeyboardFocusLostEvent();
+}
+
 void TextField::OnTap( const TapGesture& gesture )
 {
+  // Show the keyboard if it was hidden.
+  if (!VirtualKeyboard::IsVisible())
+  {
+    VirtualKeyboard::Show();
+  }
+
   SetKeyInputFocus();
 
   mController->TapEvent( gesture.numberOfTaps, gesture.localPoint.x, gesture.localPoint.y );
@@ -467,6 +513,39 @@ bool TextField::OnKeyEvent( const KeyEvent& event )
   return mController->KeyEvent( event );
 }
 
+ImfManager::ImfCallbackData TextField::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData&  imfEvent )
+{
+  switch ( imfEvent.eventName )
+  {
+    case ImfManager::PREEDIT:
+    {
+      // TODO
+      break;
+    }
+    case ImfManager::COMMIT:
+    {
+      // TODO
+      break;
+    }
+    case ImfManager::DELETESURROUNDING:
+    {
+      // TODO
+      break;
+    }
+    case ImfManager::GETSURROUNDING:
+    {
+      // TODO
+      break;
+    }
+    case ImfManager::VOID:
+    {
+      // do nothing
+    }
+  } // end switch
+
+  return ImfManager::ImfCallbackData();
+}
+
 void TextField::RequestTextRelayout()
 {
   RelayoutRequest();
@@ -500,6 +579,15 @@ void TextField::EnableClipping( bool clipping, const Vector2& size )
   }
 }
 
+void TextField::KeyboardStatusChanged(bool keyboardShown)
+{
+  // Just hide the grab handle when keyboard is hidden.
+  if (!keyboardShown )
+  {
+    mController->KeyboardFocusLostEvent();
+  }
+}
+
 TextField::TextField()
 : Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
index 5d103c9..fa55c77 100644 (file)
@@ -18,6 +18,9 @@
  *
  */
 
+// EXTERNAL INCLUDES
+#include <dali/public-api/adaptor-framework/imf-manager.h>
+
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-field.h>
@@ -96,6 +99,16 @@ private: // From Control
   virtual void OnRelayout( const Vector2& size, ActorSizeContainer& container );
 
   /**
+   * @copydoc Control::OnKeyInputFocusGained()
+   */
+  virtual void OnKeyInputFocusGained();
+
+  /**
+   * @copydoc Control::OnKeyInputFocusLost()
+   */
+  virtual void OnKeyInputFocusLost();
+
+  /**
    * Received for single & double taps
    */
   virtual void OnTap( const TapGesture& tap );
@@ -106,6 +119,15 @@ private: // From Control
   virtual bool OnKeyEvent(const KeyEvent& event);
 
   /**
+   * @brief Event received from IMF manager
+   *
+   * @param[in] imfManager The IMF manager.
+   * @param[in] imfEvent The event received.
+   * @return A data struture indicating if update is needed, cursor position and current text.
+   */
+  ImfManager::ImfCallbackData OnImfEvent( ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent );
+
+  /**
    * @copydoc Text::ControlInterface::RequestTextRelayout()
    */
   virtual void RequestTextRelayout();
@@ -121,6 +143,13 @@ private: // Implementation
   void EnableClipping( bool clipping, const Vector2& size );
 
   /**
+   * @brief Callback when keyboard is shown/hidden.
+   *
+   * @param[in] keyboardShown True if keyboard is shown.
+   */
+  void KeyboardStatusChanged( bool keyboardShown );
+
+  /**
    * Construct a new TextField.
    */
   TextField();
index 3293406..4a27e26 100644 (file)
@@ -78,7 +78,7 @@ toolkit_src_files = \
    $(toolkit_src_dir)/text/bidirectional-support.cpp \
    $(toolkit_src_dir)/text/character-set-conversion.cpp \
    $(toolkit_src_dir)/text/clipping/text-clipper.cpp \
-   $(toolkit_src_dir)/text/logical-model.cpp \
+   $(toolkit_src_dir)/text/logical-model-impl.cpp \
    $(toolkit_src_dir)/text/multi-language-support.cpp \
    $(toolkit_src_dir)/text/segmentation.cpp \
    $(toolkit_src_dir)/text/shaper.cpp \
@@ -87,7 +87,7 @@ toolkit_src_files = \
    $(toolkit_src_dir)/text/text-io.cpp \
    $(toolkit_src_dir)/text/text-view.cpp \
    $(toolkit_src_dir)/text/text-view-interface.cpp \
-   $(toolkit_src_dir)/text/visual-model.cpp \
+   $(toolkit_src_dir)/text/visual-model-impl.cpp \
    $(toolkit_src_dir)/text/decorator/text-decorator.cpp \
    $(toolkit_src_dir)/text/layouts/layout-engine.cpp \
    $(toolkit_src_dir)/text/multi-language-support-impl.cpp \
index 66bf2ec..416fdba 100644 (file)
@@ -78,6 +78,7 @@ void Clipper::Refresh( const Vector2& size )
     FrameBufferImage frameBufferImage = FrameBufferImage::New( offscreenSize.width,
                                                                offscreenSize.height,
                                                                Pixel::RGBA8888 );
+    mImageActor.SetSize( offscreenSize );
     mImageActor.SetImage( frameBufferImage );
     mRenderTask.SetTargetFrameBuffer( frameBufferImage );
 
  */
 
 // CLASS HEADER
-#include <dali-toolkit/internal/text/logical-model.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
 
 // EXTERNAL INCLUDES
 #include <memory.h>
 
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
-#include <dali-toolkit/internal/text/bidirectional-paragraph-info-run.h>
-#include <dali-toolkit/internal/text/font-run.h>
-#include <dali-toolkit/internal/text/script-run.h>
-
 namespace Dali
 {
 
@@ -35,36 +29,6 @@ namespace Toolkit
 
 namespace Text
 {
-/**
- * @brief caches some temporary values of the GetNumberOfScriptRuns( characterIndex, numberOfCharacters )
- * operation and the GetNumberOfFontRuns( characterIndex, numberOfCharacters ) as they are going to be
- * used in the GetScriptRuns() and the GetFontRuns() calls.
- */
-struct GetRunCache
-{
-  CharacterIndex characterIndex;     ///< The character index.
-  Length         numberOfCharacters; ///< The number of characters.
-  Length         firstRun;           ///< Index to the first run.
-  Length         numberOfRuns;       ///< The number of runs.
-};
-
-struct LogicalModel::Impl
-{
-  Vector<Character>                     mText;
-  Vector<ScriptRun>                     mScriptRuns;
-  Vector<FontRun>                       mFontRuns;
-  Vector<LineBreakInfo>                 mLineBreakInfo;
-  Vector<WordBreakInfo>                 mWordBreakInfo;
-  Vector<BidirectionalParagraphInfoRun> mBidirectionalParagraphInfo;
-
-  Vector<BidirectionalLineInfoRun>      mBidirectionalLineInfo;
-  Vector<CharacterIndex>                mLogicalToVisualMap; ///< Bidirectional logical to visual conversion table.
-  Vector<CharacterIndex>                mVisualToLogicalMap; ///< Bidirectional visual to logical conversion table.
-
-  GetRunCache                           mGetScriptCache;             ///< Caches the GetNumberOfScriptRuns( characterIndex, numberOfCharacters ) operation.
-  GetRunCache                           mGetFontCache;               ///< Caches the GetNumberOfFontRuns( characterIndex, numberOfCharacters ) operation.
-  GetRunCache                           mGetBidirectionalCache;      ///< Caches the GetNumberOfBidirectionalInfoRuns( characterIndex, numberOfCharacters ) operation.
-};
 
 LogicalModelPtr LogicalModel::New()
 {
@@ -74,35 +38,32 @@ LogicalModelPtr LogicalModel::New()
 void LogicalModel::SetText( const Character* const text,
                             Length numberOfCharacters )
 {
-  Vector<Character>& modelText = mImpl->mText;
-
   if( 0u == numberOfCharacters )
   {
-    modelText.Clear();
+    mText.Clear();
   }
   else
   {
-    modelText.Resize( numberOfCharacters );
-    memcpy( modelText.Begin(), text, numberOfCharacters * sizeof( Character ) );
+    mText.Resize( numberOfCharacters );
+    memcpy( mText.Begin(), text, numberOfCharacters * sizeof( Character ) );
   }
 }
 
 Length LogicalModel::GetNumberOfCharacters() const
 {
-  return mImpl->mText.Count();
+  return mText.Count();
 }
 
 void LogicalModel::GetText( Character* text,
                             CharacterIndex characterIndex,
                             Length numberOfCharacters ) const
 {
-  Vector<Character>& modelText = mImpl->mText;
-  memcpy( text, modelText.Begin() + characterIndex, numberOfCharacters * sizeof( Character ) );
+  memcpy( text, mText.Begin() + characterIndex, numberOfCharacters * sizeof( Character ) );
 }
 
 Character LogicalModel::GetCharacter( CharacterIndex characterIndex ) const
 {
-  return mImpl->mText[characterIndex];
+  return mText[characterIndex];
 }
 
 void LogicalModel::ReplaceText( CharacterIndex characterIndex,
@@ -115,52 +76,32 @@ void LogicalModel::ReplaceText( CharacterIndex characterIndex,
 void LogicalModel::SetScripts( const ScriptRun* const scripts,
                                Length numberOfRuns )
 {
-  Vector<ScriptRun>& scriptRuns = mImpl->mScriptRuns;
-
   if( 0u == numberOfRuns )
   {
-    scriptRuns.Clear();
+    mScriptRuns.Clear();
   }
   else
   {
-    scriptRuns.Resize( numberOfRuns );
-    memcpy( scriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) );
+    mScriptRuns.Resize( numberOfRuns );
+    memcpy( mScriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) );
   }
-
-  mImpl->mGetScriptCache.characterIndex = 0u;
-  mImpl->mGetScriptCache.numberOfCharacters = 0u;
-  mImpl->mGetScriptCache.firstRun = 0u;
-  mImpl->mGetScriptCache.numberOfRuns = 0u;
 }
 
-Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex,
-                                            Length numberOfCharacters ) const
+void LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex,
+                                          Length numberOfCharacters,
+                                          ScriptRunIndex& firstScriptRun,
+                                          Length& numberOfScriptRuns ) const
 {
-  GetRunCache& scriptCache = mImpl->mGetScriptCache;
-
-  // Set the character index and the number of characters into the cache.
-  scriptCache.characterIndex = characterIndex;
-  scriptCache.numberOfCharacters = numberOfCharacters;
-
-  if( ( 0u == characterIndex ) &&
-      ( mImpl->mText.Count() == numberOfCharacters ) )
-  {
-    scriptCache.firstRun = 0u;
-    scriptCache.numberOfRuns = mImpl->mScriptRuns.Count();
-    return scriptCache.numberOfRuns;
-  }
-
   // Initialize the number of scripts and the index to the first script.
-  scriptCache.firstRun = 0u;
-  scriptCache.numberOfRuns = 0;
+  firstScriptRun = 0u;
+  numberOfScriptRuns = 0;
   bool firstScriptFound = false;
 
-  const Vector<ScriptRun>& modelScripts = mImpl->mScriptRuns;
   const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters;
 
   // Traverse the scripts and count those scripts within the range of characters.
-  for( Vector<ScriptRun>::ConstIterator it = modelScripts.Begin(),
-         endIt = modelScripts.End();
+  for( Vector<ScriptRun>::ConstIterator it = mScriptRuns.Begin(),
+         endIt = mScriptRuns.End();
        it != endIt;
        ++it )
   {
@@ -170,7 +111,7 @@ Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex,
         ( lastCharacterIndex > script.characterRun.characterIndex ) )
     {
       firstScriptFound = true;
-      ++scriptCache.numberOfRuns;
+      ++numberOfScriptRuns;
     }
     else if( lastCharacterIndex <= script.characterRun.characterIndex )
     {
@@ -180,37 +121,33 @@ Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex,
 
     if( !firstScriptFound )
     {
-      ++scriptCache.firstRun;
+      ++firstScriptRun;
     }
   }
-
-  return scriptCache.numberOfRuns;
 }
 
 void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns,
                                   CharacterIndex characterIndex,
                                   Length numberOfCharacters ) const
 {
-  const Vector<ScriptRun>& modelScripts = mImpl->mScriptRuns;
-  GetRunCache& scriptCache = mImpl->mGetScriptCache;
+  ScriptRunIndex firstScriptRun = 0u;
+  Length numberOfScriptRuns = 0u;
 
-  if( ( characterIndex != scriptCache.characterIndex ) ||
-      ( numberOfCharacters != scriptCache.numberOfCharacters ) )
-  {
-    GetNumberOfScriptRuns( characterIndex,
-                           numberOfCharacters );
-  }
+  GetNumberOfScriptRuns( characterIndex,
+                         numberOfCharacters,
+                         firstScriptRun,
+                         numberOfScriptRuns );
 
-  memcpy( scriptRuns, modelScripts.Begin() + scriptCache.firstRun, scriptCache.numberOfRuns * sizeof( ScriptRun ) );
+  memcpy( scriptRuns, mScriptRuns.Begin() + firstScriptRun, numberOfScriptRuns * sizeof( ScriptRun ) );
 }
 
 Script LogicalModel::GetScript( CharacterIndex characterIndex ) const
 {
   // If this operation is too slow, consider a binary search.
 
-  for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
+  for( Length index = 0u, length = mScriptRuns.Count(); index < length; ++index )
   {
-    const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
+    const ScriptRun* const scriptRun = mScriptRuns.Begin() + index;
 
     if( ( scriptRun->characterRun.characterIndex <= characterIndex ) &&
         ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
@@ -232,52 +169,32 @@ void LogicalModel::ReplaceScripts( CharacterIndex characterIndex,
 void LogicalModel::SetFonts( const FontRun* const fonts,
                              Length numberOfRuns )
 {
-  Vector<FontRun>& fontRuns = mImpl->mFontRuns;
-
   if( 0u == numberOfRuns )
   {
-    fontRuns.Clear();
+    mFontRuns.Clear();
   }
   else
   {
-    fontRuns.Resize( numberOfRuns );
-    memcpy( fontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) );
+    mFontRuns.Resize( numberOfRuns );
+    memcpy( mFontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) );
   }
-
-  mImpl->mGetFontCache.characterIndex = 0u;
-  mImpl->mGetFontCache.numberOfCharacters = 0u;
-  mImpl->mGetFontCache.firstRun = 0u;
-  mImpl->mGetFontCache.numberOfRuns = 0u;
 }
 
-Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex,
-                                          Length numberOfCharacters ) const
+void LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex,
+                                        Length numberOfCharacters,
+                                        FontRunIndex& firstFontRun,
+                                        Length& numberOfFontRuns ) const
 {
-  GetRunCache& fontCache = mImpl->mGetFontCache;
-
-  // Set the character index and the number of characters into the cache.
-  fontCache.characterIndex = characterIndex;
-  fontCache.numberOfCharacters = numberOfCharacters;
-
-  if( ( 0u == characterIndex ) &&
-      ( mImpl->mText.Count() == numberOfCharacters ) )
-  {
-    fontCache.firstRun = 0u;
-    fontCache.numberOfRuns = mImpl->mFontRuns.Count();
-    return fontCache.numberOfRuns;
-  }
-
   // Initialize the number of fonts and the index to the first font.
-  fontCache.firstRun = 0u;
-  fontCache.numberOfRuns = 0;
+  firstFontRun = 0u;
+  numberOfFontRuns = 0;
   bool firstFontFound = false;
 
-  const Vector<FontRun>& modelFonts = mImpl->mFontRuns;
   const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters;
 
   // Traverse the fonts and count those fonts within the range of characters.
-  for( Vector<FontRun>::ConstIterator it = modelFonts.Begin(),
-         endIt = modelFonts.End();
+  for( Vector<FontRun>::ConstIterator it = mFontRuns.Begin(),
+         endIt = mFontRuns.End();
        it != endIt;
        ++it )
   {
@@ -287,7 +204,7 @@ Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex,
         ( characterIndex + numberOfCharacters > font.characterRun.characterIndex ) )
     {
       firstFontFound = true;
-      ++fontCache.numberOfRuns;
+      ++numberOfFontRuns;
     }
     else if( lastCharacterIndex <= font.characterRun.characterIndex )
     {
@@ -297,35 +214,31 @@ Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex,
 
     if( !firstFontFound )
     {
-      ++fontCache.firstRun;
+      ++firstFontRun;
     }
   }
-
-  return fontCache.numberOfRuns;
 }
 
 void LogicalModel::GetFontRuns( FontRun* fontRuns,
                                 CharacterIndex characterIndex,
                                 Length numberOfCharacters ) const
 {
-  const Vector<FontRun>& modelFonts = mImpl->mFontRuns;
-  GetRunCache& fontCache = mImpl->mGetFontCache;
+  FontRunIndex firstFontRun = 0u;
+  Length numberOfFontRuns = 0u;
 
-  if( ( characterIndex != fontCache.characterIndex ) ||
-      ( numberOfCharacters != fontCache.numberOfCharacters ) )
-  {
-    GetNumberOfFontRuns( characterIndex,
-                         numberOfCharacters );
-  }
+  GetNumberOfFontRuns( characterIndex,
+                       numberOfCharacters,
+                       firstFontRun,
+                       numberOfFontRuns );
 
-  memcpy( fontRuns, modelFonts.Begin() + fontCache.firstRun, fontCache.numberOfRuns * sizeof( FontRun ) );
+  memcpy( fontRuns, mFontRuns.Begin() + firstFontRun, numberOfFontRuns * sizeof( FontRun ) );
 }
 
 FontId LogicalModel::GetFont( CharacterIndex characterIndex ) const
 {
-  for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
+  for( Length index = 0u, length = mFontRuns.Count(); index < length; ++index )
   {
-    const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
+    const FontRun* const fontRun = mFontRuns.Begin() + index;
 
     if( ( fontRun->characterRun.characterIndex <= characterIndex ) &&
         ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) )
@@ -347,16 +260,14 @@ void LogicalModel::ReplaceFonts( CharacterIndex characterIndex,
 void LogicalModel::SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo,
                                      Length length )
 {
-  Vector<LineBreakInfo>& modelLineBreakInfo = mImpl->mLineBreakInfo;
-
   if( 0u == length )
   {
-    modelLineBreakInfo.Clear();
+    mLineBreakInfo.Clear();
   }
   else
   {
-    modelLineBreakInfo.Resize( length );
-    memcpy( modelLineBreakInfo.Begin(), lineBreakInfo, length * sizeof( LineBreakInfo ) );
+    mLineBreakInfo.Resize( length );
+    memcpy( mLineBreakInfo.Begin(), lineBreakInfo, length * sizeof( LineBreakInfo ) );
   }
 }
 
@@ -364,12 +275,12 @@ void LogicalModel::GetLineBreakInfo( LineBreakInfo* lineBreakInfo,
                                      CharacterIndex characterIndex,
                                      Length numberOfItems ) const
 {
-  memcpy( lineBreakInfo, mImpl->mLineBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( LineBreakInfo ) );
+  memcpy( lineBreakInfo, mLineBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( LineBreakInfo ) );
 }
 
 LineBreakInfo LogicalModel::GetLineBreakInfo( CharacterIndex characterIndex ) const
 {
-  return *( mImpl->mLineBreakInfo.Begin() + characterIndex );
+  return *( mLineBreakInfo.Begin() + characterIndex );
 }
 
 void LogicalModel::ReplaceLineBreakInfo( CharacterIndex characterIndex,
@@ -382,16 +293,14 @@ void LogicalModel::ReplaceLineBreakInfo( CharacterIndex characterIndex,
 void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo,
                                      Length length )
 {
-  Vector<WordBreakInfo>& modelWordBreakInfo = mImpl->mWordBreakInfo;
-
   if( 0u == length )
   {
-    modelWordBreakInfo.Clear();
+    mWordBreakInfo.Clear();
   }
   else
   {
-    modelWordBreakInfo.Resize( length );
-    memcpy( modelWordBreakInfo.Begin(), wordBreakInfo, length * sizeof( WordBreakInfo ) );
+    mWordBreakInfo.Resize( length );
+    memcpy( mWordBreakInfo.Begin(), wordBreakInfo, length * sizeof( WordBreakInfo ) );
   }
 }
 
@@ -399,12 +308,12 @@ void LogicalModel::GetWordBreakInfo( WordBreakInfo* wordBreakInfo,
                                      CharacterIndex characterIndex,
                                      Length numberOfItems ) const
 {
-  memcpy( wordBreakInfo, mImpl->mWordBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( WordBreakInfo ) );
+  memcpy( wordBreakInfo, mWordBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( WordBreakInfo ) );
 }
 
 WordBreakInfo LogicalModel::GetWordBreakInfo( CharacterIndex characterIndex ) const
 {
-  return *( mImpl->mWordBreakInfo.Begin() + characterIndex );
+  return *( mWordBreakInfo.Begin() + characterIndex );
 }
 
 void LogicalModel::ReplaceWordBreakInfo( CharacterIndex characterIndex,
@@ -417,51 +326,30 @@ void LogicalModel::ReplaceWordBreakInfo( CharacterIndex characterIndex,
 void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo,
                                          Length numberOfRuns )
 {
-  Vector<BidirectionalParagraphInfoRun>& modelBidirectionalParagraphInfo = mImpl->mBidirectionalParagraphInfo;
-
   if( 0u == numberOfRuns )
   {
-    modelBidirectionalParagraphInfo.Clear();
+    mBidirectionalParagraphInfo.Clear();
   }
   else
   {
-    modelBidirectionalParagraphInfo.Resize( numberOfRuns );
-    memcpy( modelBidirectionalParagraphInfo.Begin(), bidirectionalInfo, numberOfRuns * sizeof( BidirectionalParagraphInfoRun ) );
+    mBidirectionalParagraphInfo.Resize( numberOfRuns );
+    memcpy( mBidirectionalParagraphInfo.Begin(), bidirectionalInfo, numberOfRuns * sizeof( BidirectionalParagraphInfoRun ) );
   }
-
-  mImpl->mGetBidirectionalCache.characterIndex = 0u;
-  mImpl->mGetBidirectionalCache.numberOfCharacters = 0u;
-  mImpl->mGetBidirectionalCache.firstRun = 0u;
-  mImpl->mGetBidirectionalCache.numberOfRuns = 0u;
 }
 
-Length LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex,
-                                                       Length numberOfCharacters ) const
+void LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex,
+                                                     Length numberOfCharacters,
+                                                     BidirectionalRunIndex& firstBidirectionalRun,
+                                                     Length& numberOfFontRuns  ) const
 {
-  GetRunCache& bidiCache = mImpl->mGetBidirectionalCache;
-
-  // Set the character index and the number of characters into the cache.
-  bidiCache.characterIndex = characterIndex;
-  bidiCache.numberOfCharacters = numberOfCharacters;
-
-  if( ( 0u == characterIndex ) &&
-      ( mImpl->mText.Count() == numberOfCharacters ) )
-  {
-    bidiCache.firstRun = 0u;
-    bidiCache.numberOfRuns = mImpl->mBidirectionalParagraphInfo.Count();
-    return bidiCache.numberOfRuns;
-  }
-
   // Initialize the number of bidi paragraphs and the index to the first paragraph.
-  bidiCache.firstRun = 0u;
-  bidiCache.numberOfRuns = 0;
+  firstBidirectionalRun = 0u;
+  numberOfFontRuns = 0;
   bool firstParagraphFound = false;
 
-  const Vector<BidirectionalParagraphInfoRun>& modelBidirectionalParagraphInfo = mImpl->mBidirectionalParagraphInfo;
-
   // Traverse the bidirectional paragraph info and count those bidi paragraphs within the range of characters.
-  for( Vector<BidirectionalParagraphInfoRun>::ConstIterator it = modelBidirectionalParagraphInfo.Begin(),
-         endIt = modelBidirectionalParagraphInfo.End();
+  for( Vector<BidirectionalParagraphInfoRun>::ConstIterator it = mBidirectionalParagraphInfo.Begin(),
+         endIt = mBidirectionalParagraphInfo.End();
        it != endIt;
        ++it )
   {
@@ -471,33 +359,29 @@ Length LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterI
         ( characterIndex + numberOfCharacters > bidi.characterRun.characterIndex ) )
     {
       firstParagraphFound = true;
-      ++bidiCache.numberOfRuns;
+      ++numberOfFontRuns;
     }
 
     if( !firstParagraphFound )
     {
-      ++bidiCache.firstRun;
+      ++firstBidirectionalRun;
     }
   }
-
-  return bidiCache.numberOfRuns;
 }
 
 void LogicalModel::GetBidirectionalInfo( BidirectionalParagraphInfoRun* bidirectionalInfo,
                                          CharacterIndex characterIndex,
                                          Length numberOfCharacters ) const
 {
-  const Vector<BidirectionalParagraphInfoRun>& modelBidirectionalParagraphInfo = mImpl->mBidirectionalParagraphInfo;
-  GetRunCache& bidiCache = mImpl->mGetBidirectionalCache;
+  BidirectionalRunIndex firstBidirectionalRun = 0u;
+  Length numberOfFontRuns = 0u;
 
-  if( ( characterIndex != bidiCache.characterIndex ) ||
-      ( numberOfCharacters != bidiCache.numberOfCharacters ) )
-  {
-    GetNumberOfBidirectionalInfoRuns( characterIndex,
-                                      numberOfCharacters );
-  }
+  GetNumberOfBidirectionalInfoRuns( characterIndex,
+                                    numberOfCharacters,
+                                    firstBidirectionalRun,
+                                    numberOfFontRuns );
 
-  memcpy( bidirectionalInfo, modelBidirectionalParagraphInfo.Begin() + bidiCache.firstRun, bidiCache.numberOfRuns * sizeof( BidirectionalParagraphInfoRun ) );
+  memcpy( bidirectionalInfo, mBidirectionalParagraphInfo.Begin() + firstBidirectionalRun, numberOfFontRuns * sizeof( BidirectionalParagraphInfoRun ) );
 }
 
 void ReplaceBidirectionalInfo( CharacterIndex characterIndex,
@@ -521,22 +405,19 @@ CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex character
 void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
                                           Length numberOfRuns )
 {
-  Vector<CharacterIndex>& modelVisualToLogicalMap = mImpl->mVisualToLogicalMap;
-  Vector<CharacterIndex>& modelLogicalToVisualMap = mImpl->mLogicalToVisualMap;
-
   if( 0u == numberOfRuns )
   {
-    modelVisualToLogicalMap.Clear();
-    modelLogicalToVisualMap.Clear();
+    mVisualToLogicalMap.Clear();
+    mLogicalToVisualMap.Clear();
   }
   else
   {
-    const Length numberOfCharacters = mImpl->mText.Count();
-    modelVisualToLogicalMap.Resize( numberOfCharacters );
-    modelLogicalToVisualMap.Resize( numberOfCharacters );
+    const Length numberOfCharacters = mText.Count();
+    mVisualToLogicalMap.Resize( numberOfCharacters );
+    mLogicalToVisualMap.Resize( numberOfCharacters );
 
-    CharacterIndex* modelVisualToLogicalMapBuffer = modelVisualToLogicalMap.Begin();
-    CharacterIndex* modelLogicalToVisualMapBuffer = modelLogicalToVisualMap.Begin();
+    CharacterIndex* modelVisualToLogicalMapBuffer = mVisualToLogicalMap.Begin();
+    CharacterIndex* modelLogicalToVisualMapBuffer = mLogicalToVisualMap.Begin();
 
     CharacterIndex lastIndex = 0u;
     for( unsigned int bidiIndex = 0u; bidiIndex < numberOfRuns; ++bidiIndex )
@@ -584,51 +465,48 @@ void LogicalModel::ReplaceVisualToLogicalMap( CharacterIndex characterIndex,
 
 CharacterIndex LogicalModel::GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const
 {
-  if( 0u == mImpl->mLogicalToVisualMap.Count() )
+  if( 0u == mLogicalToVisualMap.Count() )
   {
     // If there is no logical to visual info is because the whole text is left to right.
     // Return the identity.
     return logicalCharacterIndex;
   }
 
-  return *( mImpl->mLogicalToVisualMap.Begin() + logicalCharacterIndex );
+  return *( mLogicalToVisualMap.Begin() + logicalCharacterIndex );
 }
 
 CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const
 {
-  if( 0u == mImpl->mVisualToLogicalMap.Count() )
+  if( 0u == mVisualToLogicalMap.Count() )
   {
     // If there is no visual to logical info is because the whole text is left to right.
     // Return the identity.
     return visualCharacterIndex;
   }
 
-  return *( mImpl->mVisualToLogicalMap.Begin() + visualCharacterIndex );
+  return *( mVisualToLogicalMap.Begin() + visualCharacterIndex );
 }
 
 void LogicalModel::GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap,
                                           CharacterIndex characterIndex,
                                           Length numberOfCharacters ) const
 {
-  memcpy( logicalToVisualMap, mImpl->mLogicalToVisualMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) );
+  memcpy( logicalToVisualMap, mLogicalToVisualMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) );
 }
 
 void LogicalModel::GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap,
                                           CharacterIndex characterIndex,
                                           Length numberOfCharacters ) const
 {
-  memcpy( visualToLogicalMap, mImpl->mVisualToLogicalMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) );
+  memcpy( visualToLogicalMap, mVisualToLogicalMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) );
 }
 
 LogicalModel::~LogicalModel()
 {
-  delete mImpl;
 }
 
 LogicalModel::LogicalModel()
-: mImpl( NULL )
 {
-  mImpl = new LogicalModel::Impl();
 }
 
 } // namespace Text
similarity index 89%
rename from dali-toolkit/internal/text/logical-model.h
rename to dali-toolkit/internal/text/logical-model-impl.h
index 43490d1..c73190e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_H__
-#define __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_H__
+#ifndef __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__
+#define __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__
 
 /*
  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 #include <dali/public-api/object/ref-object.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-definitions.h>
+#include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
+#include <dali-toolkit/internal/text/bidirectional-paragraph-info-run.h>
+#include <dali-toolkit/internal/text/font-run.h>
+#include <dali-toolkit/internal/text/script-run.h>
 
 namespace Dali
 {
@@ -134,17 +137,19 @@ public:
                    Length numberOfRuns );
 
   /**
-   * Retrieves the number of script runs for the given range of characters.
+   * Retrieves the number of script runs and the index to the first one for the given range of characters.
    *
    * A run is a group of consecutive characters. A script run contains the script for a run.
    *
    * @param[in] characterIndex Index to the first character.
    * @param[in] numberOfCharacters The number of characters.
-   *
-   * @return The number of script runs.
+   * @param[out] firstScriptRun Index to the script run containing the character index.
+   * @param[out] numberOfScriptRuns The number of script runs.
    */
-  Length GetNumberOfScriptRuns( CharacterIndex characterIndex,
-                                Length numberOfCharacters ) const;
+  void GetNumberOfScriptRuns( CharacterIndex characterIndex,
+                              Length numberOfCharacters,
+                              ScriptRunIndex& firstScriptRun,
+                              Length& numberOfScriptRuns ) const;
 
   /**
    * Retrieves the script runs for the given range of characters.
@@ -201,17 +206,19 @@ public:
                  Length numberOfRuns );
 
   /**
-   * Retrieves the number of font runs for the given range of characters.
+   * Retrieves the number of font runs and the index of the first one for the given range of characters.
    *
    * A run is a group of consecutive characters. A font run contains the font id for a run.
    *
    * @param[in] characterIndex Index to the first character.
    * @param[in] numberOfCharacters The number of characters.
-   *
-   * @return The number of font runs.
+   * @param[out] firstFontRun Index to the font run containing the character index.
+   * @param[out] numberOfFontRuns The number of font runs.
    */
-  Length GetNumberOfFontRuns( CharacterIndex characterIndex,
-                              Length numberOfCharacters ) const;
+  void GetNumberOfFontRuns( CharacterIndex characterIndex,
+                            Length numberOfCharacters,
+                            FontRunIndex& firstFontRun,
+                            Length& numberOfFontRuns ) const;
 
   /**
    * Retrieves the font runs for the given range of characters.
@@ -405,7 +412,7 @@ public:
                              Length numberOfRuns );
 
   /**
-   * Retrieves the number of bidirectional info runs for the given range of characters.
+   * Retrieves the number of bidirectional info runs and the index to the first one for the given range of characters.
    *
    * It may be zero if there is no right to left scripts.
    *
@@ -414,8 +421,10 @@ public:
    *
    * @return The number of bidirectional info runs.
    */
-  Length GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex,
-                                           Length numberOfCharacters ) const;
+  void GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex,
+                                         Length numberOfCharacters,
+                                         BidirectionalRunIndex& firstBidirectionalRun,
+                                         Length& numberOfFontRuns ) const;
 
   /**
    * Retrieves the bidirectional paragraph info runs for the given range of characters.
@@ -572,10 +581,18 @@ private:
   // Undefined
   LogicalModel& operator=( const LogicalModel& handle );
 
-private:
+public:
+
+  Vector<Character>                     mText;
+  Vector<ScriptRun>                     mScriptRuns;
+  Vector<FontRun>                       mFontRuns;
+  Vector<LineBreakInfo>                 mLineBreakInfo;
+  Vector<WordBreakInfo>                 mWordBreakInfo;
+  Vector<BidirectionalParagraphInfoRun> mBidirectionalParagraphInfo;
 
-  struct Impl;
-  Impl* mImpl;
+  Vector<BidirectionalLineInfoRun>      mBidirectionalLineInfo;
+  Vector<CharacterIndex>                mLogicalToVisualMap; ///< Bidirectional logical to visual conversion table.
+  Vector<CharacterIndex>                mVisualToLogicalMap; ///< Bidirectional visual to logical conversion table.
 };
 
 } // namespace Text
@@ -584,4 +601,4 @@ private:
 
 } // namespace Dali
 
-#endif // __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_H__
+#endif // __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__
index f251025..fa50497 100644 (file)
@@ -26,7 +26,7 @@
 #include <dali/public-api/text-abstraction/script.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/logical-model.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
 #include <dali-toolkit/internal/text/font-run.h>
 #include <dali-toolkit/internal/text/script-run.h>
 #include <dali-toolkit/internal/text/text-io.h>
index c0c45fd..55101eb 100644 (file)
@@ -24,9 +24,9 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/font-run.h>
-#include <dali-toolkit/internal/text/logical-model.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
 #include <dali-toolkit/internal/text/script-run.h>
-#include <dali-toolkit/internal/text/visual-model.h>
+#include <dali-toolkit/internal/text/visual-model-impl.h>
 
 namespace Dali
 {
index c302440..b4d4bb5 100644 (file)
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
-#include <dali-toolkit/internal/text/logical-model.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
 #include <dali-toolkit/internal/text/multi-language-support.h>
 #include <dali-toolkit/internal/text/script-run.h>
 #include <dali-toolkit/internal/text/segmentation.h>
 #include <dali-toolkit/internal/text/shaper.h>
+#include <dali-toolkit/internal/text/text-io.h>
 #include <dali-toolkit/internal/text/text-view.h>
-#include <dali-toolkit/internal/text/visual-model.h>
+#include <dali-toolkit/internal/text/visual-model-impl.h>
 
 using std::vector;
 
 namespace
 {
+
 const float MAX_FLOAT = std::numeric_limits<float>::max();
 const std::string EMPTY_STRING;
+
+enum ModifyType
+{
+  REPLACE_TEXT, ///< Replace the entire text
+  INSERT_TEXT,  ///< Insert characters at the current cursor position
+  DELETE_TEXT   ///< Delete a character at the current cursor position
+};
+
+struct ModifyEvent
+{
+  ModifyType type;
+  std::string text;
+};
+
 } // namespace
 
 namespace Dali
@@ -61,7 +77,7 @@ struct Controller::TextInput
   {
     KEYBOARD_FOCUS_GAIN_EVENT,
     KEYBOARD_FOCUS_LOST_EVENT,
-    KEY_EVENT,
+    CURSOR_KEY_EVENT,
     TAP_EVENT,
     GRAB_HANDLE_EVENT
   };
@@ -71,7 +87,6 @@ struct Controller::TextInput
     int mInt;
     unsigned int mUint;
     float mFloat;
-    char* mString;
   };
 
   struct Event
@@ -102,7 +117,11 @@ struct Controller::TextInput
   : mLogicalModel( logicalModel ),
     mVisualModel( visualModel ),
     mDecorator( decorator ),
-    mState( INACTIVE )
+    mState( INACTIVE ),
+    mPrimaryCursorPosition( 0u ),
+    mSecondaryCursorPosition( 0u ),
+    mDecoratorUpdated( false ),
+    mCursorBlinkEnabled( true )
   {
   }
 
@@ -129,9 +148,9 @@ struct Controller::TextInput
             OnKeyboardFocus( false );
             break;
           }
-          case KEY_EVENT:
+          case CURSOR_KEY_EVENT:
           {
-            OnKeyEvent( *iter );
+            OnCursorKeyEvent( *iter );
             break;
           }
           case TAP_EVENT:
@@ -155,40 +174,35 @@ struct Controller::TextInput
 
   void OnKeyboardFocus( bool hasFocus )
   {
+    if( !hasFocus )
+    {
+      ChangeState( INACTIVE );
+    }
+    else
+    {
+      ChangeState( EDITING );
+    }
   }
 
-  void OnKeyEvent( const Event& event )
+  void OnCursorKeyEvent( const Event& event )
   {
     int keyCode = event.p1.mInt;
 
-    // Handle state changes
-    if( Dali::DALI_KEY_ESCAPE == keyCode )
+    if( Dali::DALI_KEY_CURSOR_LEFT == keyCode )
     {
-      ChangeState( INACTIVE ); // Escape key ends edit mode
+      // TODO
     }
-    else if ( event.p2.mString )
+    else if( Dali::DALI_KEY_CURSOR_RIGHT == keyCode )
     {
-      // Some text may be selected, hiding keyboard causes an empty keystring to be sent, we don't want to delete highlight in this case
-      ChangeState( EDITING );
+      // TODO
     }
-
-    // Handle the actual key event
-    if( Dali::DALI_KEY_BACKSPACE == keyCode )
+    else if( Dali::DALI_KEY_CURSOR_UP == keyCode )
     {
-      HandleBackspaceKey();
+      // TODO
     }
-    else if( Dali::DALI_KEY_CURSOR_LEFT  == keyCode ||
-             Dali::DALI_KEY_CURSOR_RIGHT == keyCode ||
-             Dali::DALI_KEY_CURSOR_UP    == keyCode ||
-             Dali::DALI_KEY_CURSOR_DOWN  == keyCode )
+    else if(   Dali::DALI_KEY_CURSOR_DOWN == keyCode )
     {
-      HandleCursorKey( keyCode );
-    }
-    else if ( event.p2.mString )
-    {
-      HandleKeyString( event.p2.mString );
-
-      delete [] event.p2.mString;
+      // TODO
     }
   }
 
@@ -278,7 +292,10 @@ struct Controller::TextInput
       else if( EDITING == mState )
       {
         mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY );
-        mDecorator->StartCursorBlink();
+        if( mCursorBlinkEnabled )
+        {
+          mDecorator->StartCursorBlink();
+        }
         mDecorator->SetGrabHandleActive( true );
         mDecorator->SetSelectionActive( false );
         mDecoratorUpdated = true;
@@ -296,14 +313,10 @@ struct Controller::TextInput
       return;
     }
 
-    Vector<GlyphInfo> glyphs;
-    glyphs.Resize( numberOfGlyphs );
-    mVisualModel->GetGlyphs( glyphs.Begin(), 0, numberOfGlyphs );
+    Vector<GlyphInfo>& glyphs = mVisualModel->mGlyphs;
     const GlyphInfo* const glyphsBuffer = glyphs.Begin();
 
-    Vector<Vector2> positions;
-    positions.Resize( numberOfGlyphs );
-    mVisualModel->GetGlyphPositions( positions.Begin(), 0, numberOfGlyphs );
+    Vector<Vector2>& positions = mVisualModel->mGlyphPositions;
     const Vector2* const positionsBuffer = positions.Begin();
 
     unsigned int closestGlyph = 0;
@@ -346,9 +359,13 @@ struct Controller::TextInput
    */
   vector<Event> mEventQueue; ///< The queue of touch events etc.
 
-  State mState;
+  State mState; ///< Selection mode, edit mode etc.
+
+  CharacterIndex mPrimaryCursorPosition;   ///< Index into logical model for primary cursor
+  CharacterIndex mSecondaryCursorPosition; ///< Index into logical model for secondary cursor
 
-  bool mDecoratorUpdated;
+  bool mDecoratorUpdated   : 1; ///< True if the decorator was updated during event processing
+  bool mCursorBlinkEnabled : 1; ///< True if cursor should blink when active
 };
 
 struct Controller::FontDefaults
@@ -387,7 +404,7 @@ struct Controller::Impl
     mFontClient(),
     mView(),
     mLayoutEngine(),
-    mNewText(),
+    mModifyEvents(),
     mControlSize(),
     mOperationsPending( NO_OPERATION ),
     mRecalculateNaturalSize( true )
@@ -413,7 +430,7 @@ struct Controller::Impl
   TextAbstraction::FontClient mFontClient; ///< Handle to the font client.
   View mView;                              ///< The view interface to the rendering back-end.
   LayoutEngine mLayoutEngine;              ///< The layout engine.
-  std::string mNewText;                    ///< Temporary stores the text set until the next relayout.
+  std::vector<ModifyEvent> mModifyEvents;  ///< Temporary stores the text set until the next relayout.
   Size mControlSize;                       ///< The size of the control.
   OperationsMask mOperationsPending;       ///< Operations pending to be done to layout the text.
   bool mRecalculateNaturalSize:1;          ///< Whether the natural size needs to be recalculated.
@@ -426,26 +443,14 @@ ControllerPtr Controller::New( ControlInterface& controlInterface )
 
 void Controller::SetText( const std::string& text )
 {
-  // Keep until size negotiation
-  mImpl->mNewText = text;
-
-  // All operations need to be done. (convert to utf32, get break info, ..., layout, ...)
-  mImpl->mOperationsPending = ALL_OPERATIONS;
+  // Cancel previously queued inserts etc.
+  mImpl->mModifyEvents.clear();
 
-  // The natural size needs to be re-calculated.
-  mImpl->mRecalculateNaturalSize = true;
-
-  // Reset buffers.
-  mImpl->mLogicalModel->SetText( NULL, 0u );
-  mImpl->mLogicalModel->SetScripts( NULL, 0u );
-  mImpl->mLogicalModel->SetFonts( NULL, 0u );
-  mImpl->mLogicalModel->SetLineBreakInfo( NULL, 0u );
-  mImpl->mLogicalModel->SetWordBreakInfo( NULL, 0u );
-  mImpl->mLogicalModel->SetBidirectionalInfo( NULL, 0u );
-  mImpl->mLogicalModel->SetVisualToLogicalMap( NULL, 0u );
-  mImpl->mVisualModel->SetGlyphs( NULL, NULL, NULL, 0u );
-  mImpl->mVisualModel->SetGlyphPositions( NULL, 0u );
-  mImpl->mVisualModel->SetLines( NULL, 0u );
+  // Keep until size negotiation
+  ModifyEvent event;
+  event.type = REPLACE_TEXT;
+  event.text = text;
+  mImpl->mModifyEvents.push_back( event );
 
   if( mImpl->mTextInput )
   {
@@ -458,9 +463,10 @@ void Controller::SetText( const std::string& text )
 
 void Controller::GetText( std::string& text ) const
 {
-  if( !mImpl->mNewText.empty() )
+  if( !mImpl->mModifyEvents.empty() &&
+       REPLACE_TEXT == mImpl->mModifyEvents[0].type )
   {
-    text = mImpl->mNewText;
+    text = mImpl->mModifyEvents[0].text;
   }
   else
   {
@@ -575,12 +581,136 @@ void Controller::EnableTextInput( DecoratorPtr decorator )
   }
 }
 
+void Controller::SetEnableCursorBlink( bool enable )
+{
+  DALI_ASSERT_DEBUG( NULL != mImpl->mTextInput && "TextInput disabled" );
+
+  if( mImpl->mTextInput )
+  {
+    mImpl->mTextInput->mCursorBlinkEnabled = enable;
+
+    if( !enable &&
+        mImpl->mTextInput->mDecorator )
+    {
+      mImpl->mTextInput->mDecorator->StopCursorBlink();
+    }
+  }
+}
+
+bool Controller::GetEnableCursorBlink() const
+{
+  if( mImpl->mTextInput )
+  {
+    return mImpl->mTextInput->mCursorBlinkEnabled;
+  }
+
+  return false;
+}
+
+Vector3 Controller::GetNaturalSize()
+{
+  Vector3 naturalSize;
+
+  // Make sure the model is up-to-date before layouting
+  ProcessModifyEvents();
+
+  if( mImpl->mRecalculateNaturalSize )
+  {
+    // Operations that can be done only once until the text changes.
+    const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
+                                                                           GET_SCRIPTS       |
+                                                                           VALIDATE_FONTS    |
+                                                                           GET_LINE_BREAKS   |
+                                                                           GET_WORD_BREAKS   |
+                                                                           SHAPE_TEXT        |
+                                                                           GET_GLYPH_METRICS );
+    // Make sure the model is up-to-date before layouting
+    UpdateModel( onlyOnceOperations );
+
+    // Operations that need to be done if the size changes.
+    const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
+                                                                        REORDER );
+
+    DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ),
+                static_cast<OperationsMask>( onlyOnceOperations |
+                                             sizeOperations ),
+                naturalSize.GetVectorXY() );
+
+    // Do not do again the only once operations.
+    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
+
+    // Do the size related operations again.
+    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
+
+    // Stores the natural size to avoid recalculate it again
+    // unless the text/style changes.
+    mImpl->mVisualModel->SetNaturalSize( naturalSize.GetVectorXY() );
+
+    mImpl->mRecalculateNaturalSize = false;
+  }
+  else
+  {
+    naturalSize = mImpl->mVisualModel->GetNaturalSize();
+  }
+
+  return naturalSize;
+}
+
+float Controller::GetHeightForWidth( float width )
+{
+  // Make sure the model is up-to-date before layouting
+  ProcessModifyEvents();
+
+  Size layoutSize;
+  if( width != mImpl->mControlSize.width )
+  {
+    // Operations that can be done only once until the text changes.
+    const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
+                                                                           GET_SCRIPTS       |
+                                                                           VALIDATE_FONTS    |
+                                                                           GET_LINE_BREAKS   |
+                                                                           GET_WORD_BREAKS   |
+                                                                           SHAPE_TEXT        |
+                                                                           GET_GLYPH_METRICS );
+    // Make sure the model is up-to-date before layouting
+    UpdateModel( onlyOnceOperations );
+
+    // Operations that need to be done if the size changes.
+    const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
+                                                                        REORDER );
+
+    DoRelayout( Size( width, MAX_FLOAT ),
+                static_cast<OperationsMask>( onlyOnceOperations |
+                                             sizeOperations ),
+                layoutSize );
+
+    // Do not do again the only once operations.
+    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
+
+    // Do the size related operations again.
+    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
+  }
+  else
+  {
+    layoutSize = mImpl->mVisualModel->GetActualSize();
+  }
+
+  return layoutSize.height;
+}
+
 bool Controller::Relayout( const Vector2& size )
 {
   if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
   {
+    bool glyphsRemoved( false );
+    if( 0u != mImpl->mVisualModel->GetNumberOfGlyphPositions() )
+    {
+      mImpl->mVisualModel->SetGlyphPositions( NULL, 0u );
+      glyphsRemoved = true;
+    }
+
     // Not worth to relayout if width or height is equal to zero.
-    return false;
+    return glyphsRemoved;
   }
 
   if( size != mImpl->mControlSize )
@@ -589,13 +719,15 @@ bool Controller::Relayout( const Vector2& size )
     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
                                                              LAYOUT                    |
                                                              UPDATE_ACTUAL_SIZE        |
-                                                             UPDATE_POSITIONS          |
-                                                             UPDATE_LINES              |
                                                              REORDER );
 
     mImpl->mControlSize = size;
   }
 
+  // Make sure the model is up-to-date before layouting
+  ProcessModifyEvents();
+  UpdateModel( mImpl->mOperationsPending );
+
   Size layoutSize;
   bool updated = DoRelayout( mImpl->mControlSize,
                              mImpl->mOperationsPending,
@@ -613,73 +745,197 @@ bool Controller::Relayout( const Vector2& size )
   return updated;
 }
 
-bool Controller::DoRelayout( const Vector2& size,
-                             OperationsMask operationsRequired,
-                             Size& layoutSize )
+void Controller::ProcessModifyEvents()
 {
-  bool viewUpdated( false );
+  std::vector<ModifyEvent>& events = mImpl->mModifyEvents;
 
-  // Calculate the operations to be done.
-  const OperationsMask operations = static_cast<OperationsMask>( mImpl->mOperationsPending & operationsRequired );
+  for( unsigned int i=0; i<events.size(); ++i )
+  {
+    if( REPLACE_TEXT == events[0].type )
+    {
+      // A (single) replace event should come first, otherwise we wasted time processing NOOP events
+      DALI_ASSERT_DEBUG( 0 == i && "Unexpected REPLACE event" );
 
+      ReplaceTextEvent( events[0].text );
+    }
+    else if( INSERT_TEXT == events[0].type )
+    {
+      InsertTextEvent( events[0].text );
+    }
+    else if( DELETE_TEXT == events[0].type )
+    {
+      DeleteTextEvent();
+    }
+  }
+
+  // Discard temporary text
+  events.clear();
+}
+
+void Controller::ReplaceTextEvent( const std::string& text )
+{
+  // Reset buffers.
+  mImpl->mLogicalModel->mScriptRuns.Clear();
+  mImpl->mLogicalModel->mFontRuns.Clear();
+  mImpl->mLogicalModel->mLineBreakInfo.Clear();
+  mImpl->mLogicalModel->mWordBreakInfo.Clear();
+  mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear();
+  mImpl->mVisualModel->mGlyphs.Clear();
+
+  //  Convert text into UTF-32
+  Vector<Character>& utf32Characters = mImpl->mLogicalModel->mText;
+  utf32Characters.Resize( text.size() );
+
+  // This is a bit horrible but std::string returns a (signed) char*
+  const uint8_t* utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
+
+  // Transform a text array encoded in utf8 into an array encoded in utf32.
+  // It returns the actual number of characters.
+  Length characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() );
+  utf32Characters.Resize( characterCount );
+
+  // Reset the cursor position
+  if( mImpl->mTextInput )
+  {
+    mImpl->mTextInput->mPrimaryCursorPosition = characterCount;
+    // TODO - handle secondary cursor
+  }
+
+  // The natural size needs to be re-calculated.
+  mImpl->mRecalculateNaturalSize = true;
+
+  // Apply modifications to the model
+  mImpl->mOperationsPending = ALL_OPERATIONS;
+  UpdateModel( ALL_OPERATIONS );
+  mImpl->mOperationsPending = static_cast<OperationsMask>( LAYOUT |
+                                                           UPDATE_ACTUAL_SIZE |
+                                                           REORDER );
+}
+
+void Controller::InsertTextEvent( const std::string& text )
+{
+  DALI_ASSERT_DEBUG( NULL != mImpl->mTextInput && "Unexpected InsertTextEvent" );
+
+  // TODO - Optimize this
+  mImpl->mLogicalModel->mScriptRuns.Clear();
+  mImpl->mLogicalModel->mFontRuns.Clear();
+  mImpl->mLogicalModel->mLineBreakInfo.Clear();
+  mImpl->mLogicalModel->mWordBreakInfo.Clear();
+  mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear();
+  mImpl->mVisualModel->mGlyphs.Clear();
+
+  //  Convert text into UTF-32
   Vector<Character> utf32Characters;
-  Length characterCount = 0u;
-  if( CONVERT_TO_UTF32 & operations )
+  utf32Characters.Resize( text.size() );
+
+  // This is a bit horrible but std::string returns a (signed) char*
+  const uint8_t* utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
+
+  // Transform a text array encoded in utf8 into an array encoded in utf32.
+  // It returns the actual number of characters.
+  Length characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() );
+  utf32Characters.Resize( characterCount );
+
+  // Insert at current cursor position
+  Vector<Character>& modifyText = mImpl->mLogicalModel->mText;
+  CharacterIndex& cursorIndex = mImpl->mTextInput->mPrimaryCursorPosition;
+
+  if( cursorIndex < modifyText.Count() )
   {
-    std::string& text = mImpl->mNewText;
+    modifyText.Insert( modifyText.Begin() + cursorIndex, utf32Characters.Begin(), utf32Characters.End() );
+  }
+  else
+  {
+    modifyText.Insert( modifyText.End(), utf32Characters.Begin(), utf32Characters.End() );
+  }
 
-    //  Convert text into UTF-32
-    utf32Characters.Resize( text.size() );
+  // Advance the cursor position
+  ++cursorIndex;
 
-    // This is a bit horrible but std::string returns a (signed) char*
-    const uint8_t* utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
+  // The natural size needs to be re-calculated.
+  mImpl->mRecalculateNaturalSize = true;
 
-    // Transform a text array encoded in utf8 into an array encoded in utf32.
-    // It returns the actual number of characters.
-    characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() );
-    utf32Characters.Resize( characterCount );
+  // Apply modifications to the model; TODO - Optimize this
+  mImpl->mOperationsPending = ALL_OPERATIONS;
+  UpdateModel( ALL_OPERATIONS );
+  mImpl->mOperationsPending = static_cast<OperationsMask>( LAYOUT |
+                                                           UPDATE_ACTUAL_SIZE |
+                                                           REORDER );
+}
 
-    // Sets the text into the model.
-    mImpl->mLogicalModel->SetText( utf32Characters.Begin(), characterCount );
+void Controller::DeleteTextEvent()
+{
+  DALI_ASSERT_DEBUG( NULL != mImpl->mTextInput && "Unexpected InsertTextEvent" );
+
+  // TODO - Optimize this
+  mImpl->mLogicalModel->mScriptRuns.Clear();
+  mImpl->mLogicalModel->mFontRuns.Clear();
+  mImpl->mLogicalModel->mLineBreakInfo.Clear();
+  mImpl->mLogicalModel->mWordBreakInfo.Clear();
+  mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear();
+  mImpl->mVisualModel->mGlyphs.Clear();
+
+  // Delte at current cursor position
+  Vector<Character>& modifyText = mImpl->mLogicalModel->mText;
+  CharacterIndex& cursorIndex = mImpl->mTextInput->mPrimaryCursorPosition;
+
+  if( cursorIndex > 0 &&
+      cursorIndex-1 < modifyText.Count() )
+  {
+    modifyText.Remove( modifyText.Begin() + cursorIndex - 1 );
 
-    // Discard temporary text
-    text.clear();
+    // Cursor position retreat
+    --cursorIndex;
   }
 
+  // The natural size needs to be re-calculated.
+  mImpl->mRecalculateNaturalSize = true;
+
+  // Apply modifications to the model; TODO - Optimize this
+  mImpl->mOperationsPending = ALL_OPERATIONS;
+  UpdateModel( ALL_OPERATIONS );
+  mImpl->mOperationsPending = static_cast<OperationsMask>( LAYOUT |
+                                                           UPDATE_ACTUAL_SIZE |
+                                                           REORDER );
+}
+
+void Controller::UpdateModel( OperationsMask operationsRequired )
+{
+  // Calculate the operations to be done.
+  const OperationsMask operations = static_cast<OperationsMask>( mImpl->mOperationsPending & operationsRequired );
+
+  Vector<Character>& utf32Characters = mImpl->mLogicalModel->mText;
+
   const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
 
-  Vector<LineBreakInfo> lineBreakInfo;
+  Vector<LineBreakInfo>& lineBreakInfo = mImpl->mLogicalModel->mLineBreakInfo;
   if( GET_LINE_BREAKS & operations )
   {
     // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
     // calculate the bidirectional info for each 'paragraph'.
     // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
     // is not shaped together).
-    lineBreakInfo.Resize( characterCount, TextAbstraction::LINE_NO_BREAK );
+    lineBreakInfo.Resize( numberOfCharacters, TextAbstraction::LINE_NO_BREAK );
 
     SetLineBreakInfo( utf32Characters,
                       lineBreakInfo );
-
-    mImpl->mLogicalModel->SetLineBreakInfo( lineBreakInfo.Begin(), characterCount );
   }
 
-  Vector<WordBreakInfo> wordBreakInfo;
+  Vector<WordBreakInfo>& wordBreakInfo = mImpl->mLogicalModel->mWordBreakInfo;
   if( 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( characterCount, TextAbstraction::WORD_NO_BREAK );
+    wordBreakInfo.Resize( numberOfCharacters, TextAbstraction::WORD_NO_BREAK );
 
     SetWordBreakInfo( utf32Characters,
                       wordBreakInfo );
-
-    mImpl->mLogicalModel->SetWordBreakInfo( wordBreakInfo.Begin(), characterCount );
   }
 
   const bool getScripts = GET_SCRIPTS & operations;
   const bool validateFonts = VALIDATE_FONTS & operations;
 
-  Vector<ScriptRun> scripts;
-  Vector<FontRun> validFonts;
+  Vector<ScriptRun>& scripts = mImpl->mLogicalModel->mScriptRuns;
+  Vector<FontRun>& validFonts = mImpl->mLogicalModel->mFontRuns;
 
   if( getScripts || validateFonts )
   {
@@ -693,69 +949,34 @@ bool Controller::DoRelayout( const Vector2& size,
       multilanguageSupport.SetScripts( utf32Characters,
                                        lineBreakInfo,
                                        scripts );
-
-      // Sets the scripts into the model.
-      mImpl->mLogicalModel->SetScripts( scripts.Begin(), scripts.Count() );
     }
 
     if( validateFonts )
     {
-      // Copy the requested font defaults received via the property system.
-      // These may not be valid i.e. may not contain glyphs for the necessary scripts.
-      GetDefaultFonts( validFonts, numberOfCharacters );
+      if( 0u == validFonts.Count() )
+      {
+        // Copy the requested font defaults received via the property system.
+        // These may not be valid i.e. may not contain glyphs for the necessary scripts.
+        GetDefaultFonts( validFonts, numberOfCharacters );
+      }
 
       // Validates the fonts. If there is a character with no assigned font it sets a default one.
       // After this call, fonts are validated.
       multilanguageSupport.ValidateFonts( utf32Characters,
                                           scripts,
                                           validFonts );
-
-      // Sets the fonts into the model.
-      mImpl->mLogicalModel->SetFonts( validFonts.Begin(), validFonts.Count() );
     }
   }
 
-  Vector<BidirectionalParagraphInfoRun> bidirectionalInfo;
   if( BIDI_INFO & operations )
   {
-    // Some vectors with data needed to get the paragraph's bidirectional info may be void
-    // after the first time the text has been laid out.
-    // Fill the vectors again.
-
-    if( 0u == utf32Characters.Count() )
-    {
-      utf32Characters.Resize( numberOfCharacters );
-
-      mImpl->mLogicalModel->GetText( utf32Characters.Begin(),
-                                     0u,
-                                     numberOfCharacters );
-    }
-
-    if( 0u == lineBreakInfo.Count() )
-    {
-      lineBreakInfo.Resize( numberOfCharacters );
-
-      mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(),
-                                              0u,
-                                              numberOfCharacters );
-    }
-
-    if( 0u == scripts.Count() )
-    {
-      scripts.Resize( mImpl->mLogicalModel->GetNumberOfScriptRuns( 0u,
-                                                                   numberOfCharacters ) );
-      mImpl->mLogicalModel->GetScriptRuns( scripts.Begin(),
-                                           0u,
-                                           numberOfCharacters );
-    }
-
     // Count the number of LINE_NO_BREAK to reserve some space for the vector of paragraph's
     // bidirectional info.
 
     Length numberOfParagraphs = 0u;
 
     const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
-    for( Length index = 0u; index < characterCount; ++index )
+    for( Length index = 0u; index < numberOfCharacters; ++index )
     {
       if( TextAbstraction::LINE_NO_BREAK == *( lineBreakInfoBuffer + index ) )
       {
@@ -763,6 +984,7 @@ bool Controller::DoRelayout( const Vector2& size,
       }
     }
 
+    Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo;
     bidirectionalInfo.Reserve( numberOfParagraphs );
 
     // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
@@ -770,25 +992,13 @@ bool Controller::DoRelayout( const Vector2& size,
                           scripts,
                           lineBreakInfo,
                           bidirectionalInfo );
-
-    mImpl->mLogicalModel->SetBidirectionalInfo( bidirectionalInfo.Begin(),
-                                                bidirectionalInfo.Count() );
   }
 
-  Vector<GlyphInfo> glyphs;
-  Vector<CharacterIndex> glyphsToCharactersMap;
-  Vector<Length> charactersPerGlyph;
+  Vector<GlyphInfo>& glyphs = mImpl->mVisualModel->mGlyphs;
+  Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters;
+  Vector<Length>& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph;
   if( SHAPE_TEXT & operations )
   {
-    if( 0u == validFonts.Count() )
-    {
-      validFonts.Resize( mImpl->mLogicalModel->GetNumberOfFontRuns( 0u,
-                                                                    numberOfCharacters ) );
-      mImpl->mLogicalModel->GetFontRuns( validFonts.Begin(),
-                                         0u,
-                                         numberOfCharacters );
-    }
-
     // Shapes the text.
     ShapeText( utf32Characters,
                lineBreakInfo,
@@ -799,20 +1009,29 @@ bool Controller::DoRelayout( const Vector2& size,
                charactersPerGlyph );
   }
 
+  const Length numberOfGlyphs = glyphs.Count();
+
   if( GET_GLYPH_METRICS & operations )
   {
-    mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), glyphs.Count() );
+    mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), numberOfGlyphs );
   }
 
-  Length numberOfGlyphs = glyphs.Count();
   if( 0u != numberOfGlyphs )
   {
-    // Sets the glyphs into the model.
-    mImpl->mVisualModel->SetGlyphs( glyphs.Begin(),
-                                    glyphsToCharactersMap.Begin(),
-                                    charactersPerGlyph.Begin(),
-                                    numberOfGlyphs );
+    // Create the glyph to character conversion table and the 'number of glyphs' per character.
+    mImpl->mVisualModel->CreateCharacterToGlyphTable(numberOfCharacters );
+    mImpl->mVisualModel->CreateGlyphsPerCharacterTable( numberOfCharacters );
   }
+}
+
+bool Controller::DoRelayout( const Vector2& size,
+                             OperationsMask operationsRequired,
+                             Size& layoutSize )
+{
+  bool viewUpdated( false );
+
+  // Calculate the operations to be done.
+  const OperationsMask operations = static_cast<OperationsMask>( mImpl->mOperationsPending & operationsRequired );
 
   if( LAYOUT & operations )
   {
@@ -821,47 +1040,13 @@ bool Controller::DoRelayout( const Vector2& size,
     // Fill the vectors again.
 
     const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
-    numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
+    Length numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
 
-    if( 0u == lineBreakInfo.Count() )
-    {
-      lineBreakInfo.Resize( numberOfCharacters );
-      mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(),
-                                              0u,
-                                              numberOfCharacters );
-    }
-
-    if( 0u == wordBreakInfo.Count() )
-    {
-      wordBreakInfo.Resize( numberOfCharacters );
-      mImpl->mLogicalModel->GetWordBreakInfo( wordBreakInfo.Begin(),
-                                              0u,
-                                              numberOfCharacters );
-    }
-
-    if( 0u == glyphs.Count() )
-    {
-      glyphs.Resize( numberOfGlyphs );
-      mImpl->mVisualModel->GetGlyphs( glyphs.Begin(),
-                                      0u,
-                                      numberOfGlyphs );
-    }
-
-    if( 0u == glyphsToCharactersMap.Count() )
-    {
-      glyphsToCharactersMap.Resize( numberOfGlyphs );
-      mImpl->mVisualModel->GetGlyphToCharacterMap( glyphsToCharactersMap.Begin(),
-                                                   0u,
-                                                   numberOfGlyphs );
-    }
-
-    if( 0u == charactersPerGlyph.Count() )
-    {
-      charactersPerGlyph.Resize( numberOfGlyphs );
-      mImpl->mVisualModel->GetCharactersPerGlyphMap( charactersPerGlyph.Begin(),
-                                                     0u,
-                                                     numberOfGlyphs );
-    }
+    Vector<LineBreakInfo>& lineBreakInfo = mImpl->mLogicalModel->mLineBreakInfo;
+    Vector<WordBreakInfo>& wordBreakInfo = mImpl->mLogicalModel->mWordBreakInfo;
+    Vector<GlyphInfo>& glyphs = mImpl->mVisualModel->mGlyphs;
+    Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters;
+    Vector<Length>& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph;
 
     // Set the layout parameters.
     LayoutParameters layoutParameters( size,
@@ -872,16 +1057,23 @@ bool Controller::DoRelayout( const Vector2& size,
                                        glyphsToCharactersMap.Begin(),
                                        charactersPerGlyph.Begin() );
 
-    // Reserve space to set the positions of the glyphs.
-    Vector<Vector2> glyphPositions;
-    glyphPositions.Resize( numberOfGlyphs );
-
     // The laid-out lines.
     // It's not possible to know in how many lines the text is going to be laid-out,
     // but it can be resized at least with the number of 'paragraphs' to avoid
     // some re-allocations.
-    Vector<LineRun> lines;
-    lines.Reserve( mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters ) );
+    Vector<LineRun>& lines = mImpl->mVisualModel->mLines;
+
+    // Resize the vector of positions to have the same size than the vector of glyphs.
+    Vector<Vector2>& glyphPositions = mImpl->mVisualModel->mGlyphPositions;
+    glyphPositions.Resize( numberOfGlyphs );
+
+    BidirectionalRunIndex firstBidiRunIndex = 0u;
+    Length numberOfBidiRuns = 0u;
+    mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters, firstBidiRunIndex, numberOfBidiRuns );
+
+    // Delete any previous laid out lines before setting the new ones.
+    lines.Clear();
+    lines.Reserve( numberOfBidiRuns );
 
     // Update the visual model.
     viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters,
@@ -894,15 +1086,7 @@ bool Controller::DoRelayout( const Vector2& size,
       // Reorder the lines
       if( REORDER & operations )
       {
-        const Length numberOfBidiParagraphs = mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters );
-
-        if( 0u == bidirectionalInfo.Count() )
-        {
-          bidirectionalInfo.Resize( numberOfBidiParagraphs );
-          mImpl->mLogicalModel->GetBidirectionalInfo( bidirectionalInfo.Begin(),
-                                                      0u,
-                                                      numberOfCharacters );
-        }
+        Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo;
 
         // Check first if there are paragraphs with bidirectional info.
         if( 0u != bidirectionalInfo.Count() )
@@ -927,22 +1111,10 @@ bool Controller::DoRelayout( const Vector2& size,
           layoutParameters.numberOfBidirectionalInfoRuns = numberOfBidirectionalInfoRuns;
 
           // Get the character to glyph conversion table and set into the layout.
-          Vector<GlyphIndex> characterToGlyphMap;
-          characterToGlyphMap.Resize( numberOfCharacters );
-
-          layoutParameters.charactersToGlyphsBuffer = characterToGlyphMap.Begin();
-          mImpl->mVisualModel->GetCharacterToGlyphMap( layoutParameters.charactersToGlyphsBuffer,
-                                                       0u,
-                                                       numberOfCharacters );
+          layoutParameters.charactersToGlyphsBuffer = mImpl->mVisualModel->mCharactersToGlyph.Begin();
 
           // Get the glyphs per character table and set into the layout.
-          Vector<Length> glyphsPerCharacter;
-          glyphsPerCharacter.Resize( numberOfCharacters );
-
-          layoutParameters.glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
-          mImpl->mVisualModel->GetGlyphsPerCharacterMap( layoutParameters.glyphsPerCharacterBuffer,
-                                                         0u,
-                                                         numberOfCharacters );
+          layoutParameters.glyphsPerCharacterBuffer = mImpl->mVisualModel->mGlyphsPerCharacter.Begin();
 
           // Re-layout the text. Reorder those lines with right to left characters.
           mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters,
@@ -961,20 +1133,6 @@ bool Controller::DoRelayout( const Vector2& size,
         }
       }
 
-      // Sets the positions into the model.
-      if( UPDATE_POSITIONS & operations )
-      {
-        mImpl->mVisualModel->SetGlyphPositions( glyphPositions.Begin(),
-                                                numberOfGlyphs );
-      }
-
-      // Sets the lines into the model.
-      if( UPDATE_LINES & operations )
-      {
-        mImpl->mVisualModel->SetLines( lines.Begin(),
-                                       lines.Count() );
-      }
-
       // Sets the actual size.
       if( UPDATE_ACTUAL_SIZE & operations )
       {
@@ -990,87 +1148,6 @@ bool Controller::DoRelayout( const Vector2& size,
   return viewUpdated;
 }
 
-Vector3 Controller::GetNaturalSize()
-{
-  Vector3 naturalSize;
-
-  if( mImpl->mRecalculateNaturalSize )
-  {
-    // Operations that can be done only once until the text changes.
-    const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
-                                                                           GET_SCRIPTS       |
-                                                                           VALIDATE_FONTS    |
-                                                                           GET_LINE_BREAKS   |
-                                                                           GET_WORD_BREAKS   |
-                                                                           SHAPE_TEXT        |
-                                                                           GET_GLYPH_METRICS );
-
-    // Operations that need to be done if the size changes.
-    const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
-                                                                        REORDER );
-
-    DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ),
-                static_cast<OperationsMask>( onlyOnceOperations |
-                                             sizeOperations ),
-                naturalSize.GetVectorXY() );
-
-    // Do not do again the only once operations.
-    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
-
-    // Do the size related operations again.
-    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
-
-    // Stores the natural size to avoid recalculate it again
-    // unless the text/style changes.
-    mImpl->mVisualModel->SetNaturalSize( naturalSize.GetVectorXY() );
-
-    mImpl->mRecalculateNaturalSize = false;
-  }
-  else
-  {
-    naturalSize = mImpl->mVisualModel->GetNaturalSize();
-  }
-
-  return naturalSize;
-}
-
-float Controller::GetHeightForWidth( float width )
-{
-  Size layoutSize;
-  if( width != mImpl->mControlSize.width )
-  {
-    // Operations that can be done only once until the text changes.
-    const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
-                                                                           GET_SCRIPTS       |
-                                                                           VALIDATE_FONTS    |
-                                                                           GET_LINE_BREAKS   |
-                                                                           GET_WORD_BREAKS   |
-                                                                           SHAPE_TEXT        |
-                                                                           GET_GLYPH_METRICS );
-
-    // Operations that need to be done if the size changes.
-    const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
-                                                                        REORDER );
-
-    DoRelayout( Size( width, MAX_FLOAT ),
-                static_cast<OperationsMask>( onlyOnceOperations |
-                                             sizeOperations ),
-                layoutSize );
-
-    // Do not do again the only once operations.
-    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
-
-    // Do the size related operations again.
-    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
-  }
-  else
-  {
-    layoutSize = mImpl->mVisualModel->GetActualSize();
-  }
-
-  return layoutSize.height;
-}
-
 View& Controller::GetView()
 {
   return mImpl->mView;
@@ -1116,21 +1193,42 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
 {
   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyEvent" );
 
-  if( mImpl->mTextInput )
+  if( mImpl->mTextInput &&
+      keyEvent.state == KeyEvent::Down )
   {
-    TextInput::Event event( TextInput::KEY_EVENT );
-    event.p1.mInt = keyEvent.keyCode;
-    event.p2.mString = NULL;
-
+    int keyCode = keyEvent.keyCode;
     const std::string& keyString = keyEvent.keyPressed;
-    if ( !keyString.empty() )
+
+    // Pre-process to separate modifying events from non-modifying input events.
+    if( Dali::DALI_KEY_ESCAPE == keyCode )
     {
-      event.p2.mString = new char[keyString.size() + 1];
-      std::copy(keyString.begin(), keyString.end(), event.p2.mString);
-      event.p2.mString[keyString.size()] = '\0';
+      // Escape key is a special case which causes focus loss
+      KeyboardFocusLostEvent();
+    }
+    else if( Dali::DALI_KEY_CURSOR_LEFT  == keyCode ||
+             Dali::DALI_KEY_CURSOR_RIGHT == keyCode ||
+             Dali::DALI_KEY_CURSOR_UP    == keyCode ||
+             Dali::DALI_KEY_CURSOR_DOWN  == keyCode )
+    {
+      TextInput::Event event( TextInput::CURSOR_KEY_EVENT );
+      event.p1.mInt = keyCode;
+      mImpl->mTextInput->mEventQueue.push_back( event );
+    }
+    else if( Dali::DALI_KEY_BACKSPACE == keyCode )
+    {
+      // Queue a delete event
+      ModifyEvent event;
+      event.type = DELETE_TEXT;
+      mImpl->mModifyEvents.push_back( event );
+    }
+    else if( !keyString.empty() )
+    {
+      // Queue an insert event
+      ModifyEvent event;
+      event.type = INSERT_TEXT;
+      event.text = keyString;
+      mImpl->mModifyEvents.push_back( event );
     }
-
-    mImpl->mTextInput->mEventQueue.push_back( event );
 
     RequestRelayout();
   }
index 9b38aca..82672e6 100644 (file)
@@ -77,11 +77,9 @@ private:
     GET_GLYPH_METRICS  = 0x0080,
     LAYOUT             = 0x0100,
     UPDATE_ACTUAL_SIZE = 0x0200,
-    UPDATE_POSITIONS   = 0x0400,
-    UPDATE_LINES       = 0x0800,
-    REORDER            = 0x1000,
-    ALIGNMENT          = 0x2000,
-    RENDER             = 0x4000,
+    REORDER            = 0x0400,
+    ALIGNMENT          = 0x0800,
+    RENDER             = 0x1000,
     ALL_OPERATIONS     = 0xFFFF
   };
 
@@ -136,7 +134,7 @@ public:
    *
    * @return The default font family.
    */
-   const std::string& GetDefaultFontFamily() const;
+  const std::string& GetDefaultFontFamily() const;
 
   /**
    * @brief Set the default font style.
@@ -150,7 +148,7 @@ public:
    *
    * @return The default font style.
    */
-   const std::string& GetDefaultFontStyle() const;
+  const std::string& GetDefaultFontStyle() const;
 
   /**
    * @brief Set the default point size.
@@ -164,7 +162,7 @@ public:
    *
    * @return The default point size.
    */
-   float GetDefaultPointSize() const;
+  float GetDefaultPointSize() const;
 
   /**
    * @brief Retrieve the default fonts.
@@ -172,7 +170,7 @@ public:
    * @param[out] fonts The default font family, style and point sizes.
    * @param[in] numberOfCharacters The number of characters in the logical model.
    */
-   void GetDefaultFonts( Dali::Vector<FontRun>& fonts, Length numberOfCharacters );
+  void GetDefaultFonts( Dali::Vector<FontRun>& fonts, Length numberOfCharacters );
 
   /**
    * @brief Called to enable text input.
@@ -183,6 +181,31 @@ public:
   void EnableTextInput( DecoratorPtr decorator );
 
   /**
+   * @brief Called to enable/disable cursor blink.
+   *
+   * @note Only editable controls should calls this.
+   * @param[in] enabled Whether the cursor should blink or not.
+   */
+  void SetEnableCursorBlink( bool enable );
+
+  /**
+   * @brief Query whether cursor blink is enabled.
+   *
+   * @return Whether the cursor should blink or not.
+   */
+  bool GetEnableCursorBlink() const;
+
+  /**
+   * @copydoc Control::GetNaturalSize()
+   */
+  Vector3 GetNaturalSize();
+
+  /**
+   * @copydoc Control::GetHeightForWidth()
+   */
+  float GetHeightForWidth( float width );
+
+  /**
    * @brief Triggers a relayout which updates View (if necessary).
    *
    * @note UI Controls are expected to minimize calls to this method e.g. call once after size negotiation.
@@ -192,6 +215,37 @@ public:
   bool Relayout( const Vector2& size );
 
   /**
+   * @brief Process queued events which modify the model.
+   */
+  void ProcessModifyEvents();
+
+  /**
+   * @brief Used to process an event queued from SetText()
+   *
+   * @param[in] newText The new text to store in the logical model.
+   */
+  void ReplaceTextEvent( const std::string& newText );
+
+  /**
+   * @brief Used to process an event queued from key events etc.
+   *
+   * @param[in] text The text to insert into the logical model.
+   */
+  void InsertTextEvent( const std::string& text );
+
+  /**
+   * @brief Used to process an event queued from backspace key etc.
+   */
+  void DeleteTextEvent();
+
+  /**
+   * @brief Update the model following text replace/insert etc.
+   *
+   * @param[in] operationsRequired The layout operations which need to be done.
+   */
+  void UpdateModel( OperationsMask operationsRequired );
+
+  /**
    * @brief Lays-out the text.
    *
    * GetNaturalSize(), GetHeightForWidth() and Relayout() calls this method.
@@ -205,16 +259,6 @@ public:
                    Size& layoutSize );
 
   /**
-   * @copydoc Control::GetNaturalSize()
-   */
-  Vector3 GetNaturalSize();
-
-  /**
-   * @copydoc Control::GetHeightForWidth()
-   */
-  float GetHeightForWidth( float width );
-
-  /**
    * @brief Return the layout engine.
    *
    * @return A reference to the layout engine.
@@ -228,6 +272,8 @@ public:
    */
   View& GetView();
 
+  // Text-input Event Queuing
+
   /**
    * @brief Caller by editable UI controls when keyboard focus is gained.
    */
index d991384..6f00b7b 100644 (file)
@@ -33,23 +33,26 @@ namespace Toolkit
 namespace Text
 {
 
-typedef TextAbstraction::FontId          FontId;             ///< The unique identifier for a font face (generated by FontClient).
-typedef TextAbstraction::FontMetrics     FontMetrics;        ///< The metrics for a Font expressed in 26.6 fractional pixel format.
-typedef TextAbstraction::PointSize26Dot6 PointSize26Dot6;    ///< The point size in 26.6 fractional points.
-typedef TextAbstraction::FaceIndex       FaceIndex;          ///< Used with fonts which allow several font faces.
-typedef TextAbstraction::GlyphIndex      GlyphIndex;         ///< Uniquely identifies a glyph within a particular font.
-typedef TextAbstraction::Character       Character;          ///< A UTF-32 representation of a character.
-typedef TextAbstraction::GlyphInfo       GlyphInfo;          ///< The information describing a glyph (font ID, index, metrics).
-typedef TextAbstraction::CharacterIndex  CharacterIndex;     ///< An index into an array of characters.
-typedef TextAbstraction::Length          Length;             ///< The length of an array.
-typedef TextAbstraction::BidiInfoIndex   BidiInfoIndex;      ///< Index to the bidirectional info for a paragraph.
-typedef TextAbstraction::Script          Script;             ///< The character's script.
-typedef TextAbstraction::LineBreakInfo   LineBreakInfo;      ///< Line break info (must break, allow break, no break). Possible values are: @e LINE_MUST_BREAK, @e LINE_ALLOW_BREAK and @e LINE_NO_BREAK (in the TextAbstraction namespace).
-typedef TextAbstraction::WordBreakInfo   WordBreakInfo;      ///< Word break info (break, no break). Possible values are: @e WORD_BREAK and @e WORD_NO_BREAK (in the TextAbstraction namespace).
-
-typedef uint32_t                         GlyphIndex;         ///< An index into an array of glyphs.
-typedef bool                             CharacterDirection; ///< The character's direction: @e false is left to right, @e true is right to left.
-typedef uint32_t                         LineIndex;          ///< An index into an array of lines.
+typedef TextAbstraction::FontId          FontId;                ///< The unique identifier for a font face (generated by FontClient).
+typedef TextAbstraction::FontMetrics     FontMetrics;           ///< The metrics for a Font expressed in 26.6 fractional pixel format.
+typedef TextAbstraction::PointSize26Dot6 PointSize26Dot6;       ///< The point size in 26.6 fractional points.
+typedef TextAbstraction::FaceIndex       FaceIndex;             ///< Used with fonts which allow several font faces.
+typedef TextAbstraction::GlyphIndex      GlyphIndex;            ///< Uniquely identifies a glyph within a particular font.
+typedef TextAbstraction::Character       Character;             ///< A UTF-32 representation of a character.
+typedef TextAbstraction::GlyphInfo       GlyphInfo;             ///< The information describing a glyph (font ID, index, metrics).
+typedef TextAbstraction::CharacterIndex  CharacterIndex;        ///< An index into an array of characters.
+typedef TextAbstraction::Length          Length;                ///< The length of an array.
+typedef TextAbstraction::BidiInfoIndex   BidiInfoIndex;         ///< Index to the bidirectional info for a paragraph.
+typedef TextAbstraction::Script          Script;                ///< The character's script.
+typedef TextAbstraction::LineBreakInfo   LineBreakInfo;         ///< Line break info (must break, allow break, no break). Possible values are: @e LINE_MUST_BREAK, @e LINE_ALLOW_BREAK and @e LINE_NO_BREAK (in the TextAbstraction namespace).
+typedef TextAbstraction::WordBreakInfo   WordBreakInfo;         ///< Word break info (break, no break). Possible values are: @e WORD_BREAK and @e WORD_NO_BREAK (in the TextAbstraction namespace).
+
+typedef uint32_t                         GlyphIndex;            ///< An index into an array of glyphs.
+typedef bool                             CharacterDirection;    ///< The character's direction: @e false is left to right, @e true is right to left.
+typedef uint32_t                         ScriptRunIndex;        ///< An index into an array of script runs.
+typedef uint32_t                         FontRunIndex;          ///< An index into an array of font runs.
+typedef uint32_t                         BidirectionalRunIndex; ///< An index into an array of font runs.
+typedef uint32_t                         LineIndex;             ///< An index into an array of lines.
 
 } // namespace Text
 
index c3d033e..56ce0be 100644 (file)
@@ -20,7 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/text-view-interface.h>
-#include <dali-toolkit/internal/text/visual-model.h>
+#include <dali-toolkit/internal/text/visual-model-impl.h>
 
 namespace Dali
 {
diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp
new file mode 100644 (file)
index 0000000..5822469
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/visual-model-impl.h>
+
+// EXTERNAL INCLUDES
+#include <memory.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+VisualModelPtr VisualModel::New()
+{
+  return VisualModelPtr( new VisualModel() );
+}
+
+void VisualModel::SetGlyphs( const GlyphInfo* glyphs,
+                             const CharacterIndex* characterIndices,
+                             const Length* charactersPerGlyph,
+                             Length numberOfGlyphs )
+{
+  if( 0u == numberOfGlyphs )
+  {
+    mGlyphs.Clear();
+    mGlyphsToCharacters.Clear();
+    mCharactersToGlyph.Clear();
+    mCharactersPerGlyph.Clear();
+    mGlyphsPerCharacter.Clear();
+  }
+  else
+  {
+    if( NULL != glyphs )
+    {
+      mGlyphs.Resize( numberOfGlyphs );
+      memcpy( mGlyphs.Begin(), glyphs, numberOfGlyphs * sizeof( GlyphInfo ) );
+    }
+
+    if( NULL != characterIndices )
+    {
+      mGlyphsToCharacters.Resize( numberOfGlyphs );
+      memcpy( mGlyphsToCharacters.Begin(), characterIndices, numberOfGlyphs * sizeof( CharacterIndex ) );
+    }
+
+    if( NULL != charactersPerGlyph )
+    {
+      mCharactersPerGlyph.Resize( numberOfGlyphs );
+      memcpy( mCharactersPerGlyph.Begin(), charactersPerGlyph, numberOfGlyphs * sizeof( Length ) );
+
+      // Build the characters to glyph conversion table.
+      CreateCharacterToGlyphTable();
+
+      // Build the glyphs per character table.
+      CreateGlyphsPerCharacterTable();
+    }
+  }
+}
+
+void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters )
+{
+  // 1) Reserve some space for the characters to avoid reallocations.
+  if( 0u == numberOfCharacters )
+  {
+    // If no number of characters is given, just set something sensible to avoid reallocations.
+    numberOfCharacters = static_cast<Length> ( static_cast<float>( mGlyphs.Count() ) * 1.3f );
+  }
+  mCharactersToGlyph.Reserve( numberOfCharacters );
+
+  // 2) Traverse the glyphs and set the glyph indices per character.
+
+  // Index to the glyph.
+  GlyphIndex glyphIndex = 0u;
+  for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin(),
+         endIt = mCharactersPerGlyph.End();
+       it != endIt;
+       ++it, ++glyphIndex )
+  {
+    const Length numberOfCharactersPerGlyph = *it;
+
+    // Set the glyph indices.
+    for( Length index = 0u; index < numberOfCharactersPerGlyph; ++index )
+    {
+      mCharactersToGlyph.PushBack( glyphIndex );
+    }
+  }
+}
+
+void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters )
+{
+  // 1) Reserve some space for the characters to avoid reallocations.
+  if( 0u == numberOfCharacters )
+  {
+    // If no number of characters is given, just set something sensible to avoid reallocations.
+    numberOfCharacters = static_cast<Length> ( static_cast<float>( mGlyphs.Count() ) * 1.3f );
+  }
+  mCharactersToGlyph.Reserve( numberOfCharacters );
+
+  // 2) Traverse the glyphs and set the number of glyphs per character.
+
+  // The number of 'characters per glyph' equal to zero.
+  Length zeroCharactersPerGlyph = 0u;
+
+  for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin(),
+         endIt = mCharactersPerGlyph.End();
+       it != endIt;
+       ++it )
+  {
+    const Length numberOfCharactersPerGlyph = *it;
+
+    // Set the glyphs per character.
+    if( 0u == numberOfCharactersPerGlyph )
+    {
+      ++zeroCharactersPerGlyph;
+    }
+    else
+    {
+      const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharactersPerGlyph - 1u );
+      for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex )
+      {
+        mGlyphsPerCharacter.PushBack( 0u );
+      }
+
+      mGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph );
+
+      zeroCharactersPerGlyph = 0u;
+    }
+  }
+}
+
+Length VisualModel::GetNumberOfGlyphs() const
+{
+  return mGlyphs.Count();
+}
+
+void VisualModel::GetGlyphs( GlyphInfo* glyphs,
+                             GlyphIndex glyphIndex,
+                             Length numberOfGlyphs ) const
+{
+  memcpy( glyphs, mGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) );
+}
+
+const GlyphInfo& VisualModel::GetGlyphInfo( GlyphIndex glyphIndex ) const
+{
+  return mGlyphs[glyphIndex];
+}
+
+void VisualModel::ReplaceGlyphs( GlyphIndex glyphIndex,
+                                 Length numberOfGlyphsToRemove,
+                                 const GlyphInfo* const glyphs,
+                                 const Length* const numberOfCharacters,
+                                 Length numberOfGlyphsToInsert )
+{
+}
+
+CharacterIndex VisualModel::GetCharacterIndex( GlyphIndex glyphIndex ) const
+{
+  return mGlyphsToCharacters[glyphIndex];
+}
+
+Length VisualModel::GetCharactersPerGlyph( GlyphIndex glyphIndex ) const
+{
+  return mCharactersPerGlyph[glyphIndex];
+}
+
+GlyphIndex VisualModel::GetGlyphIndex( CharacterIndex characterIndex ) const
+{
+  return mCharactersToGlyph[characterIndex];
+}
+
+void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap,
+                                          CharacterIndex characterIndex,
+                                          Length numberOfCharacters ) const
+{
+  memcpy( characterToGlyphMap, mCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) );
+}
+
+void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
+                                          GlyphIndex glyphIndex,
+                                          Length numberOfGlyphs ) const
+{
+  memcpy( glyphToCharacter, mGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) );
+}
+
+void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph,
+                                            GlyphIndex glyphIndex,
+                                            Length numberOfGlyphs ) const
+{
+  memcpy( charactersPerGlyph, mCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) );
+}
+
+void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter,
+                                            CharacterIndex characterIndex,
+                                            Length numberOfCharacters ) const
+{
+  memcpy( glyphsPerCharacter, mGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) );
+}
+
+void VisualModel::SetGlyphPositions( const Vector2* glyphPositions,
+                                     Length numberOfGlyphs )
+{
+  if( 0u == numberOfGlyphs )
+  {
+    mGlyphPositions.Clear();
+  }
+  else
+  {
+    mGlyphPositions.Resize( numberOfGlyphs );
+    memcpy( mGlyphPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) );
+  }
+}
+
+Length VisualModel::GetNumberOfGlyphPositions() const
+{
+  return mGlyphPositions.Count();
+}
+
+void VisualModel::GetGlyphPositions( Vector2* glyphPositions,
+                                     GlyphIndex glyphIndex,
+                                     Length numberOfGlyphs ) const
+{
+  memcpy( glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) );
+}
+
+const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const
+{
+  return *( mGlyphPositions.Begin() + glyphIndex );
+}
+
+void VisualModel::ReplaceGlyphPositions( GlyphIndex glyphIndex,
+                                         Length numberOfGlyphsToRemove,
+                                         const Vector2* const positions,
+                                         Length numberOfGlyphsToInsert )
+{
+}
+
+void VisualModel::SetLines( const LineRun* const lines,
+                            Length numberOfLines )
+{
+  if( 0u == numberOfLines )
+  {
+    mLines.Clear();
+  }
+  else
+  {
+    mLines.Resize( numberOfLines );
+    memcpy( mLines.Begin(), lines, numberOfLines * sizeof( LineRun ) );
+  }
+}
+
+Length VisualModel::GetNumberOfLines() const
+{
+  return mLines.Count();
+}
+
+void VisualModel::GetLines( LineRun* lines,
+                            LineIndex lineIndex,
+                            Length numberOfLines ) const
+{
+  memcpy( lines, mLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) );
+}
+
+void VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
+                                    Length numberOfGlyphs,
+                                    LineIndex& firstLine,
+                                    Length& numberOfLines ) const
+{
+  // Initialize the number of lines and the first line.
+  firstLine = 0u;
+  numberOfLines = 0u;
+  bool firstLineFound = false;
+
+  const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
+
+  // Traverse the lines and count those lines within the range of glyphs.
+  for( Vector<LineRun>::ConstIterator it = mLines.Begin(),
+         endIt = mLines.End();
+       it != endIt;
+       ++it )
+  {
+    const LineRun& line = *it;
+
+    if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) &&
+        ( lastGlyphIndex > line.glyphIndex ) )
+    {
+      firstLineFound = true;
+      ++numberOfLines;
+    }
+    else if( lastGlyphIndex <= line.glyphIndex )
+    {
+      // nothing else to do.
+      break;
+    }
+
+    if( !firstLineFound )
+    {
+      ++firstLine;
+    }
+  }
+}
+
+void VisualModel::GetLinesOfGlyphRange( LineRun* lines,
+                                        GlyphIndex glyphIndex,
+                                        Length numberOfGlyphs ) const
+{
+  LineIndex firstLine = 0u;
+  Length numberOfLines = 0u;
+
+  GetNumberOfLines( glyphIndex,
+                    numberOfGlyphs,
+                    firstLine,
+                    numberOfLines );
+
+  memcpy( lines, mLines.Begin() + firstLine, numberOfLines * sizeof( LineRun ) );
+}
+
+void VisualModel::ReplaceLines( GlyphIndex glyphIndex,
+                                Length numberOfGlyphsToRemove,
+                                const LineRun* const lines,
+                                Length numberOfGlyphsToInsert )
+{
+}
+
+void VisualModel::SetNaturalSize( const Vector2& size  )
+{
+  mNaturalSize = size;
+}
+
+const Vector2& VisualModel::GetNaturalSize() const
+{
+  return mNaturalSize;
+}
+
+void VisualModel::SetActualSize( const Vector2& size )
+{
+  mActualSize = size;
+}
+
+const Vector2& VisualModel::GetActualSize() const
+{
+  return mActualSize;
+}
+
+VisualModel::~VisualModel()
+{
+}
+
+VisualModel::VisualModel()
+{
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
similarity index 86%
rename from dali-toolkit/internal/text/visual-model.h
rename to dali-toolkit/internal/text/visual-model-impl.h
index 4dee216..415b4a0 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __DALI_TOOLKIT_TEXT_VISUAL_MODEL_H__
-#define __DALI_TOOLKIT_TEXT_VISUAL_MODEL_H__
+#ifndef __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__
+#define __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__
 
 /*
  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
  */
 
 // EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/common/intrusive-ptr.h>
 #include <dali/public-api/object/ref-object.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-definitions.h>
+#include <dali-toolkit/internal/text/line-run.h>
 
 namespace Dali
 {
@@ -77,6 +78,20 @@ public:
                   Length numberOfGlyphs );
 
   /**
+   * @brief Creates the character to glyph conversion table.
+   *
+   * @param[in] numberOfCharacters The number of characters.
+   */
+  void CreateCharacterToGlyphTable( Length numberOfCharacters = 0u );
+
+  /**
+   * @brief Creates an array containing the number of glyphs per character.
+   *
+   * @param[in] numberOfCharacters The number of characters.
+   */
+  void CreateGlyphsPerCharacterTable( Length numberOfCharacters = 0u );
+
+  /**
    * Retrieves the number of glyphs.
    *
    * @return The number of glyphs.
@@ -296,15 +311,17 @@ public:
                  Length numberOfLines ) const;
 
   /**
-   * Retrieves the number of lines where the given range of glyphs is laid out.
+   * Retrieves the number of lines and the index to the first line where the given range of glyphs is laid out.
    *
    * @param[in] glyphIndex Index to the first glyph.
    * @param[in] numberOfGlyphs The number of glyph.
-   *
-   * @return The number of lines.
+   * @param[out] firstLine Index to the line containing the glyph index.
+   * @param[out] numberOfLines The number of lines.
    */
-  Length GetNumberOfLines( GlyphIndex glyphIndex,
-                           Length numberOfGlyphs ) const;
+  void GetNumberOfLines( GlyphIndex glyphIndex,
+                         Length numberOfGlyphs,
+                         LineIndex& firstLine,
+                         Length& numberOfLines ) const;
   /**
    * Retrieves the lines where the given range of glyphs is laid out.
    *
@@ -384,15 +401,26 @@ private:
   // Undefined
   VisualModel& operator=( const VisualModel& handle );
 
+public:
+
+  Vector<GlyphInfo>      mGlyphs;             ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics.
+  Vector<CharacterIndex> mGlyphsToCharacters; ///< For each glyph, the index of the first character.
+  Vector<GlyphIndex>     mCharactersToGlyph;  ///< For each character, the index of the first glyph.
+  Vector<Length>         mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph.
+  Vector<Length>         mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped.
+  Vector<Vector2>        mGlyphPositions;     ///< For each glyph, the position.
+  Vector<LineRun>        mLines;              ///< The laid out lines.
+
 private:
 
-  struct Impl;
-  Impl* mImpl;
+  Size                   mNaturalSize;        ///< Size of the text with no line wrapping.
+  Size                   mActualSize;         ///< Size of the laid-out text considering the layout properties set.
 };
+
 } // namespace Text
 
 } // namespace Toolkit
 
 } // namespace Dali
 
-#endif // __DALI_TOOLKIT_TEXT_VISUAL_MODEL_H__
+#endif // __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__
diff --git a/dali-toolkit/internal/text/visual-model.cpp b/dali-toolkit/internal/text/visual-model.cpp
deleted file mode 100644 (file)
index e7015e0..0000000
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/visual-model.h>
-
-// EXTERNAL INCLUDES
-#include <memory.h>
-#include <dali/public-api/common/dali-vector.h>
-#include <dali/public-api/math/vector2.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/line-run.h>
-
-namespace Dali
-{
-
-namespace Toolkit
-{
-
-namespace Text
-{
-
-/**
- * @brief caches some temporary values of the GetNumberOfLines( glyphIndex, numberOfGlyphs ) operation
- * as they are going to be used in the GetLinesOfGlyphRange() call.
- */
-struct GetLineCache
-{
-  GlyphIndex glyphIndex;     ///< The glyph index.
-  Length     numberOfGlyphs; ///< The number of glyphs.
-  Length     firstLine;      ///< Index to the first line.
-  Length     numberOfLines;  ///< The number of lines.
-};
-
-struct VisualModel::Impl
-{
-  Vector<GlyphInfo>      mGlyphs;             ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics.
-  Vector<CharacterIndex> mGlyphsToCharacters; ///< For each glyph, the index of the first character.
-  Vector<GlyphIndex>     mCharactersToGlyph;  ///< For each character, the index of the first glyph.
-  Vector<Length>         mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph.
-  Vector<Length>         mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped.
-  Vector<Vector2>        mGlyphPositions;     ///< For each glyph, the position.
-  Vector<LineRun>        mLines;              ///< The laid out lines.
-
-  Size                   mNaturalSize;        ///< Size of the text with no line wrapping.
-  Size                   mActualSize;         ///< Size of the laid-out text considering the layout properties set.
-
-  GetLineCache           mGetLineCache;       ///< Caches the GetNumberOfLines( glyphIndex, numberOfGlyphs ) operation.
-};
-
-VisualModelPtr VisualModel::New()
-{
-  return VisualModelPtr( new VisualModel() );
-}
-
-void VisualModel::SetGlyphs( const GlyphInfo* glyphs,
-                             const CharacterIndex* characterIndices,
-                             const Length* charactersPerGlyph,
-                             Length numberOfGlyphs )
-{
-  Vector<GlyphInfo>& modelGlyphs = mImpl->mGlyphs;
-  Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
-  Vector<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
-  Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
-  Vector<Length>& modelGlyphsPerCharacter = mImpl->mGlyphsPerCharacter;
-
-  if( 0u == numberOfGlyphs )
-  {
-    modelGlyphs.Clear();
-    modelGlyphsToCharacters.Clear();
-    modelCharactersToGlyph.Clear();
-    modelCharactersPerGlyph.Clear();
-    modelGlyphsPerCharacter.Clear();
-  }
-  else
-  {
-    if( NULL != glyphs )
-    {
-      modelGlyphs.Resize( numberOfGlyphs );
-      memcpy( modelGlyphs.Begin(), glyphs, numberOfGlyphs * sizeof( GlyphInfo ) );
-    }
-
-    if( NULL != characterIndices )
-    {
-      modelGlyphsToCharacters.Resize( numberOfGlyphs );
-      memcpy( modelGlyphsToCharacters.Begin(), characterIndices, numberOfGlyphs * sizeof( CharacterIndex ) );
-    }
-
-    if( NULL != charactersPerGlyph )
-    {
-      modelCharactersPerGlyph.Resize( numberOfGlyphs );
-      memcpy( modelCharactersPerGlyph.Begin(), charactersPerGlyph, numberOfGlyphs * sizeof( Length ) );
-
-      // Build the characters to glyph conversion table.
-
-      // 1) Reserve some space for the characters to avoid reallocations.
-      const Length numberOfCharacters = static_cast<Length> ( static_cast<float>( numberOfGlyphs ) * 1.3f );
-      modelCharactersToGlyph.Reserve( numberOfCharacters );
-      modelGlyphsPerCharacter.Reserve( numberOfCharacters );
-
-      // 2) Traverse the glyphs and set the glyph indices and the glyphs per character.
-
-      // The number of 'characters per glyph' equal to zero.
-      Length zeroCharactersPerGlyph = 0u;
-
-      // Index to the glyph.
-      GlyphIndex glyphIndex = 0u;
-      for( Vector<Length>::ConstIterator it = modelCharactersPerGlyph.Begin(),
-             endIt = modelCharactersPerGlyph.End();
-           it != endIt;
-           ++it, ++glyphIndex )
-      {
-        const Length numberOfCharacters = *it;
-
-        // Set the glyph indices.
-        for( Length index = 0u; index < numberOfCharacters; ++index )
-        {
-          modelCharactersToGlyph.PushBack( glyphIndex );
-        }
-
-        // Set the glyphs per character.
-        if( 0u == numberOfCharacters )
-        {
-          ++zeroCharactersPerGlyph;
-        }
-        else
-        {
-          const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharacters - 1u );
-          for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex )
-          {
-            modelGlyphsPerCharacter.PushBack( 0u );
-          }
-
-          modelGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph );
-
-          zeroCharactersPerGlyph = 0u;
-        }
-      }
-    }
-  }
-}
-
-Length VisualModel::GetNumberOfGlyphs() const
-{
-  return mImpl->mGlyphs.Count();
-}
-
-void VisualModel::GetGlyphs( GlyphInfo* glyphs,
-                             GlyphIndex glyphIndex,
-                             Length numberOfGlyphs ) const
-{
-  const Vector<GlyphInfo>& modelGlyphs = mImpl->mGlyphs;
-  memcpy( glyphs, modelGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) );
-}
-
-const GlyphInfo& VisualModel::GetGlyphInfo( GlyphIndex glyphIndex ) const
-{
-  return mImpl->mGlyphs[glyphIndex];
-}
-
-void VisualModel::ReplaceGlyphs( GlyphIndex glyphIndex,
-                                 Length numberOfGlyphsToRemove,
-                                 const GlyphInfo* const glyphs,
-                                 const Length* const numberOfCharacters,
-                                 Length numberOfGlyphsToInsert )
-{
-}
-
-CharacterIndex VisualModel::GetCharacterIndex( GlyphIndex glyphIndex ) const
-{
-  return mImpl->mGlyphsToCharacters[glyphIndex];
-}
-
-Length VisualModel::GetCharactersPerGlyph( GlyphIndex glyphIndex ) const
-{
-  return mImpl->mCharactersPerGlyph[glyphIndex];
-}
-
-GlyphIndex VisualModel::GetGlyphIndex( CharacterIndex characterIndex ) const
-{
-  return mImpl->mCharactersToGlyph[characterIndex];
-}
-
-void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap,
-                                          CharacterIndex characterIndex,
-                                          Length numberOfCharacters ) const
-{
-  const Vector<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
-  memcpy( characterToGlyphMap, modelCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) );
-}
-
-void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
-                                          GlyphIndex glyphIndex,
-                                          Length numberOfGlyphs ) const
-{
-  const Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
-  memcpy( glyphToCharacter, modelGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) );
-}
-
-void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph,
-                                            GlyphIndex glyphIndex,
-                                            Length numberOfGlyphs ) const
-{
-  const Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
-  memcpy( charactersPerGlyph, modelCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) );
-}
-
-void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter,
-                                            CharacterIndex characterIndex,
-                                            Length numberOfCharacters ) const
-{
-  const Vector<Length>& modelGlyphsPerCharacter = mImpl->mGlyphsPerCharacter;
-  memcpy( glyphsPerCharacter, modelGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) );
-}
-
-void VisualModel::SetGlyphPositions( const Vector2* glyphPositions,
-                                     Length numberOfGlyphs )
-{
-  Vector<Vector2>& modelPositions = mImpl->mGlyphPositions;
-  if( 0u == numberOfGlyphs )
-  {
-    modelPositions.Clear();
-  }
-  else
-  {
-    modelPositions.Resize( numberOfGlyphs );
-    memcpy( modelPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) );
-  }
-}
-
-Length VisualModel::GetNumberOfGlyphPositions() const
-{
-  return mImpl->mGlyphPositions.Count();
-}
-
-void VisualModel::GetGlyphPositions( Vector2* glyphPositions,
-                                     GlyphIndex glyphIndex,
-                                     Length numberOfGlyphs ) const
-{
-  const Vector<Vector2>& modelPositions = mImpl->mGlyphPositions;
-  memcpy( glyphPositions, modelPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) );
-}
-
-const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const
-{
-  return *( mImpl->mGlyphPositions.Begin() + glyphIndex );
-}
-
-void VisualModel::ReplaceGlyphPositions( GlyphIndex glyphIndex,
-                                         Length numberOfGlyphsToRemove,
-                                         const Vector2* const positions,
-                                         Length numberOfGlyphsToInsert )
-{
-}
-
-void VisualModel::SetLines( const LineRun* const lines,
-                            Length numberOfLines )
-{
-  Vector<LineRun>& modelLines = mImpl->mLines;
-  GetLineCache& lineCache = mImpl->mGetLineCache;
-
-  if( 0u == numberOfLines )
-  {
-    modelLines.Clear();
-  }
-  else
-  {
-    modelLines.Resize( numberOfLines );
-    memcpy( modelLines.Begin(), lines, numberOfLines * sizeof( LineRun ) );
-  }
-
-  // Clear the get line cache.
-  lineCache.glyphIndex = 0u;
-  lineCache.numberOfGlyphs = 0u;
-  lineCache.firstLine = 0u;
-  lineCache.numberOfLines = 0u;
-}
-
-Length VisualModel::GetNumberOfLines() const
-{
-  return mImpl->mLines.Count();
-}
-
-void VisualModel::GetLines( LineRun* lines,
-                            LineIndex lineIndex,
-                            Length numberOfLines ) const
-{
-  const Vector<LineRun>& modelLines = mImpl->mLines;
-  memcpy( lines, modelLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) );
-}
-
-Length VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
-                                      Length numberOfGlyphs ) const
-{
-  // If is likely the user query consecutively for the number of lines with the same
-  // glyph index and number of glyphs, use the cache could be considered.
-  GetLineCache& lineCache = mImpl->mGetLineCache;
-
-  // Cache the glyph index and number of glyphs to be used in the GetLinesOfGlyphRange().
-  lineCache.glyphIndex = glyphIndex;
-  lineCache.numberOfGlyphs = numberOfGlyphs;
-
-  // Check first if the query is for the total number of glyphs.
-  const Length totalNumberOfGlyphs = mImpl->mGlyphs.Count();
-
-  if( ( 0u == glyphIndex ) &&
-      ( totalNumberOfGlyphs == numberOfGlyphs ) )
-  {
-    lineCache.firstLine = 0u;
-    lineCache.numberOfLines = mImpl->mLines.Count();
-
-    return lineCache.numberOfLines;
-  }
-
-  // Initialize the number of lines and the first line.
-  lineCache.numberOfLines = 0u;
-  lineCache.firstLine = 0u;
-  bool firstLineFound = false;
-
-  const Vector<LineRun>& modelLines = mImpl->mLines;
-  const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
-
-  // Traverse the lines and count those lines within the range of glyphs.
-  for( Vector<LineRun>::ConstIterator it = modelLines.Begin(),
-         endIt = modelLines.End();
-       it != endIt;
-       ++it )
-  {
-    const LineRun& line = *it;
-
-    if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) &&
-        ( lastGlyphIndex > line.glyphIndex ) )
-    {
-      firstLineFound = true;
-      ++lineCache.numberOfLines;
-    }
-    else if( lastGlyphIndex <= line.glyphIndex )
-    {
-      // nothing else to do.
-      break;
-    }
-
-    if( !firstLineFound )
-    {
-      ++lineCache.firstLine;
-    }
-  }
-
-  return lineCache.numberOfLines;
-}
-
-void VisualModel::GetLinesOfGlyphRange( LineRun* lines,
-                                        GlyphIndex glyphIndex,
-                                        Length numberOfGlyphs ) const
-{
-  const Vector<LineRun>& modelLines = mImpl->mLines;
-  GetLineCache& lineCache = mImpl->mGetLineCache;
-
-  if( ( glyphIndex != lineCache.glyphIndex ) ||
-      ( numberOfGlyphs != lineCache.numberOfGlyphs ) )
-  {
-    GetNumberOfLines( glyphIndex,
-                      numberOfGlyphs );
-  }
-
-  memcpy( lines, modelLines.Begin() + lineCache.firstLine, lineCache.numberOfLines * sizeof( LineRun ) );
-}
-
-void VisualModel::ReplaceLines( GlyphIndex glyphIndex,
-                                Length numberOfGlyphsToRemove,
-                                const LineRun* const lines,
-                                Length numberOfGlyphsToInsert )
-{
-}
-
-void VisualModel::SetNaturalSize( const Vector2& size  )
-{
-  mImpl->mNaturalSize = size;
-}
-
-const Vector2& VisualModel::GetNaturalSize() const
-{
-  return mImpl->mNaturalSize;
-}
-
-void VisualModel::SetActualSize( const Vector2& size )
-{
-  mImpl->mActualSize = size;
-}
-
-const Vector2& VisualModel::GetActualSize() const
-{
-  return mImpl->mActualSize;
-}
-
-VisualModel::~VisualModel()
-{
-  delete mImpl;
-}
-
-VisualModel::VisualModel()
-: mImpl( NULL )
-{
-  mImpl = new VisualModel::Impl();
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
index 398ae2e..6993797 100644 (file)
@@ -39,9 +39,9 @@ distributing this software or its derivatives.
     },
     "textfield":
     {
-      "font-family":"DejaVuSans",
+      "font-family":"UbuntuMono",
       "font-style":"Regular",
-      "point-size":10
+      "point-size":13
     },
     "scrollview":
     {