Internal text model inteface. 43/36943/6
authorVictor Cebollada <v.cebollada@samsung.com>
Tue, 17 Mar 2015 14:10:09 +0000 (14:10 +0000)
committerVictor Cebollada <v.cebollada@samsung.com>
Tue, 17 Mar 2015 15:01:51 +0000 (15:01 +0000)
Modify the internal interface of the text's logical and visual
model to access the data directly without copying it.

Change-Id: I3de4509653c473cf03c70c96474dd78bcd3aaa50
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
12 files changed:
dali-toolkit/internal/file.list
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]

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/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 \
    $(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/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 \
    $(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 \
  */
 
 // CLASS HEADER
  */
 
 // CLASS HEADER
-#include <dali-toolkit/internal/text/logical-model.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
 
 // EXTERNAL INCLUDES
 #include <memory.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
 {
 
 namespace Dali
 {
 
@@ -35,36 +29,6 @@ namespace Toolkit
 
 namespace Text
 {
 
 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()
 {
 
 LogicalModelPtr LogicalModel::New()
 {
@@ -74,35 +38,32 @@ LogicalModelPtr LogicalModel::New()
 void LogicalModel::SetText( const Character* const text,
                             Length numberOfCharacters )
 {
 void LogicalModel::SetText( const Character* const text,
                             Length numberOfCharacters )
 {
-  Vector<Character>& modelText = mImpl->mText;
-
   if( 0u == numberOfCharacters )
   {
   if( 0u == numberOfCharacters )
   {
-    modelText.Clear();
+    mText.Clear();
   }
   else
   {
   }
   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
 {
   }
 }
 
 Length LogicalModel::GetNumberOfCharacters() const
 {
-  return mImpl->mText.Count();
+  return mText.Count();
 }
 
 void LogicalModel::GetText( Character* text,
                             CharacterIndex characterIndex,
                             Length numberOfCharacters ) const
 {
 }
 
 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
 {
 }
 
 Character LogicalModel::GetCharacter( CharacterIndex characterIndex ) const
 {
-  return mImpl->mText[characterIndex];
+  return mText[characterIndex];
 }
 
 void LogicalModel::ReplaceText( CharacterIndex characterIndex,
 }
 
 void LogicalModel::ReplaceText( CharacterIndex characterIndex,
@@ -115,52 +76,32 @@ void LogicalModel::ReplaceText( CharacterIndex characterIndex,
 void LogicalModel::SetScripts( const ScriptRun* const scripts,
                                Length numberOfRuns )
 {
 void LogicalModel::SetScripts( const ScriptRun* const scripts,
                                Length numberOfRuns )
 {
-  Vector<ScriptRun>& scriptRuns = mImpl->mScriptRuns;
-
   if( 0u == numberOfRuns )
   {
   if( 0u == numberOfRuns )
   {
-    scriptRuns.Clear();
+    mScriptRuns.Clear();
   }
   else
   {
   }
   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.
   // 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;
 
   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.
   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 )
   {
        it != endIt;
        ++it )
   {
@@ -170,7 +111,7 @@ Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex,
         ( lastCharacterIndex > script.characterRun.characterIndex ) )
     {
       firstScriptFound = true;
         ( lastCharacterIndex > script.characterRun.characterIndex ) )
     {
       firstScriptFound = true;
-      ++scriptCache.numberOfRuns;
+      ++numberOfScriptRuns;
     }
     else if( lastCharacterIndex <= script.characterRun.characterIndex )
     {
     }
     else if( lastCharacterIndex <= script.characterRun.characterIndex )
     {
@@ -180,37 +121,33 @@ Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex,
 
     if( !firstScriptFound )
     {
 
     if( !firstScriptFound )
     {
-      ++scriptCache.firstRun;
+      ++firstScriptRun;
     }
   }
     }
   }
-
-  return scriptCache.numberOfRuns;
 }
 
 void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns,
                                   CharacterIndex characterIndex,
                                   Length numberOfCharacters ) const
 {
 }
 
 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.
 
 }
 
 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 ) )
 
     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 )
 {
 void LogicalModel::SetFonts( const FontRun* const fonts,
                              Length numberOfRuns )
 {
-  Vector<FontRun>& fontRuns = mImpl->mFontRuns;
-
   if( 0u == numberOfRuns )
   {
   if( 0u == numberOfRuns )
   {
-    fontRuns.Clear();
+    mFontRuns.Clear();
   }
   else
   {
   }
   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.
   // 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;
 
   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.
   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 )
   {
        it != endIt;
        ++it )
   {
@@ -287,7 +204,7 @@ Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex,
         ( characterIndex + numberOfCharacters > font.characterRun.characterIndex ) )
     {
       firstFontFound = true;
         ( characterIndex + numberOfCharacters > font.characterRun.characterIndex ) )
     {
       firstFontFound = true;
-      ++fontCache.numberOfRuns;
+      ++numberOfFontRuns;
     }
     else if( lastCharacterIndex <= font.characterRun.characterIndex )
     {
     }
     else if( lastCharacterIndex <= font.characterRun.characterIndex )
     {
@@ -297,35 +214,31 @@ Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex,
 
     if( !firstFontFound )
     {
 
     if( !firstFontFound )
     {
-      ++fontCache.firstRun;
+      ++firstFontRun;
     }
   }
     }
   }
-
-  return fontCache.numberOfRuns;
 }
 
 void LogicalModel::GetFontRuns( FontRun* fontRuns,
                                 CharacterIndex characterIndex,
                                 Length numberOfCharacters ) const
 {
 }
 
 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
 {
 }
 
 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 ) )
 
     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 )
 {
 void LogicalModel::SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo,
                                      Length length )
 {
-  Vector<LineBreakInfo>& modelLineBreakInfo = mImpl->mLineBreakInfo;
-
   if( 0u == length )
   {
   if( 0u == length )
   {
-    modelLineBreakInfo.Clear();
+    mLineBreakInfo.Clear();
   }
   else
   {
   }
   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
 {
                                      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
 {
 }
 
 LineBreakInfo LogicalModel::GetLineBreakInfo( CharacterIndex characterIndex ) const
 {
-  return *( mImpl->mLineBreakInfo.Begin() + characterIndex );
+  return *( mLineBreakInfo.Begin() + characterIndex );
 }
 
 void LogicalModel::ReplaceLineBreakInfo( CharacterIndex characterIndex,
 }
 
 void LogicalModel::ReplaceLineBreakInfo( CharacterIndex characterIndex,
@@ -382,16 +293,14 @@ void LogicalModel::ReplaceLineBreakInfo( CharacterIndex characterIndex,
 void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo,
                                      Length length )
 {
 void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo,
                                      Length length )
 {
-  Vector<WordBreakInfo>& modelWordBreakInfo = mImpl->mWordBreakInfo;
-
   if( 0u == length )
   {
   if( 0u == length )
   {
-    modelWordBreakInfo.Clear();
+    mWordBreakInfo.Clear();
   }
   else
   {
   }
   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
 {
                                      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
 {
 }
 
 WordBreakInfo LogicalModel::GetWordBreakInfo( CharacterIndex characterIndex ) const
 {
-  return *( mImpl->mWordBreakInfo.Begin() + characterIndex );
+  return *( mWordBreakInfo.Begin() + characterIndex );
 }
 
 void LogicalModel::ReplaceWordBreakInfo( CharacterIndex characterIndex,
 }
 
 void LogicalModel::ReplaceWordBreakInfo( CharacterIndex characterIndex,
@@ -417,51 +326,30 @@ void LogicalModel::ReplaceWordBreakInfo( CharacterIndex characterIndex,
 void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo,
                                          Length numberOfRuns )
 {
 void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo,
                                          Length numberOfRuns )
 {
-  Vector<BidirectionalParagraphInfoRun>& modelBidirectionalParagraphInfo = mImpl->mBidirectionalParagraphInfo;
-
   if( 0u == numberOfRuns )
   {
   if( 0u == numberOfRuns )
   {
-    modelBidirectionalParagraphInfo.Clear();
+    mBidirectionalParagraphInfo.Clear();
   }
   else
   {
   }
   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.
   // 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;
 
   bool firstParagraphFound = false;
 
-  const Vector<BidirectionalParagraphInfoRun>& modelBidirectionalParagraphInfo = mImpl->mBidirectionalParagraphInfo;
-
   // Traverse the bidirectional paragraph info and count those bidi paragraphs within the range of characters.
   // 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 )
   {
        it != endIt;
        ++it )
   {
@@ -471,33 +359,29 @@ Length LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterI
         ( characterIndex + numberOfCharacters > bidi.characterRun.characterIndex ) )
     {
       firstParagraphFound = true;
         ( characterIndex + numberOfCharacters > bidi.characterRun.characterIndex ) )
     {
       firstParagraphFound = true;
-      ++bidiCache.numberOfRuns;
+      ++numberOfFontRuns;
     }
 
     if( !firstParagraphFound )
     {
     }
 
     if( !firstParagraphFound )
     {
-      ++bidiCache.firstRun;
+      ++firstBidirectionalRun;
     }
   }
     }
   }
-
-  return bidiCache.numberOfRuns;
 }
 
 void LogicalModel::GetBidirectionalInfo( BidirectionalParagraphInfoRun* bidirectionalInfo,
                                          CharacterIndex characterIndex,
                                          Length numberOfCharacters ) const
 {
 }
 
 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,
 }
 
 void ReplaceBidirectionalInfo( CharacterIndex characterIndex,
@@ -521,22 +405,19 @@ CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex character
 void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
                                           Length numberOfRuns )
 {
 void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
                                           Length numberOfRuns )
 {
-  Vector<CharacterIndex>& modelVisualToLogicalMap = mImpl->mVisualToLogicalMap;
-  Vector<CharacterIndex>& modelLogicalToVisualMap = mImpl->mLogicalToVisualMap;
-
   if( 0u == numberOfRuns )
   {
   if( 0u == numberOfRuns )
   {
-    modelVisualToLogicalMap.Clear();
-    modelLogicalToVisualMap.Clear();
+    mVisualToLogicalMap.Clear();
+    mLogicalToVisualMap.Clear();
   }
   else
   {
   }
   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 )
 
     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
 {
 
 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;
   }
 
   {
     // 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
 {
 }
 
 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;
   }
 
   {
     // 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
 {
 }
 
 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
 {
 }
 
 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()
 {
 }
 
 LogicalModel::~LogicalModel()
 {
-  delete mImpl;
 }
 
 LogicalModel::LogicalModel()
 }
 
 LogicalModel::LogicalModel()
-: mImpl( NULL )
 {
 {
-  mImpl = new LogicalModel::Impl();
 }
 
 } // namespace Text
 }
 
 } // 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.
 
 /*
  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 #include <dali/public-api/object/ref-object.h>
 
 // INTERNAL INCLUDES
 #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
 {
 
 namespace Dali
 {
@@ -134,17 +137,19 @@ public:
                    Length numberOfRuns );
 
   /**
                    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.
    *
    * 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.
 
   /**
    * Retrieves the script runs for the given range of characters.
@@ -201,17 +206,19 @@ public:
                  Length numberOfRuns );
 
   /**
                  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.
    *
    * 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.
 
   /**
    * Retrieves the font runs for the given range of characters.
@@ -405,7 +412,7 @@ public:
                              Length numberOfRuns );
 
   /**
                              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.
    *
    *
    * It may be zero if there is no right to left scripts.
    *
@@ -414,8 +421,10 @@ public:
    *
    * @return The number of bidirectional info runs.
    */
    *
    * @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.
 
   /**
    * Retrieves the bidirectional paragraph info runs for the given range of characters.
@@ -572,10 +581,18 @@ private:
   // Undefined
   LogicalModel& operator=( const LogicalModel& handle );
 
   // 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
 };
 
 } // namespace Text
@@ -584,4 +601,4 @@ private:
 
 } // namespace Dali
 
 
 } // 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/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>
 #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>
 
 // 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/script-run.h>
-#include <dali-toolkit/internal/text/visual-model.h>
+#include <dali-toolkit/internal/text/visual-model-impl.h>
 
 namespace Dali
 {
 
 namespace Dali
 {
index a203e03..24521a5 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/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-view.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-view.h>
-#include <dali-toolkit/internal/text/visual-model.h>
+#include <dali-toolkit/internal/text/visual-model-impl.h>
 
 using std::vector;
 
 
 using std::vector;
 
@@ -309,14 +309,10 @@ struct Controller::TextInput
       return;
     }
 
       return;
     }
 
-    Vector<GlyphInfo> glyphs;
-    glyphs.Resize( numberOfGlyphs );
-    mVisualModel->GetGlyphs( glyphs.Begin(), 0, numberOfGlyphs );
+    Vector<GlyphInfo>& glyphs = mVisualModel->mGlyphs;
     const GlyphInfo* const glyphsBuffer = glyphs.Begin();
 
     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;
     const Vector2* const positionsBuffer = positions.Begin();
 
     unsigned int closestGlyph = 0;
@@ -615,6 +611,92 @@ bool Controller::GetEnableCursorBlink() const
   return false;
 }
 
   return false;
 }
 
+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 );
+    // Make sure the model is up-to-date before layouting
+    ReplaceText( 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 )
+{
+  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
+    ReplaceText( 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 Controller::Relayout( const Vector2& size )
 {
   if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
@@ -636,8 +718,6 @@ bool Controller::Relayout( const Vector2& size )
     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
                                                              LAYOUT                    |
                                                              UPDATE_ACTUAL_SIZE        |
     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
                                                              LAYOUT                    |
                                                              UPDATE_ACTUAL_SIZE        |
-                                                             UPDATE_POSITIONS          |
-                                                             UPDATE_LINES              |
                                                              REORDER );
 
     mImpl->mControlSize = size;
                                                              REORDER );
 
     mImpl->mControlSize = size;
@@ -668,8 +748,7 @@ void Controller::ReplaceText( OperationsMask operationsRequired )
   // Calculate the operations to be done.
   const OperationsMask operations = static_cast<OperationsMask>( mImpl->mOperationsPending & operationsRequired );
 
   // Calculate the operations to be done.
   const OperationsMask operations = static_cast<OperationsMask>( mImpl->mOperationsPending & operationsRequired );
 
-  Vector<Character> utf32Characters;
-  Length characterCount = 0u;
+  Vector<Character>& utf32Characters = mImpl->mLogicalModel->mText;
   if( CONVERT_TO_UTF32 & operations )
   {
     std::string& text = mImpl->mNewText;
   if( CONVERT_TO_UTF32 & operations )
   {
     std::string& text = mImpl->mNewText;
@@ -682,50 +761,43 @@ void Controller::ReplaceText( OperationsMask operationsRequired )
 
     // Transform a text array encoded in utf8 into an array encoded in utf32.
     // It returns the actual number of characters.
 
     // 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() );
+    const Length characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() );
     utf32Characters.Resize( characterCount );
 
     utf32Characters.Resize( characterCount );
 
-    // Sets the text into the model.
-    mImpl->mLogicalModel->SetText( utf32Characters.Begin(), characterCount );
-
     // Discard temporary text
     text.clear();
   }
 
   const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
 
     // Discard temporary text
     text.clear();
   }
 
   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).
   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 );
 
     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).
   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 );
 
     SetWordBreakInfo( utf32Characters,
                       wordBreakInfo );
-
-    mImpl->mLogicalModel->SetWordBreakInfo( wordBreakInfo.Begin(), characterCount );
   }
 
   const bool getScripts = GET_SCRIPTS & operations;
   const bool validateFonts = VALIDATE_FONTS & operations;
 
   }
 
   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 )
   {
 
   if( getScripts || validateFonts )
   {
@@ -739,68 +811,34 @@ void Controller::ReplaceText( OperationsMask operationsRequired )
       multilanguageSupport.SetScripts( utf32Characters,
                                        lineBreakInfo,
                                        scripts );
       multilanguageSupport.SetScripts( utf32Characters,
                                        lineBreakInfo,
                                        scripts );
-
-      // Sets the scripts into the model.
-      mImpl->mLogicalModel->SetScripts( scripts.Begin(), scripts.Count() );
     }
 
     if( validateFonts )
     {
     }
 
     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 );
 
       // 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() );
     }
   }
 
   if( BIDI_INFO & operations )
   {
     }
   }
 
   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();
     // 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 ) )
       {
     {
       if( TextAbstraction::LINE_NO_BREAK == *( lineBreakInfoBuffer + index ) )
       {
@@ -808,7 +846,7 @@ void Controller::ReplaceText( OperationsMask operationsRequired )
       }
     }
 
       }
     }
 
-    Vector<BidirectionalParagraphInfoRun> bidirectionalInfo;
+    Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo;
     bidirectionalInfo.Reserve( numberOfParagraphs );
 
     // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
     bidirectionalInfo.Reserve( numberOfParagraphs );
 
     // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
@@ -816,25 +854,13 @@ void Controller::ReplaceText( OperationsMask operationsRequired )
                           scripts,
                           lineBreakInfo,
                           bidirectionalInfo );
                           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( 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,
     // Shapes the text.
     ShapeText( utf32Characters,
                lineBreakInfo,
@@ -845,19 +871,18 @@ void Controller::ReplaceText( OperationsMask operationsRequired )
                charactersPerGlyph );
   }
 
                charactersPerGlyph );
   }
 
+  const Length numberOfGlyphs = glyphs.Count();
+
   if( GET_GLYPH_METRICS & operations )
   {
   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 )
   {
   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 );
   }
 }
 
   }
 }
 
@@ -879,35 +904,11 @@ bool Controller::DoRelayout( const Vector2& size,
     const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
     Length numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
 
     const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
     Length numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
 
-    Vector<LineBreakInfo> lineBreakInfo;
-    lineBreakInfo.Resize( numberOfCharacters );
-    mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(),
-                                            0u,
-                                            numberOfCharacters );
-
-    Vector<WordBreakInfo> wordBreakInfo;
-    wordBreakInfo.Resize( numberOfCharacters );
-    mImpl->mLogicalModel->GetWordBreakInfo( wordBreakInfo.Begin(),
-                                            0u,
-                                            numberOfCharacters );
-
-    Vector<GlyphInfo> glyphs;
-    glyphs.Resize( numberOfGlyphs );
-    mImpl->mVisualModel->GetGlyphs( glyphs.Begin(),
-                                    0u,
-                                    numberOfGlyphs );
-
-    Vector<CharacterIndex> glyphsToCharactersMap;
-    glyphsToCharactersMap.Resize( numberOfGlyphs );
-    mImpl->mVisualModel->GetGlyphToCharacterMap( glyphsToCharactersMap.Begin(),
-                                                 0u,
-                                                 numberOfGlyphs );
-
-    Vector<Length> charactersPerGlyph;
-    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,
 
     // Set the layout parameters.
     LayoutParameters layoutParameters( size,
@@ -918,16 +919,23 @@ bool Controller::DoRelayout( const Vector2& size,
                                        glyphsToCharactersMap.Begin(),
                                        charactersPerGlyph.Begin() );
 
                                        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.
     // 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,
 
     // Update the visual model.
     viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters,
@@ -940,13 +948,7 @@ bool Controller::DoRelayout( const Vector2& size,
       // Reorder the lines
       if( REORDER & operations )
       {
       // Reorder the lines
       if( REORDER & operations )
       {
-        const Length numberOfBidiParagraphs = mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters );
-
-        Vector<BidirectionalParagraphInfoRun> bidirectionalInfo;
-        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() )
 
         // Check first if there are paragraphs with bidirectional info.
         if( 0u != bidirectionalInfo.Count() )
@@ -971,22 +973,10 @@ bool Controller::DoRelayout( const Vector2& size,
           layoutParameters.numberOfBidirectionalInfoRuns = numberOfBidirectionalInfoRuns;
 
           // Get the character to glyph conversion table and set into the layout.
           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.
 
           // 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,
 
           // Re-layout the text. Reorder those lines with right to left characters.
           mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters,
@@ -1005,20 +995,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 )
       {
       // Sets the actual size.
       if( UPDATE_ACTUAL_SIZE & operations )
       {
@@ -1034,92 +1010,6 @@ bool Controller::DoRelayout( const Vector2& size,
   return viewUpdated;
 }
 
   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 );
-    // Make sure the model is up-to-date before layouting
-    ReplaceText( 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 )
-{
-  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
-    ReplaceText( 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;
-}
-
 View& Controller::GetView()
 {
   return mImpl->mView;
 View& Controller::GetView()
 {
   return mImpl->mView;
index ee77ca3..46bf38f 100644 (file)
@@ -77,11 +77,9 @@ private:
     GET_GLYPH_METRICS  = 0x0080,
     LAYOUT             = 0x0100,
     UPDATE_ACTUAL_SIZE = 0x0200,
     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
   };
 
     ALL_OPERATIONS     = 0xFFFF
   };
 
@@ -198,6 +196,16 @@ public:
   bool GetEnableCursorBlink() const;
 
   /**
   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.
    * @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.
@@ -227,16 +235,6 @@ public:
                    Size& layoutSize );
 
   /**
                    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.
    * @brief Return the layout engine.
    *
    * @return A reference to the layout engine.
index d991384..6f00b7b 100644 (file)
@@ -33,23 +33,26 @@ namespace Toolkit
 namespace Text
 {
 
 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
 
 
 } // namespace Text
 
index c3d033e..56ce0be 100644 (file)
@@ -20,7 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/text-view-interface.h>
 
 // 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
 {
 
 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.
 
 /*
  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
  */
 
 // EXTERNAL INCLUDES
  */
 
 // 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/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
 {
 
 namespace Dali
 {
@@ -77,6 +78,20 @@ public:
                   Length numberOfGlyphs );
 
   /**
                   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.
    * Retrieves the number of glyphs.
    *
    * @return The number of glyphs.
@@ -296,15 +311,17 @@ public:
                  Length numberOfLines ) const;
 
   /**
                  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.
    *
    * @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.
    *
   /**
    * Retrieves the lines where the given range of glyphs is laid out.
    *
@@ -384,15 +401,26 @@ private:
   // Undefined
   VisualModel& operator=( const VisualModel& handle );
 
   // 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:
 
 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
 
 } // 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