[dali_2.3.24] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / visual-model-impl.cpp
index 74291b4..3fdd6b8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
 
 // 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() );
+  return VisualModelPtr(new VisualModel());
 }
 
-void VisualModel::SetGlyphs( const GlyphInfo* glyphs,
-                             const CharacterIndex* characterIndices,
-                             const Length* charactersPerGlyph,
-                             Length numberOfGlyphs )
+void VisualModel::CreateCharacterToGlyphTable(CharacterIndex startIndex,
+                                              GlyphIndex     startGlyphIndex,
+                                              Length         numberOfCharacters)
 {
-  if( 0u == numberOfGlyphs )
+  if(0u == numberOfCharacters)
   {
-    mGlyphs.Clear();
-    mGlyphsToCharacters.Clear();
-    mCharactersToGlyph.Clear();
-    mCharactersPerGlyph.Clear();
-    mGlyphsPerCharacter.Clear();
+    // Nothing to do.
+    return;
   }
-  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 ) );
-    }
+  DALI_ASSERT_DEBUG(mGlyphsPerCharacter.Count() != 0u);
 
-    if( NULL != charactersPerGlyph )
-    {
-      mCharactersPerGlyph.Resize( numberOfGlyphs );
-      memcpy( mCharactersPerGlyph.Begin(), charactersPerGlyph, numberOfGlyphs * sizeof( Length ) );
+  // 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.
 
-      // Build the glyphs per character table.
-      CreateGlyphsPerCharacterTable();
+  // Whether the current buffer is being updated or is set from scratch.
+  const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters;
 
-      // Build the characters to glyph conversion table.
-      CreateCharacterToGlyphTable();
-    }
-  }
-}
+  Vector<GlyphIndex> newCharactersToGlyph;
+  GlyphIndex*        charactersToGlyphBuffer = NULL;
 
-void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters )
-{
-  // 1) Reserve some space for the characters to avoid reallocations.
-  if( 0u == numberOfCharacters )
+  // 1) Reserve some space for the glyph indices to avoid reallocations.
+  if(updateCurrentBuffer)
   {
-    // 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 );
+    newCharactersToGlyph.Resize(numberOfCharacters);
+    charactersToGlyphBuffer = newCharactersToGlyph.Begin();
+  }
+  else
+  {
+    mCharactersToGlyph.Resize(numberOfCharacters);
+    charactersToGlyphBuffer = mCharactersToGlyph.Begin() + startIndex;
   }
-  mCharactersToGlyph.Reserve( numberOfCharacters );
-
-  DALI_ASSERT_DEBUG( mGlyphsPerCharacter.Count() != 0u ||
-                     ( 0u == numberOfCharacters ) );
 
   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(),
-         endIt = mCharactersPerGlyph.End();
-       it != endIt;
-       ++it )
+  GlyphIndex           glyphIndex                = startGlyphIndex;
+  CharacterIndex       characterIndex            = startIndex;
+  const CharacterIndex lastCharacterIndexPlusOne = startIndex + numberOfCharacters;
+  for(Vector<Length>::ConstIterator it    = mCharactersPerGlyph.Begin() + glyphIndex,
+                                    endIt = mCharactersPerGlyph.End();
+      (it != endIt) && (characterIndex < lastCharacterIndexPlusOne);
+      ++it)
   {
     const Length numberOfCharactersPerGlyph = *it;
 
     Length numberOfGlyphs = 0u;
     // Set the glyph indices.
-    for( Length index = 0u; index < numberOfCharactersPerGlyph; ++index, ++characterIndex )
+    for(Length index = 0u; index < numberOfCharactersPerGlyph; ++index, ++characterIndex)
     {
-      mCharactersToGlyph.PushBack( glyphIndex );
-      numberOfGlyphs += *( glyphsPerCharacterBuffer + characterIndex );
+      *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(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(),
-         endIt = mCharactersPerGlyph.End();
-       it != endIt;
-       ++it )
+  for(Vector<Length>::ConstIterator it    = mCharactersPerGlyph.Begin() + startGlyphIndex,
+                                    endIt = mCharactersPerGlyph.End();
+      (it != endIt) && (traversedCharacters < numberOfCharacters);
+      ++it)
   {
     const Length numberOfCharactersPerGlyph = *it;
+    traversedCharacters += numberOfCharactersPerGlyph;
 
     // Set the glyphs per character.
-    if( 0u == numberOfCharactersPerGlyph )
+    if(0u == numberOfCharactersPerGlyph)
     {
       ++zeroCharactersPerGlyph;
     }
     else
     {
-      const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharactersPerGlyph - 1u );
-      for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex )
+      const Length numberOfZeroGlyphsPerCharacter = (numberOfCharactersPerGlyph - 1u);
+      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());
+  }
 }
 
