Refactor TextLabel to use text visual
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / visual-model-impl.cpp
index 561beee..1b114c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 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.
@@ -35,29 +35,50 @@ VisualModelPtr VisualModel::New()
   return VisualModelPtr( new VisualModel() );
 }
 
-void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters )
+void VisualModel::CreateCharacterToGlyphTable( CharacterIndex startIndex,
+                                               GlyphIndex startGlyphIndex,
+                                               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 );
+    // Nothing to do.
+    return;
   }
-  mCharactersToGlyph.Reserve( numberOfCharacters );
 
-  DALI_ASSERT_DEBUG( mGlyphsPerCharacter.Count() != 0u ||
-                     ( 0u == numberOfCharacters ) );
+  DALI_ASSERT_DEBUG( mGlyphsPerCharacter.Count() != 0u );
+
+  // Get the total number of characters.
+  const Length totalNumberOfCharacters = ( 0u == mGlyphsToCharacters.Count() ) ? 0u : *( mGlyphsToCharacters.End() - 1u ) + *( mCharactersPerGlyph.End() - 1u ); // Index to the first character + the number of characters that form the last glyph.
+
+  // Whether the current buffer is being updated or is set from scratch.
+  const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters;
+
+  Vector<GlyphIndex> newCharactersToGlyph;
+  GlyphIndex* charactersToGlyphBuffer = NULL;
+
+  // 1) Reserve some space for the glyph indices to avoid reallocations.
+  if( updateCurrentBuffer )
+  {
+    newCharactersToGlyph.Resize( numberOfCharacters );
+    charactersToGlyphBuffer = newCharactersToGlyph.Begin();
+  }
+  else
+  {
+    mCharactersToGlyph.Resize( numberOfCharacters );
+    charactersToGlyphBuffer = mCharactersToGlyph.Begin() + startIndex;
+  }
 
   const Length* const glyphsPerCharacterBuffer = mGlyphsPerCharacter.Begin();
 
   // 2) Traverse the glyphs and set the glyph indices per character.
 
   // Index to the glyph.
-  GlyphIndex glyphIndex = 0u;
-  CharacterIndex characterIndex = 0u;
-  for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin(),
+  GlyphIndex glyphIndex = startGlyphIndex;
+  CharacterIndex characterIndex = startIndex;
+  const CharacterIndex lastCharacterIndexPlusOne = startIndex + numberOfCharacters;
+  for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin() + glyphIndex,
          endIt = mCharactersPerGlyph.End();
-       it != endIt;
+       ( it != endIt ) && ( characterIndex < lastCharacterIndexPlusOne );
        ++it )
   {
     const Length numberOfCharactersPerGlyph = *it;
@@ -66,34 +87,78 @@ void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters )
     // Set the glyph indices.
     for( Length index = 0u; index < numberOfCharactersPerGlyph; ++index, ++characterIndex )
     {
-      mCharactersToGlyph.PushBack( glyphIndex );
+      *charactersToGlyphBuffer = glyphIndex;
       numberOfGlyphs += *( glyphsPerCharacterBuffer + characterIndex );
+      ++charactersToGlyphBuffer;
     }
     glyphIndex += numberOfGlyphs;
   }
+
+  // If the character to glyph buffer is updated, it needs to be inserted in the model.
+  if( updateCurrentBuffer )
+  {
+    // Update the indices.
+    const Length numberOfGlyphs = glyphIndex - startGlyphIndex;
+    for( Vector<Length>::Iterator it = mCharactersToGlyph.Begin() + startIndex,
+           endIt = mCharactersToGlyph.End();
+         it != endIt;
+         ++it )
+    {
+      *it += numberOfGlyphs;
+    }
+
+    mCharactersToGlyph.Insert( mCharactersToGlyph.Begin() + startIndex,
+                               newCharactersToGlyph.Begin(),
+                               newCharactersToGlyph.End() );
+
+  }
 }
 