-Length VisualModel::GetNumberOfGlyphs() const
+void VisualModel::GetGlyphs(GlyphInfo* glyphs,
+                            GlyphIndex glyphIndex,
+                            Length     numberOfGlyphs) const
 {
-  return mGlyphs.Count();
+  memcpy(glyphs, mGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof(GlyphInfo));
 }
 
-void VisualModel::GetGlyphs( GlyphInfo* glyphs,
-                             GlyphIndex glyphIndex,
-                             Length numberOfGlyphs ) const
+void VisualModel::GetGlyphPositions(Vector2*   glyphPositions,
+                                    GlyphIndex glyphIndex,
+                                    Length     numberOfGlyphs) const
 {
-  memcpy( glyphs, mGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) );
+  memcpy(glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof(Vector2));
 }
 
-const GlyphInfo& VisualModel::GetGlyphInfo( GlyphIndex glyphIndex ) const
+Length VisualModel::GetTotalNumberOfLines() const
 {
-  return mGlyphs[glyphIndex];
+  return mLines.Size();
 }
 
-void VisualModel::ReplaceGlyphs( GlyphIndex glyphIndex,
-                                 Length numberOfGlyphsToRemove,
-                                 const GlyphInfo* const glyphs,
-                                 const Length* const numberOfCharacters,
-                                 Length numberOfGlyphsToInsert )
+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.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs > glyphIndex) &&
+       (lastGlyphIndex > line.glyphRun.glyphIndex))
+    {
+      firstLineFound = true;
+      ++numberOfLines;
+    }
+    else if((line.glyphRunSecondHalf.glyphIndex + line.glyphRunSecondHalf.numberOfGlyphs > glyphIndex) &&
+            (lastGlyphIndex > line.glyphRunSecondHalf.glyphIndex))
+    {
+      firstLineFound = true;
+      ++numberOfLines;
+    }
+    else if(lastGlyphIndex <= line.glyphRun.glyphIndex)
+    {
+      // nothing else to do.
+      break;
+    }
+
+    if(!firstLineFound)
+    {
+      ++firstLine;
+    }
+  }
 }
 
-CharacterIndex VisualModel::GetCharacterIndex( GlyphIndex glyphIndex ) const
+LineIndex VisualModel::GetLineOfGlyph( GlyphIndex glyphIndex )
 {
-  return mGlyphsToCharacters[glyphIndex];
+  const CharacterIndex characterIndex = *(mGlyphsToCharacters.Begin() + glyphIndex);
+  return GetLineOfCharacter(characterIndex);
 }
 
-Length VisualModel::GetCharactersPerGlyph( GlyphIndex glyphIndex ) const
+void VisualModel::GetLinesOfGlyphRange(LineRun*   lines,
+                                       GlyphIndex glyphIndex,
+                                       Length     numberOfGlyphs) const
 {
-  return mCharactersPerGlyph[glyphIndex];
+  LineIndex firstLine     = 0u;
+  Length    numberOfLines = 0u;
+
+  GetNumberOfLines(glyphIndex,
+                   numberOfGlyphs,
+                   firstLine,
+                   numberOfLines);
+
+  memcpy(lines, mLines.Begin() + firstLine, numberOfLines * sizeof(LineRun));
 }
 
-GlyphIndex VisualModel::GetGlyphIndex( CharacterIndex characterIndex ) const
+LineIndex VisualModel::GetLineOfCharacter(CharacterIndex characterIndex)
 {
-  return mCharactersToGlyph[characterIndex];
+  // 1) Check line is empty or not.
+  if(mLines.Empty())
+  {
+    return 0u;
+  }
+
+  // 2) Check in the cached line.
+  const LineRun& lineRun = *(mLines.Begin() + mCachedLineIndex);
+  if((lineRun.characterRun.characterIndex <= characterIndex) &&
+     (characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters))
+  {
+    return mCachedLineIndex;
+  }
+
+  // 3) Is not in the cached line. Check in the other lines.
+  LineIndex index = characterIndex < lineRun.characterRun.characterIndex ? 0u : mCachedLineIndex + 1u;
+
+  for(Vector<LineRun>::ConstIterator it    = mLines.Begin() + index,
+                                     endIt = mLines.End();
+      it != endIt;
+      ++it, ++index)
+  {
+    const LineRun& lineRun = *it;
+
+    if(characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters)
+    {
+      mCachedLineIndex = index;
+      break;
+    }
+  }
+
+  return index;
 }
 
-void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap,
-                                          CharacterIndex characterIndex,
-                                          Length numberOfCharacters ) const
+void VisualModel::GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns,
+                                   UnderlineRunIndex   index,
+                                   Length              numberOfRuns) const
 {
-  memcpy( characterToGlyphMap, mCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) );
+  memcpy(underlineRuns,
+         mUnderlineRuns.Begin() + index,
+         numberOfRuns * sizeof(UnderlinedGlyphRun));
 }
 
-void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
-                                          GlyphIndex glyphIndex,
-                                          Length numberOfGlyphs ) const
+void VisualModel::SetNaturalSize(const Vector2& size)
 {
-  memcpy( glyphToCharacter, mGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) );
+  mNaturalSize = size;
 }
 
-void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph,
-                                            GlyphIndex glyphIndex,
-                                            Length numberOfGlyphs ) const
+const Vector2& VisualModel::GetNaturalSize() const
 {
-  memcpy( charactersPerGlyph, mCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) );
+  return mNaturalSize;
 }
 
-void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter,
-                                            CharacterIndex characterIndex,
-                                            Length numberOfCharacters ) const
+void VisualModel::SetLayoutSize(const Vector2& size)
 {
-  memcpy( glyphsPerCharacter, mGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) );
+  mLayoutSize = size;
 }
 
-void VisualModel::SetGlyphPositions( const Vector2* glyphPositions,
-                                     Length numberOfGlyphs )
+const Vector2& VisualModel::GetLayoutSize() const
 {
-  if( 0u == numberOfGlyphs )
-  {
-    mGlyphPositions.Clear();
-  }
-  else
+  return mLayoutSize;
+}
+
+void VisualModel::SetHeightForWidth(const Vector2& size)
+{
+  mHeightForWidth = size;
+}
+
+const Vector2& VisualModel::GetHeightForWidth() const
+{
+  return mHeightForWidth;
+}
+
+void VisualModel::SetTextColor(const Vector4& textColor)
+{
+  mTextColor = textColor;
+
+  if(!mUnderlineColorSet)
   {
-    mGlyphPositions.Resize( numberOfGlyphs );
-    memcpy( mGlyphPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) );
+    mUnderlineColor = textColor;
   }
 }
 
-Length VisualModel::GetNumberOfGlyphPositions() const
+void VisualModel::SetShadowOffset(const Vector2& shadowOffset)
 {
-  return mGlyphPositions.Count();
+  mShadowOffset = shadowOffset;
 }
 
-void VisualModel::GetGlyphPositions( Vector2* glyphPositions,
-                                     GlyphIndex glyphIndex,
-                                     Length numberOfGlyphs ) const
+void VisualModel::SetShadowColor(const Vector4& shadowColor)
 {
-  memcpy( glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) );
+  mShadowColor = shadowColor;
 }
 
-const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const
+void VisualModel::SetShadowBlurRadius(const float& shadowBlurRadius)
 {
-  return *( mGlyphPositions.Begin() + glyphIndex );
+  mShadowBlurRadius = shadowBlurRadius;
 }
 
-void VisualModel::ReplaceGlyphPositions( GlyphIndex glyphIndex,
-                                         Length numberOfGlyphsToRemove,
-                                         const Vector2* const positions,
-                                         Length numberOfGlyphsToInsert )
+void VisualModel::SetUnderlineColor(const Vector4& color)
 {
+  mUnderlineColor    = color;
+  mUnderlineColorSet = true;
 }
 
-void VisualModel::SetLines( const LineRun* const lines,
-                            Length numberOfLines )
+void VisualModel::SetOutlineOffset(const Vector2& outlineOffset)
 {
-  if( 0u == numberOfLines )
-  {
-    mLines.Clear();
-  }
-  else
-  {
-    mLines.Resize( numberOfLines );
-    memcpy( mLines.Begin(), lines, numberOfLines * sizeof( LineRun ) );
-  }
+  mOutlineOffset = outlineOffset;
 }
 