-void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters )
+void VisualModel::CreateGlyphsPerCharacterTable( CharacterIndex startIndex,
+                                                 GlyphIndex startGlyphIndex,
+                                                 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 );
+    // Nothing to do.
+    return;
+  }
+
+  // Get the total number of characters.
+  const Length totalNumberOfCharacters = ( 0u == mGlyphsToCharacters.Count() ) ? 0u : *( mGlyphsToCharacters.End() - 1u ) + *( mCharactersPerGlyph.End() - 1u ); // Index to the first character + the number of characters that form the last glyph.
+
+  // Whether the current buffer is being updated or is set from scratch.
+  const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters;
+
+  Vector<Length> newGlyphsPerCharacter;
+  Length* glyphsPerCharacterBuffer = NULL;
+
+  // 1) Reserve some space for the glyphs per character to avoid reallocations.
+  if( updateCurrentBuffer )
+  {
+    newGlyphsPerCharacter.Resize( numberOfCharacters );
+    glyphsPerCharacterBuffer = newGlyphsPerCharacter.Begin();
+  }
+  else
+  {
+    mGlyphsPerCharacter.Resize( numberOfCharacters );
+    glyphsPerCharacterBuffer = mGlyphsPerCharacter.Begin() + startIndex;
   }
-  mGlyphsPerCharacter.Reserve( numberOfCharacters );
 
   // 2) Traverse the glyphs and set the number of glyphs per character.
 
+  Length traversedCharacters = 0;
+
   // The number of 'characters per glyph' equal to zero.
   Length zeroCharactersPerGlyph = 0u;
 
-  for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin(),
+  for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin() + startGlyphIndex,
          endIt = mCharactersPerGlyph.End();
-       it != endIt;
+       ( it != endIt ) && ( traversedCharacters < numberOfCharacters );
        ++it )
   {
     const Length numberOfCharactersPerGlyph = *it;
+    traversedCharacters += numberOfCharactersPerGlyph;
 
     // Set the glyphs per character.
     if( 0u == numberOfCharactersPerGlyph )
@@ -103,16 +168,30 @@ void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters )
     else
     {
       const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharactersPerGlyph - 1u );
-      for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex )
+      for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter; ++zeroIndex )
       {
-        mGlyphsPerCharacter.PushBack( 0u );
+        *glyphsPerCharacterBuffer = 0u;
+
+        // Point to the next position in the buffer.
+        ++glyphsPerCharacterBuffer;
       }
 
-      mGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph );
+      *glyphsPerCharacterBuffer = zeroCharactersPerGlyph + 1u;
 
       zeroCharactersPerGlyph = 0u;
+
+      // Point to the next position in the buffer.
+      ++glyphsPerCharacterBuffer;
     }
   }
+
+  // If the glyphs per character buffer is updated, it needs to be inserted in the model.
+  if( updateCurrentBuffer )
+  {
+    mGlyphsPerCharacter.Insert( mGlyphsPerCharacter.Begin() + startIndex,
+                                newGlyphsPerCharacter.Begin(),
+                                newGlyphsPerCharacter.End() );
+  }
 }
 
 void VisualModel::GetGlyphs( GlyphInfo* glyphs,
@@ -235,14 +314,14 @@ const Vector2& VisualModel::GetNaturalSize() const
   return mNaturalSize;
 }
 
-void VisualModel::SetActualSize( const Vector2& size )
+void VisualModel::SetLayoutSize( const Vector2& size )
 {
-  mActualSize = size;
+  mLayoutSize = size;
 }
 
-const Vector2& VisualModel::GetActualSize() const
+const Vector2& VisualModel::GetLayoutSize() const
 {
-  return mActualSize;
+  return mLayoutSize;
 }
 
 void VisualModel::SetTextColor( const Vector4& textColor )
@@ -311,6 +390,11 @@ float VisualModel::GetUnderlineHeight() const
   return mUnderlineHeight;
 }
 
+Length VisualModel::GetNumberOfUnderlineRuns() const
+{
+  return mUnderlineRuns.Count();
+}
+
 void VisualModel::ClearCaches()
 {
   mCachedLineIndex = 0u;
@@ -331,10 +415,11 @@ VisualModel::VisualModel()
   mTextColor( Color::BLACK ),
   mShadowColor( Color::BLACK ),
   mUnderlineColor( Color::BLACK ),
-  mShadowOffset( Vector2::ZERO ),
+  mControlSize(),
+  mShadowOffset(),
   mUnderlineHeight( 0.0f ),
   mNaturalSize(),
-  mActualSize(),
+  mLayoutSize(),
   mCachedLineIndex( 0u ),
   mUnderlineEnabled( false ),
   mUnderlineColorSet( false )