-Length VisualModel::GetNumberOfLines() const
+void VisualModel::SetOutlineColor(const Vector4& color)
 {
-  return mLines.Count();
+  mOutlineColor = color;
 }
 
-void VisualModel::GetLines( LineRun* lines,
-                            LineIndex lineIndex,
-                            Length numberOfLines ) const
+void VisualModel::SetOutlineBlurRadius(const float& outlineBlurRadius)
 {
-  memcpy( lines, mLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) );
+  mOutlineBlurRadius = outlineBlurRadius;
 }
 
-void VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
-                                    Length numberOfGlyphs,
-                                    LineIndex& firstLine,
-                                    Length& numberOfLines ) const
+void VisualModel::SetUnderlineEnabled(bool enabled)
 {
-  // Initialize the number of lines and the first line.
-  firstLine = 0u;
-  numberOfLines = 0u;
-  bool firstLineFound = false;
+  mUnderlineEnabled = enabled;
+}
 
-  const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
+void VisualModel::SetUnderlineHeight(float height)
+{
+  mUnderlineHeight = height;
+}
 
-  // 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;
+void VisualModel::SetUnderlineType(Text::Underline::Type type)
+{
+  mUnderlineType = type;
+}
 
-    if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) &&
-        ( lastGlyphIndex > line.glyphIndex ) )
-    {
-      firstLineFound = true;
-      ++numberOfLines;
-    }
-    else if( lastGlyphIndex <= line.glyphIndex )
-    {
-      // nothing else to do.
-      break;
-    }
+void VisualModel::SetDashedUnderlineWidth(float width)
+{
+  mDashedUnderlineWidth = width;
+}
 
-    if( !firstLineFound )
-    {
-      ++firstLine;
-    }
-  }
+void VisualModel::SetDashedUnderlineGap(float gap)
+{
+  mDashedUnderlineGap = gap;
 }
 
-void VisualModel::GetLinesOfGlyphRange( LineRun* lines,
-                                        GlyphIndex glyphIndex,
-                                        Length numberOfGlyphs ) const
+void VisualModel::SetOutlineWidth(uint16_t width)
 {
-  LineIndex firstLine = 0u;
-  Length numberOfLines = 0u;
+  mOutlineWidth = width;
+}
 
-  GetNumberOfLines( glyphIndex,
-                    numberOfGlyphs,
-                    firstLine,
-                    numberOfLines );
+void VisualModel::SetBackgroundColor(const Vector4& color)
+{
+  mBackgroundColor = color;
+}
 
-  memcpy( lines, mLines.Begin() + firstLine, numberOfLines * sizeof( LineRun ) );
+void VisualModel::SetBackgroundEnabled(bool enabled)
+{
+  mBackgroundEnabled = enabled;
 }
 
-void VisualModel::ReplaceLines( GlyphIndex glyphIndex,
-                                Length numberOfGlyphsToRemove,
-                                const LineRun* const lines,
-                                Length numberOfGlyphsToInsert )
+void VisualModel::SetMarkupProcessorEnabled(bool enabled)
 {
+  mMarkupProcessorEnabled = enabled;
 }
 
-void VisualModel::SetNaturalSize( const Vector2& size  )
+void VisualModel::SetTextElideEnabled(bool enabled)
 {
-  mNaturalSize = size;
+  mTextElideEnabled = enabled;
 }
 
-const Vector2& VisualModel::GetNaturalSize() const
+void VisualModel::SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition)
 {
-  return mNaturalSize;
+  mEllipsisPosition = ellipsisPosition;
+}
+
+void VisualModel::SetStartIndexOfElidedGlyphs(GlyphIndex startIndexOfElidedGlyphs)
+{
+  mStartIndexOfElidedGlyphs = startIndexOfElidedGlyphs;
+}
+
+void VisualModel::SetEndIndexOfElidedGlyphs(GlyphIndex endIndexOfElidedGlyphs)
+{
+  mEndIndexOfElidedGlyphs = endIndexOfElidedGlyphs;
+}
+
+void VisualModel::SetFirstMiddleIndexOfElidedGlyphs(GlyphIndex firstMiddleIndexOfElidedGlyphs)
+{
+  mFirstMiddleIndexOfElidedGlyphs = firstMiddleIndexOfElidedGlyphs;
+}
+
+void VisualModel::SetSecondMiddleIndexOfElidedGlyphs(GlyphIndex secondMiddleIndexOfElidedGlyphs)
+{
+  mSecondMiddleIndexOfElidedGlyphs = secondMiddleIndexOfElidedGlyphs;
+}
+
+void VisualModel::SetStrikethroughColor(const Vector4& color)
+{
+  mStrikethroughColor = color;
+}
+
+void VisualModel::SetStrikethroughEnabled(bool enabled)
+{
+  mStrikethroughEnabled = enabled;
+}
+
+void VisualModel::SetStrikethroughHeight(float height)
+{
+  mStrikethroughHeight = height;
+}
+
+void VisualModel::SetCharacterSpacing(float characterSpacing)
+{
+  mCharacterSpacing = characterSpacing;
+}
+
+const Vector4& VisualModel::GetTextColor() const
+{
+  return mTextColor;
+}
+
+const Vector2& VisualModel::GetShadowOffset() const
+{
+  return mShadowOffset;
+}
+
+const Vector4& VisualModel::GetShadowColor() const
+{
+  return mShadowColor;
+}
+
+const float& VisualModel::GetShadowBlurRadius() const
+{
+  return mShadowBlurRadius;
+}
+
+const Vector4& VisualModel::GetUnderlineColor() const
+{
+  return mUnderlineColor;
+}
+
+const Vector2& VisualModel::GetOutlineOffset() const
+{
+  return mOutlineOffset;
+}
+
+const Vector4& VisualModel::GetOutlineColor() const
+{
+  return mOutlineColor;
+}
+
+const float& VisualModel::GetOutlineBlurRadius() const
+{
+  return mOutlineBlurRadius;
+}
+
+bool VisualModel::IsUnderlineEnabled() const
+{
+  return mUnderlineEnabled;
+}
+
+float VisualModel::GetUnderlineHeight() const
+{
+  return mUnderlineHeight;
+}
+
+Text::Underline::Type VisualModel::GetUnderlineType() const
+{
+  return mUnderlineType;
+}
+
+float VisualModel::GetDashedUnderlineWidth() const
+{
+  return mDashedUnderlineWidth;
+}
+
+float VisualModel::GetDashedUnderlineGap() const
+{
+  return mDashedUnderlineGap;
+}
+
+uint16_t VisualModel::GetOutlineWidth() const
+{
+  return mOutlineWidth;
+}
+
+const Vector4& VisualModel::GetBackgroundColor() const
+{
+  return mBackgroundColor;
+}
+
+const float VisualModel::GetCharacterSpacing() const
+{
+  return mCharacterSpacing;
+}
+
+bool VisualModel::IsBackgroundEnabled() const
+{
+  return mBackgroundEnabled;
+}
+
+bool VisualModel::IsMarkupProcessorEnabled() const
+{
+  return mMarkupProcessorEnabled;
+}
+
+bool VisualModel::IsTextElideEnabled() const
+{
+  return mTextElideEnabled;
+}
+
+Toolkit::DevelText::EllipsisPosition::Type VisualModel::GetEllipsisPosition() const
+{
+  return mEllipsisPosition;
+}
+
+GlyphIndex VisualModel::GetStartIndexOfElidedGlyphs() const
+{
+  return mStartIndexOfElidedGlyphs;
+}
+
+GlyphIndex VisualModel::GetEndIndexOfElidedGlyphs() const
+{
+  return mEndIndexOfElidedGlyphs;
+}
+
+GlyphIndex VisualModel::GetFirstMiddleIndexOfElidedGlyphs() const
+{
+  return mFirstMiddleIndexOfElidedGlyphs;
+}
+
+GlyphIndex VisualModel::GetSecondMiddleIndexOfElidedGlyphs() const
+{
+  return mSecondMiddleIndexOfElidedGlyphs;
+}
+
+Length VisualModel::GetNumberOfUnderlineRuns() const
+{
+  return mUnderlineRuns.Count();
+}
+
+const Vector4& VisualModel::GetStrikethroughColor() const
+{
+  return mStrikethroughColor;
+}
+
+bool VisualModel::IsStrikethroughEnabled() const
+{
+  return mStrikethroughEnabled;
+}
+
+float VisualModel::GetStrikethroughHeight() const
+{
+  return mStrikethroughHeight;
+}
+
+void VisualModel::GetStrikethroughRuns(StrikethroughGlyphRun* strikethroughRuns,
+                                       StrikethroughRunIndex  index,
+                                       Length                 numberOfRuns) const
+{
+  memcpy(strikethroughRuns,
+         mStrikethroughRuns.Begin() + index,
+         numberOfRuns * sizeof(StrikethroughGlyphRun));
+}
+
+Length VisualModel::GetNumberOfStrikethroughRuns() const
+{
+  return mStrikethroughRuns.Count();
+}
+
+Length VisualModel::GetNumberOfCharacterSpacingGlyphRuns() const
+{
+  return mCharacterSpacingRuns.Count();
+}
+
+const Vector<CharacterSpacingGlyphRun>& VisualModel::GetCharacterSpacingGlyphRuns() const
+{
+  return mCharacterSpacingRuns;
+}
+
+void VisualModel::ClearCaches()
+{
+  mCachedLineIndex = 0u;
+}
+
+const Vector<CharacterIndex>& VisualModel::GetGlyphsToCharacters() const
+{
+  return mGlyphsToCharacters;
+}
+
+void VisualModel::SetCutoutEnabled(bool enable)
+{
+  mCutoutEnabled = enable;
+}
+
+bool VisualModel::IsCutoutEnabled() const
+{
+  return mCutoutEnabled;
+}
+
+void VisualModel::SetBackgroundWithCutoutEnabled(bool enable)
+{
+  mBackgroundWithCutoutEnabled = enable;
+}
+
+bool VisualModel::IsBackgroundWithCutoutEnabled() const
+{
+  return mBackgroundWithCutoutEnabled;
 }
 
-void VisualModel::SetActualSize( const Vector2& size )
+void VisualModel::SetBackgroundColorWithCutout(const Vector4& color)
 {
-  mActualSize = size;
+  mBackgroundColorWithCutout = color;
 }
 
-const Vector2& VisualModel::GetActualSize() const
+const Vector4& VisualModel::GetBackgroundColorWithCutout() const
 {
-  return mActualSize;
+  return mBackgroundColorWithCutout;
 }
 
 VisualModel::~VisualModel()
@@ -375,6 +700,48 @@ VisualModel::~VisualModel()
 }
 
 VisualModel::VisualModel()
+: mGlyphs(),
+  mGlyphsToCharacters(),
+  mCharactersToGlyph(),
+  mCharactersPerGlyph(),
+  mGlyphsPerCharacter(),
+  mGlyphPositions(),
+  mLines(),
+  mTextColor(Color::BLACK),
+  mShadowColor(Color::BLACK),
+  mUnderlineColor(Color::BLACK),
+  mOutlineColor(Color::WHITE),
+  mBackgroundColor(Color::TRANSPARENT),
+  mStrikethroughColor(Color::BLACK),
+  mControlSize(),
+  mShadowOffset(),
+  mOutlineOffset(),
+  mUnderlineHeight(0.0f),
+  mStrikethroughHeight(0.0f),
+  mUnderlineType(Text::Underline::SOLID),
+  mDashedUnderlineWidth(2.0f),
+  mDashedUnderlineGap(1.0f),
+  mShadowBlurRadius(0.0f),
+  mOutlineBlurRadius(0.0f),
+  mOutlineWidth(0u),
+  mNaturalSize(),
+  mLayoutSize(),
+  mHeightForWidth(0.0f, 0.0f),
+  mCachedLineIndex(0u),
+  mEllipsisPosition(DevelText::EllipsisPosition::END),
+  mStartIndexOfElidedGlyphs(0u),
+  mEndIndexOfElidedGlyphs(0u),
+  mFirstMiddleIndexOfElidedGlyphs(0u),
+  mSecondMiddleIndexOfElidedGlyphs(0u),
+  mTextElideEnabled(false),
+  mUnderlineEnabled(false),
+  mUnderlineColorSet(false),
+  mBackgroundEnabled(false),
+  mMarkupProcessorEnabled(false),
+  mStrikethroughEnabled(false),
+  mCharacterSpacing(0.0f),
+  mCutoutEnabled(false),
+  mBackgroundWithCutoutEnabled(false)
 {
 }