TextView - Right to Left implementation. 50/27450/10
authorVictor Cebollada <v.cebollada@samsung.com>
Wed, 10 Sep 2014 14:58:06 +0000 (15:58 +0100)
committerVictor Cebollada <v.cebollada@samsung.com>
Fri, 19 Sep 2014 16:10:43 +0000 (17:10 +0100)
* Text and style is stored in the paragraph instead inside the character.
* If a paragraph has bidirectional text, it stores the
  minimum common data needed to reorder a line.
* Before creating text-actors, text-view reorders
  the bidirectional text, keeping the logical order.

Change-Id: Iff9c7e9223eb9c9a7d15b1e41cc6dc2f47096aa0
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
27 files changed:
automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor-Types.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Relayout-Utilities.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextView.cpp
base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp
base/dali-toolkit/internal/controls/text-view/relayout-utilities.h
base/dali-toolkit/internal/controls/text-view/split-by-char-policies.cpp
base/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.cpp
base/dali-toolkit/internal/controls/text-view/split-by-word-policies.cpp
base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp [new file with mode: 0644]
base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h [new file with mode: 0644]
base/dali-toolkit/internal/controls/text-view/text-processor.cpp
base/dali-toolkit/internal/controls/text-view/text-processor.h
base/dali-toolkit/internal/controls/text-view/text-view-character-processor.cpp
base/dali-toolkit/internal/controls/text-view/text-view-impl.cpp
base/dali-toolkit/internal/controls/text-view/text-view-impl.h
base/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.cpp
base/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.h
base/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.cpp
base/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.h
base/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.cpp
base/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h
base/dali-toolkit/internal/controls/text-view/text-view-processor-types.h
base/dali-toolkit/internal/controls/text-view/text-view-processor.cpp
base/dali-toolkit/internal/controls/text-view/text-view-word-processor.cpp
base/dali-toolkit/internal/controls/text-view/text-view-word-processor.h
base/dali-toolkit/internal/file.list

index 7cb03fe..44e25c0 100644 (file)
@@ -67,12 +67,11 @@ int UtcDaliTextViewDefaultConstructorDestructor_PT(void)
   DALI_TEST_EQUALS( characterLayoutInfo.mUnderlineThickness, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo.mUnderlinePosition, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_CHECK( !characterLayoutInfo.mGlyphActor );
   DALI_TEST_EQUALS( characterLayoutInfo.mUnderlineThickness, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo.mUnderlinePosition, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_CHECK( !characterLayoutInfo.mGlyphActor );
-  DALI_TEST_CHECK( characterLayoutInfo.mStyledText.mText.IsEmpty() );
   DALI_TEST_EQUALS( characterLayoutInfo.mColorAlpha, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_CHECK( NULL == characterLayoutInfo.mGradientInfo );
   DALI_TEST_CHECK( characterLayoutInfo.mIsVisible );
   DALI_TEST_EQUALS( characterLayoutInfo.mColorAlpha, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_CHECK( NULL == characterLayoutInfo.mGradientInfo );
   DALI_TEST_CHECK( characterLayoutInfo.mIsVisible );
-  DALI_TEST_CHECK( characterLayoutInfo.mSetText );
-  DALI_TEST_CHECK( characterLayoutInfo.mSetStyle );
+  DALI_TEST_CHECK( !characterLayoutInfo.mSetText );
+  DALI_TEST_CHECK( !characterLayoutInfo.mSetStyle );
 
   TextViewProcessor::WordLayoutInfo wordLayoutInfo;
   DALI_TEST_EQUALS( wordLayoutInfo.mSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
 
   TextViewProcessor::WordLayoutInfo wordLayoutInfo;
   DALI_TEST_EQUALS( wordLayoutInfo.mSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
@@ -116,7 +115,6 @@ int UtcDaliTextViewCopyConstructorOperator(void)
   characterLayoutInfo.mUnderlinePosition = 1.f;
 
   characterLayoutInfo.mGlyphActor = TextActor::New( "Hello" );
   characterLayoutInfo.mUnderlinePosition = 1.f;
 
   characterLayoutInfo.mGlyphActor = TextActor::New( "Hello" );
-  characterLayoutInfo.mStyledText.mText = Text( "Hello" );
 
   TextViewProcessor::GradientInfo* info = new TextViewProcessor::GradientInfo();
   info->mGradientColor = Vector4( 1.f, 1.f, 1.f, 1.f );
 
   TextViewProcessor::GradientInfo* info = new TextViewProcessor::GradientInfo();
   info->mGradientColor = Vector4( 1.f, 1.f, 1.f, 1.f );
@@ -141,7 +139,6 @@ int UtcDaliTextViewCopyConstructorOperator(void)
   DALI_TEST_EQUALS( characterLayoutInfo1.mUnderlineThickness, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo1.mUnderlinePosition, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_CHECK( characterLayoutInfo1.mGlyphActor );
   DALI_TEST_EQUALS( characterLayoutInfo1.mUnderlineThickness, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo1.mUnderlinePosition, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_CHECK( characterLayoutInfo1.mGlyphActor );
-  DALI_TEST_EQUALS( characterLayoutInfo1.mStyledText.mText.GetLength(), 5u, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo1.mColorAlpha, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo1.mGradientInfo->mGradientColor, Vector4( 1.f, 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo1.mGradientInfo->mStartPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo1.mColorAlpha, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo1.mGradientInfo->mGradientColor, Vector4( 1.f, 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo1.mGradientInfo->mStartPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
@@ -159,7 +156,6 @@ int UtcDaliTextViewCopyConstructorOperator(void)
   DALI_TEST_EQUALS( characterLayoutInfo2.mUnderlineThickness, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo2.mUnderlinePosition, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_CHECK( characterLayoutInfo2.mGlyphActor );
   DALI_TEST_EQUALS( characterLayoutInfo2.mUnderlineThickness, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo2.mUnderlinePosition, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_CHECK( characterLayoutInfo2.mGlyphActor );
-  DALI_TEST_EQUALS( characterLayoutInfo2.mStyledText.mText.GetLength(), 5u, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo2.mColorAlpha, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo2.mGradientInfo->mGradientColor, Vector4( 1.f, 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo2.mGradientInfo->mStartPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo2.mColorAlpha, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo2.mGradientInfo->mGradientColor, Vector4( 1.f, 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
   DALI_TEST_EQUALS( characterLayoutInfo2.mGradientInfo->mStartPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
index 2fb823f..8fef857 100644 (file)
@@ -22,6 +22,7 @@
 
 // Internal headers are allowed here
 #include <dali-toolkit/internal/controls/text-view/text-processor.h>
 
 // Internal headers are allowed here
 #include <dali-toolkit/internal/controls/text-view/text-processor.h>
+#include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
 
 using namespace Dali;
 using namespace Dali::Toolkit;
 
 using namespace Dali;
 using namespace Dali::Toolkit;
@@ -53,11 +54,10 @@ struct BeginsRightToLeftCharacterTest
 
 bool TestBeginsRightToLeftCharacter( const std::string& description, const std::string& input, const bool result, const char* location )
 {
 
 bool TestBeginsRightToLeftCharacter( const std::string& description, const std::string& input, const bool result, const char* location )
 {
-  // Creates a styled text with the markup or plain string.
-  MarkupProcessor::StyledTextArray styledText;
-  MarkupProcessor::GetStyledTextArray( input, styledText, true );
+  // Creates a text with the string.
+  Text text( input );
 
 
-  const bool ret = ( result == TextProcessor::BeginsRightToLeftCharacter( styledText ) );
+  const bool ret = ( result == TextProcessor::BeginsRightToLeftCharacter( text ) );
 
   if( !ret )
   {
 
   if( !ret )
   {
@@ -79,11 +79,10 @@ struct ContainsRightToLeftCharacterTest
 
 bool TestContainsRightToLeftCharacter( const std::string& description, const std::string& input, const bool result, const char* location )
 {
 
 bool TestContainsRightToLeftCharacter( const std::string& description, const std::string& input, const bool result, const char* location )
 {
-  // Creates a styled text with the markup or plain string.
-  MarkupProcessor::StyledTextArray styledText;
-  MarkupProcessor::GetStyledTextArray( input, styledText, true );
+  // Creates a text with the string.
+  Text text( input );
 
 
-  const bool ret = ( result == TextProcessor::ContainsRightToLeftCharacter( styledText ) );
+  const bool ret = ( result == TextProcessor::ContainsRightToLeftCharacter( text ) );
 
   if( !ret )
   {
 
   if( !ret )
   {
@@ -141,10 +140,12 @@ bool TestSplitInParagraphs( const SplitInParagraphsTest& test, const char* locat
   MarkupProcessor::StyledTextArray styledText;
   MarkupProcessor::GetStyledTextArray( test.inputText, styledText, true );
 
   MarkupProcessor::StyledTextArray styledText;
   MarkupProcessor::GetStyledTextArray( test.inputText, styledText, true );
 
-  std::vector<MarkupProcessor::StyledTextArray> paragraphs;
+  std::vector<Text> paragraphs;
+  std::vector< Vector<TextStyle*> > styles;
 
   TextProcessor::SplitInParagraphs( styledText,
 
   TextProcessor::SplitInParagraphs( styledText,
-                                    paragraphs );
+                                    paragraphs,
+                                    styles );
 
   if( paragraphs.size() != test.resultNumberOfParagraphs )
   {
 
   if( paragraphs.size() != test.resultNumberOfParagraphs )
   {
@@ -163,24 +164,23 @@ struct SplitInWordsTest
 {
   std::string inputText;
 
 {
   std::string inputText;
 
-  std::size_t resultNumberOfWords;
+  std::size_t resultNumberOfSeparators;
 };
 
 bool TestSplitInWords( const SplitInWordsTest& test, const char* location )
 {
 };
 
 bool TestSplitInWords( const SplitInWordsTest& test, const char* location )
 {
-  // Creates a styled text with the markup or plain string.
-  MarkupProcessor::StyledTextArray styledText;
-  MarkupProcessor::GetStyledTextArray( test.inputText, styledText, true );
+  // Creates a text with the string.
+  Text text( test.inputText );
 
 
-  std::vector<MarkupProcessor::StyledTextArray> words;
+  Vector<std::size_t> positions;
 
 
-  TextProcessor::SplitInWords( styledText,
-                               words );
+  TextProcessor::SplitInWords( text,
+                               positions );
 
 
-  if( words.size() != test.resultNumberOfWords )
+  if( positions.Count() != test.resultNumberOfSeparators )
   {
     tet_printf( "Fail. %s", location );
   {
     tet_printf( "Fail. %s", location );
-    tet_printf( "Different number of words, result %d, expected result %d", words.size(), test.resultNumberOfWords );
+    tet_printf( "Different number of separators, result %d, expected result %d", positions.Count(), test.resultNumberOfSeparators );
 
     return false;
   }
 
     return false;
   }
@@ -236,10 +236,14 @@ int UtcDaliTextViewSplitInWords(void)
   {
     {
       std::string( "Hello world, hello word!" ),
   {
     {
       std::string( "Hello world, hello word!" ),
-      7
+      3u
     },
     },
+    {
+      std::string( "Hello world\n" ),
+      2u
+    }
   };
   };
-  const std::size_t numberOfTests( 1 );
+  const std::size_t numberOfTests( 2u );
 
   for( std::size_t index = 0; index < numberOfTests; ++index )
   {
 
   for( std::size_t index = 0; index < numberOfTests; ++index )
   {
index 255c96a..c556e08 100644 (file)
@@ -88,6 +88,7 @@ bool TestCalculateLineLayout( const CalculateLineLayoutTest& test,  const char*
 
   // Creaqte indices.
   TextViewProcessor::TextInfoIndices indices( 0u, test.wordIndex, test.characterIndex );
 
   // Creaqte indices.
   TextViewProcessor::TextInfoIndices indices( 0u, test.wordIndex, test.characterIndex );
+  indices.mCharacterParagraphIndex = test.characterParagraphIndex;
 
   // Get the input paragraph.
   TextViewProcessor::ParagraphLayoutInfo inputParagraphLayout;
 
   // Get the input paragraph.
   TextViewProcessor::ParagraphLayoutInfo inputParagraphLayout;
index ee43cbd..dc2a363 100644 (file)
@@ -66,6 +66,7 @@ struct SplitParagraphTest
   std::string input;
   std::size_t wordIndex;
   std::size_t characterIndex;
   std::string input;
   std::size_t wordIndex;
   std::size_t characterIndex;
+  std::size_t characterParagraphIndex;
   float       lineHeightOffset;
   std::string firstResult;
   std::string lastResult;
   float       lineHeightOffset;
   std::string firstResult;
   std::string lastResult;
@@ -141,10 +142,6 @@ void Print( const TextViewProcessor::CharacterLayoutInfo& character )
   {
     std::cout << "[" << textActor.GetText() << "]";
   }
   {
     std::cout << "[" << textActor.GetText() << "]";
   }
-  else
-  {
-    std::cout << "{" << character.mStyledText.mText.GetText() << "}";
-  }
 }
 
 void Print( const TextViewProcessor::WordLayoutInfo& word )
 }
 
 void Print( const TextViewProcessor::WordLayoutInfo& word )
@@ -186,21 +183,13 @@ void Print( const TextViewProcessor::TextLayoutInfo& text )
   std::cout << "||" << std::endl;
 }
 
   std::cout << "||" << std::endl;
 }
 
-std::string GetText( const TextViewProcessor::CharacterLayoutInfo& character )
-{
-  return character.mStyledText.mText.GetText();
-}
-
-std::string GetText( const TextViewProcessor::WordLayoutInfo& word )
+std::string GetText( const TextViewProcessor::WordLayoutInfo& word, const Text& paragraphText )
 {
 {
-  std::string text;
+  Text text;
 
 
-  for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator it = word.mCharactersLayoutInfo.begin(), endIt = word.mCharactersLayoutInfo.end(); it != endIt; ++it )
-  {
-    text += GetText( *it );
-  }
+  paragraphText.GetSubText( word.mFirstCharacter, word.mFirstCharacter + word.mCharactersLayoutInfo.size() - 1u, text );
 
 
-  return text;
+  return text.GetText();
 }
 
 std::string GetText( const TextViewProcessor::ParagraphLayoutInfo& paragraph )
 }
 
 std::string GetText( const TextViewProcessor::ParagraphLayoutInfo& paragraph )
@@ -209,7 +198,7 @@ std::string GetText( const TextViewProcessor::ParagraphLayoutInfo& paragraph )
 
   for( TextViewProcessor::WordLayoutInfoContainer::const_iterator it = paragraph.mWordsLayoutInfo.begin(), endIt = paragraph.mWordsLayoutInfo.end(); it != endIt; ++it )
   {
 
   for( TextViewProcessor::WordLayoutInfoContainer::const_iterator it = paragraph.mWordsLayoutInfo.begin(), endIt = paragraph.mWordsLayoutInfo.end(); it != endIt; ++it )
   {
-    text += GetText( *it );
+    text += GetText( *it, paragraph.mText );
   }
 
   return text;
   }
 
   return text;
@@ -288,27 +277,6 @@ bool TestEqual( const TextViewProcessor::CharacterLayoutInfo& character1,
     return false;
   }
 
     return false;
   }
 
-  text1 = character1.mStyledText.mText.GetText();
-  style1 = character1.mStyledText.mStyle;
-
-  text2 = character2.mStyledText.mText.GetText();
-  style2 = character2.mStyledText.mStyle;
-
-  if( text1 != text2 )
-  {
-    return false;
-  }
-
-  if( style1 != style2 )
-  {
-    std::cout << "  style1 : " << std::endl;
-    TextViewProcessor::dbgPrint( style1 );
-
-    std::cout << "  style2 : " << std::endl;
-    TextViewProcessor::dbgPrint( style2 );
-    return false;
-  }
-
   return true;
 }
 
   return true;
 }
 
@@ -557,6 +525,7 @@ bool TestSplitWord( const std::string& description, const std::string& input, co
  * @param input The input word.
  * @param wordIndex Index to the word within the paragraph where to split it.
  * @param characterIndex Where to split the word.
  * @param input The input word.
  * @param wordIndex Index to the word within the paragraph where to split it.
  * @param characterIndex Where to split the word.
+ * @param characterIndex Character index within the paragraph.
  * @param lineHeightOffset Offset between lines.
  * @param firstResult First part of the split paragraph.
  * @param lastResult Last part of the split paragraph.
  * @param lineHeightOffset Offset between lines.
  * @param firstResult First part of the split paragraph.
  * @param lastResult Last part of the split paragraph.
@@ -568,6 +537,7 @@ bool TestSplitParagraph( const std::string& description,
                          const std::string& input,
                          size_t wordIndex,
                          size_t characterIndex,
                          const std::string& input,
                          size_t wordIndex,
                          size_t characterIndex,
+                         size_t characterParagraphIndex,
                          float lineHeightOffset,
                          const std::string& firstResult,
                          const std::string& lastResult,
                          float lineHeightOffset,
                          const std::string& firstResult,
                          const std::string& lastResult,
@@ -589,7 +559,6 @@ bool TestSplitParagraph( const std::string& description,
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
-                                                                                    std::string( "..." ),
                                                                                     true ),
                                      relayoutData );
 
                                                                                     true ),
                                      relayoutData );
 
@@ -616,7 +585,6 @@ bool TestSplitParagraph( const std::string& description,
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
-                                                                                    std::string( "..." ),
                                                                                     true ),
                                      firstRelayoutData );
 
                                                                                     true ),
                                      firstRelayoutData );
 
@@ -643,7 +611,6 @@ bool TestSplitParagraph( const std::string& description,
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
-                                                                                    std::string( "..."),
                                                                                     true ),
                                      lastRelayoutData );
 
                                                                                     true ),
                                      lastRelayoutData );
 
@@ -660,6 +627,7 @@ bool TestSplitParagraph( const std::string& description,
   TextViewProcessor::ParagraphLayoutInfo lastParagraphLayoutInfo;
 
   TextViewProcessor::TextInfoIndices indices( 0, wordIndex, characterIndex );
   TextViewProcessor::ParagraphLayoutInfo lastParagraphLayoutInfo;
 
   TextViewProcessor::TextInfoIndices indices( 0, wordIndex, characterIndex );
+  indices.mCharacterParagraphIndex = characterParagraphIndex;
 
   SplitParagraph( indices,
                   PointSize( lineHeightOffset ),
 
   SplitParagraph( indices,
                   PointSize( lineHeightOffset ),
@@ -812,7 +780,6 @@ bool TestMergeParagraphs( const std::string& description, const std::string& inp
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
-                                                                                    std::string( "..." ),
                                                                                     true ),
                                      firstRelayoutData );
 
                                                                                     true ),
                                      firstRelayoutData );
 
@@ -838,7 +805,6 @@ bool TestMergeParagraphs( const std::string& description, const std::string& inp
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
-                                                                                    std::string( "..." ),
                                                                                     true ),
                                      lastRelayoutData );
 
                                                                                     true ),
                                      lastRelayoutData );
 
@@ -864,7 +830,6 @@ bool TestMergeParagraphs( const std::string& description, const std::string& inp
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
-                                                                                    std::string( "..." ),
                                                                                     true ),
                                      resultRelayoutData );
 
                                                                                     true ),
                                      resultRelayoutData );
 
@@ -998,7 +963,6 @@ bool TestRemoveWordsFromParagraph( const std::string& description, const std::st
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
-                                                                                    std::string( "..." ),
                                                                                     true ),
                                      relayoutData );
 
                                                                                     true ),
                                      relayoutData );
 
@@ -1024,7 +988,6 @@ bool TestRemoveWordsFromParagraph( const std::string& description, const std::st
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
-                                                                                    std::string( "..." ),
                                                                                     true ),
                                      resultRelayoutData );
 
                                                                                     true ),
                                      resultRelayoutData );
 
@@ -1099,7 +1062,6 @@ bool TestUpdateTextInfo( const std::string& description,
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
-                                                                                    std::string( "..." ),
                                                                                     true ),
                                      relayoutData );
 
                                                                                     true ),
                                      relayoutData );
 
@@ -1117,7 +1079,6 @@ bool TestUpdateTextInfo( const std::string& description,
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                                     Toolkit::TextView::Center,
                                                                                     PointSize( lineHeightOffset ),
-                                                                                    std::string( "..." ),
                                                                                     true ),
                                      resultRelayoutData );
 
                                                                                     true ),
                                      resultRelayoutData );
 
@@ -1128,7 +1089,6 @@ bool TestUpdateTextInfo( const std::string& description,
                                                                         static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                         Toolkit::TextView::Center,
                                                                         PointSize( lineHeightOffset ),
                                                                         static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                                                                         Toolkit::TextView::Center,
                                                                         PointSize( lineHeightOffset ),
-                                                                        std::string( "..." ),
                                                                         true );
 
   switch( operation )
                                                                         true );
 
   switch( operation )
@@ -1254,15 +1214,6 @@ int UtcDaliTextViewCreateTextInfo(void)
   layoutInfo12.mBearing = BEARING_12;
   layoutInfo12.mAscender = ASCENDER_12;
 
   layoutInfo12.mBearing = BEARING_12;
   layoutInfo12.mAscender = ASCENDER_12;
 
-  TextStyle style10;
-  style10.SetFontName( "" );
-  style10.SetFontPointSize( PointSize( 10.f ) );
-  TextStyle style12;
-  style12.SetFontName( "" );
-
-  layoutInfo12.mStyledText.mStyle = style12;
-  layoutInfo10.mStyledText.mStyle = style10;
-
   // Words
 
   TextViewProcessor::WordLayoutInfo wordLayout1, wordLayout2, wordLayout3, wordLayout4;
   // Words
 
   TextViewProcessor::WordLayoutInfo wordLayout1, wordLayout2, wordLayout3, wordLayout4;
@@ -1272,46 +1223,33 @@ int UtcDaliTextViewCreateTextInfo(void)
   wordLayout1.mAscender = ASCENDER_12;
   wordLayout1.mType = TextViewProcessor::NoSeparator;
 
   wordLayout1.mAscender = ASCENDER_12;
   wordLayout1.mType = TextViewProcessor::NoSeparator;
 
-  layoutInfo12.mStyledText.mText = Text( "H" );
   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // H
   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // H
-  layoutInfo12.mStyledText.mText = Text( "e" );
   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // e
   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // e
-  layoutInfo12.mStyledText.mText = Text( "l" );
   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // l
   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // l
-  layoutInfo10.mStyledText.mText = Text( "l" );
   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo10 ); // l
   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo10 ); // l
-  layoutInfo10.mStyledText.mText = Text( "o" );
   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo10 ); // o
 
   // (white space)
   wordLayout2.mSize = Size( ADVANCE_10, HEIGHT_10 );
   wordLayout2.mAscender = ASCENDER_10;
   wordLayout2.mType = TextViewProcessor::WordSeparator;
   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo10 ); // o
 
   // (white space)
   wordLayout2.mSize = Size( ADVANCE_10, HEIGHT_10 );
   wordLayout2.mAscender = ASCENDER_10;
   wordLayout2.mType = TextViewProcessor::WordSeparator;
-  layoutInfo10.mStyledText.mText = Text( " " );
   wordLayout2.mCharactersLayoutInfo.push_back( layoutInfo10 ); // (white space)
 
   // world!
   wordLayout3.mSize = Size( 2.f * ADVANCE_10 + 4.f * ADVANCE_12, HEIGHT_12 );
   wordLayout3.mAscender = ASCENDER_12;
   wordLayout3.mType = TextViewProcessor::NoSeparator;
   wordLayout2.mCharactersLayoutInfo.push_back( layoutInfo10 ); // (white space)
 
   // world!
   wordLayout3.mSize = Size( 2.f * ADVANCE_10 + 4.f * ADVANCE_12, HEIGHT_12 );
   wordLayout3.mAscender = ASCENDER_12;
   wordLayout3.mType = TextViewProcessor::NoSeparator;
-  layoutInfo10.mStyledText.mText = Text( "w" );
   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo10 ); // w
   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo10 ); // w
-  layoutInfo10.mStyledText.mText = Text( "o" );
   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo10 ); // o
   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo10 ); // o
-  layoutInfo12.mStyledText.mText = Text( "r" );
   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // r
   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // r
-  layoutInfo12.mStyledText.mText = Text( "l" );
   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // l
   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // l
-  layoutInfo12.mStyledText.mText = Text( "d" );
   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // d
   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // d
-  layoutInfo12.mStyledText.mText = Text( "!" );
   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // !
 
   // (new paragraph character)
   wordLayout4.mSize = Size( 0.f, HEIGHT_12 );
   wordLayout4.mAscender = ASCENDER_12;
   wordLayout4.mType = TextViewProcessor::ParagraphSeparator;
   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // !
 
   // (new paragraph character)
   wordLayout4.mSize = Size( 0.f, HEIGHT_12 );
   wordLayout4.mAscender = ASCENDER_12;
   wordLayout4.mType = TextViewProcessor::ParagraphSeparator;
-  layoutInfo12.mStyledText.mText = Text( "\n" );
   layoutInfo12.mSize.width = 0.f;
   wordLayout4.mCharactersLayoutInfo.push_back( layoutInfo12 ); // (new paragraph char)
 
   layoutInfo12.mSize.width = 0.f;
   wordLayout4.mCharactersLayoutInfo.push_back( layoutInfo12 ); // (new paragraph char)
 
@@ -1533,7 +1471,6 @@ int UtcDaliTextViewUpdateTextInfo(void)
       std::string( "Hello <font size='30'>w</font>orl<font size='10'>dhello</font> world" )
     },
     // * Remove RTL text within LTR
       std::string( "Hello <font size='30'>w</font>orl<font size='10'>dhello</font> world" )
     },
     // * Remove RTL text within LTR
-    /* TODO check this when RTL text is working
     {
       std::string( "Remove within the same paragraph, RTL text within LTR." ),
       Remove,
     {
       std::string( "Remove within the same paragraph, RTL text within LTR." ),
       Remove,
@@ -1544,7 +1481,6 @@ int UtcDaliTextViewUpdateTextInfo(void)
       0.f,
       std::string( "Hello worlello world" )
     },
       0.f,
       std::string( "Hello worlello world" )
     },
-    */
     // * Remove whole paragraph
     {
       std::string( "Remove whole paragraph" ),
     // * Remove whole paragraph
     {
       std::string( "Remove whole paragraph" ),
@@ -1668,7 +1604,7 @@ int UtcDaliTextViewUpdateTextInfo(void)
       std::string( "Touch <b>me\nhello\n</b>world" )
     },
   };
       std::string( "Touch <b>me\nhello\n</b>world" )
     },
   };
-  const std::size_t numberOfTests( 21u );
+  const std::size_t numberOfTests( 22u );
 
   for( std::size_t index = 0u; index < numberOfTests; ++index )
   {
 
   for( std::size_t index = 0u; index < numberOfTests; ++index )
   {
@@ -1697,6 +1633,7 @@ int UtcDaliTextViewSplitParagraph(void)
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       0,
       0,
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       0,
       0,
+      0,
       3.f,
       std::string( "" ),
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       3.f,
       std::string( "" ),
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
@@ -1706,6 +1643,7 @@ int UtcDaliTextViewSplitParagraph(void)
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       10,
       4,
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       10,
       4,
+      36,
       0.f,
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       std::string( "" ),
       0.f,
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       std::string( "" ),
@@ -1715,16 +1653,17 @@ int UtcDaliTextViewSplitParagraph(void)
       std::string("<font size='10'>Hello </font>wor<font size='12'>ld, hello wo</font>rld"),
       2,
       4,
       std::string("<font size='10'>Hello </font>wor<font size='12'>ld, hello wo</font>rld"),
       2,
       4,
+      10,
       0.f,
       std::string("<font size='10'>Hello </font>wor<font size='12'>l</font>"),
       std::string("<font size='12'>d, hello wo</font>rld")
       0.f,
       std::string("<font size='10'>Hello </font>wor<font size='12'>l</font>"),
       std::string("<font size='12'>d, hello wo</font>rld")
-    }
-    /* TODO RTL
+    },
     {
       std::string( "Split paragraph, wordPosition 6, position 0." ),
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       6,
       0,
     {
       std::string( "Split paragraph, wordPosition 6, position 0." ),
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       6,
       0,
+      21,
       0.f,
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום " ),
       std::string( "עולם text text" ),
       0.f,
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום " ),
       std::string( "עולם text text" ),
@@ -1734,6 +1673,7 @@ int UtcDaliTextViewSplitParagraph(void)
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       4,
       0,
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       4,
       0,
+      17,
       0.f,
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> " ),
       std::string( "שלום עולם text text" ),
       0.f,
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> " ),
       std::string( "שלום עולם text text" ),
@@ -1743,13 +1683,13 @@ int UtcDaliTextViewSplitParagraph(void)
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       8,
       0,
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
       8,
       0,
+      27,
       6.f,
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם " ),
       std::string( "text text" ),
     },
       6.f,
       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם " ),
       std::string( "text text" ),
     },
-    */
   };
   };
-  const std::size_t numberOfTests( 3u );
+  const std::size_t numberOfTests( 6u );
 
   for( std::size_t index = 0u; index < numberOfTests; ++index )
   {
 
   for( std::size_t index = 0u; index < numberOfTests; ++index )
   {
@@ -1759,6 +1699,7 @@ int UtcDaliTextViewSplitParagraph(void)
                              test.input,
                              test.wordIndex,
                              test.characterIndex,
                              test.input,
                              test.wordIndex,
                              test.characterIndex,
+                             test.characterParagraphIndex,
                              test.lineHeightOffset,
                              test.firstResult,
                              test.lastResult,
                              test.lineHeightOffset,
                              test.firstResult,
                              test.lastResult,
@@ -1969,7 +1910,6 @@ int UtcDaliTextViewMergeParagraph01(void)
       0.f,
       std::string( "Hello world, this is a whole paragraph" )
     },
       0.f,
       std::string( "Hello world, this is a whole paragraph" )
     },
-    /* TODO RTL
     {
       std::string( "Merge paragraphs: last starting with RTL text and first ending with RTL" ),
       std::string( "Hello world, שלום" ),
     {
       std::string( "Merge paragraphs: last starting with RTL text and first ending with RTL" ),
       std::string( "Hello world, שלום" ),
@@ -1984,7 +1924,6 @@ int UtcDaliTextViewMergeParagraph01(void)
       3.f,
       std::string( "Hello world, שלום עולם, hello world." )
     },
       3.f,
       std::string( "Hello world, שלום עולם, hello world." )
     },
-    */
     {
       std::string( "Merge paragraphs. Don't merge words" ),
       std::string( "Hello world," ),
     {
       std::string( "Merge paragraphs. Don't merge words" ),
       std::string( "Hello world," ),
@@ -2000,7 +1939,7 @@ int UtcDaliTextViewMergeParagraph01(void)
       std::string( "Hello world, this is a whole paragraph" )
     },
   };
       std::string( "Hello world, this is a whole paragraph" )
     },
   };
-  const std::size_t numberOfTests( 4u );
+  const std::size_t numberOfTests( 6u );
 
   for( std::size_t index = 0u; index < numberOfTests; ++index )
   {
 
   for( std::size_t index = 0u; index < numberOfTests; ++index )
   {
index fab32ca..d39300e 100644 (file)
@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * 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
+ * http://www.apache.org/license/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,
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
 #include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/text-view/text-processor.h>
+#include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
+#include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h>
+#include <dali-toolkit/internal/controls/text-view/text-view-processor-dbg.h>
 
 // EXTERNAL INCLUDES
 #include <cmath>
 
 // EXTERNAL INCLUDES
 #include <cmath>
@@ -213,7 +217,7 @@ struct CurrentTextActorInfo
   Vector3 position;
   Size size;
   Vector4 color;
   Vector3 position;
   Size size;
   Vector4 color;
-  TextViewProcessor::GradientInfo* gradientInfo;
+  TextViewProcessor::CharacterLayoutInfo* characterLayout;
 };
 
 void SetVisualParameters( CurrentTextActorInfo& currentTextActorInfo,
 };
 
 void SetVisualParameters( CurrentTextActorInfo& currentTextActorInfo,
@@ -222,11 +226,12 @@ void SetVisualParameters( CurrentTextActorInfo& currentTextActorInfo,
                           const float lineHeight )
 {
   currentTextActorInfo.textActor.SetTextColor( currentTextActorInfo.color );
                           const float lineHeight )
 {
   currentTextActorInfo.textActor.SetTextColor( currentTextActorInfo.color );
-  if( NULL != currentTextActorInfo.gradientInfo )
+  if( ( NULL != currentTextActorInfo.characterLayout ) &&
+      ( NULL != currentTextActorInfo.characterLayout->mGradientInfo ) )
   {
   {
-    currentTextActorInfo.textActor.SetGradientColor( currentTextActorInfo.gradientInfo->mGradientColor );
-    currentTextActorInfo.textActor.SetGradientStartPoint( currentTextActorInfo.gradientInfo->mStartPoint );
-    currentTextActorInfo.textActor.SetGradientEndPoint( currentTextActorInfo.gradientInfo->mEndPoint );
+    currentTextActorInfo.textActor.SetGradientColor( currentTextActorInfo.characterLayout->mGradientInfo->mGradientColor );
+    currentTextActorInfo.textActor.SetGradientStartPoint( currentTextActorInfo.characterLayout->mGradientInfo->mStartPoint );
+    currentTextActorInfo.textActor.SetGradientEndPoint( currentTextActorInfo.characterLayout->mGradientInfo->mEndPoint );
   }
 
   // The italics offset is used in the offscreen rendering. When text is in italics, it may exceed the text-view's boundary
   }
 
   // The italics offset is used in the offscreen rendering. When text is in italics, it may exceed the text-view's boundary
@@ -343,6 +348,278 @@ void CalculateLineLayout( float parentWidth,
   subLineInfo.mMaxAscender *= shrinkFactor;
 }
 
   subLineInfo.mMaxAscender *= shrinkFactor;
 }
 
+
+/**
+ * Sets a character of a line of a bidirectional paragraph in the new position.
+ *
+ * @param[in] wordsLayoutInfo Layout info of all the words of the paragraph.
+ * @param[in] index Index within the paragraph to the character to be set in the new position.
+ * @param[in,out] character Reference to the character in the new position.
+ */
+void SetCharacter( const TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo,
+                   std::size_t index,
+                   TextViewProcessor::CharacterLayoutInfo& character )
+{
+  // Traverse all the characters of the paragraph till the one pointed by index is found.
+  std::size_t traversedCharacters = 0u;
+  for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = wordsLayoutInfo.begin(),
+         wordEndIt = wordsLayoutInfo.end();
+       wordIt != wordEndIt;
+       ++wordIt )
+  {
+    const TextViewProcessor::WordLayoutInfo& word( *wordIt );
+
+    const std::size_t numberOfCharacters = word.mCharactersLayoutInfo.size();
+    if( index < traversedCharacters + numberOfCharacters  )
+    {
+      character = *( word.mCharactersLayoutInfo.begin() + ( index - traversedCharacters ) );
+      return;
+    }
+    traversedCharacters += numberOfCharacters;
+  }
+}
+
+/**
+ * Reorders the layout info of each line of the paragraph.
+ *
+ * Uses the visual to logical conversion table to order the text, styles and character's layout (metrics).
+ *
+ * @param[in,out] rtlParagraph Layout info for the paragraph with rtl text.
+ */
+void ReorderLayout( TextViewProcessor::ParagraphLayoutInfo& paragraph )
+{
+  // Clear any previous right to left layout.
+  if( NULL != paragraph.mRightToLeftLayout )
+  {
+    paragraph.mRightToLeftLayout->Clear();
+    paragraph.mRightToLeftLayout->mPreviousLayoutCleared = true;
+  }
+  else
+  {
+    // Create a new right to left layout if there isn't any.
+    paragraph.mRightToLeftLayout = new TextViewProcessor::RightToLeftParagraphLayout();
+  }
+
+  // Reorder Text and Styles.
+
+  // Reserve space for the styles.
+  paragraph.mRightToLeftLayout->mTextStyles.Reserve( paragraph.mTextStyles.Count() );
+
+  // Traverses all the bidirectional info per line.
+  for( Vector<TextProcessor::BidirectionalLineInfo*>::ConstIterator it = paragraph.mBidirectionalLinesInfo.Begin(), endIt = paragraph.mBidirectionalLinesInfo.End(); it != endIt; ++it )
+  {
+    TextProcessor::BidirectionalLineInfo* info( *it );
+
+    const std::size_t characterParagraphIndex = info->mCharacterParagraphIndex;
+    const Vector<int>& visualToLogicalMap = info->mVisualToLogicalMap;
+
+    // The text can be appended as it's already reordered.
+    paragraph.mRightToLeftLayout->mText.Append( info->mText );
+
+    // The visual to logical map needs to be used to reorder the styles.
+    for( std::size_t index = 0u, size = visualToLogicalMap.Count(); index < size; ++index )
+    {
+      paragraph.mRightToLeftLayout->mTextStyles.PushBack( *( paragraph.mTextStyles.Begin() + ( characterParagraphIndex + *( visualToLogicalMap.Begin() + index ) ) ) );
+    }
+  }
+
+  // Reorder Layout Info.
+
+  // Reserve space for the new word layout.
+  paragraph.mRightToLeftLayout->mWordsLayoutInfo.reserve( paragraph.mWordsLayoutInfo.size() );
+
+  // Traverses all the bidirectional info per line.
+  for( Vector<TextProcessor::BidirectionalLineInfo*>::ConstIterator it = paragraph.mBidirectionalLinesInfo.Begin(), endIt = paragraph.mBidirectionalLinesInfo.End(); it != endIt; ++it )
+  {
+    TextProcessor::BidirectionalLineInfo* info( *it );
+
+    // Reserve space for all characters.
+    TextViewProcessor::CharacterLayoutInfoContainer characters;
+    characters.resize( info->mNumberOfCharacters );
+
+    // Uses the visual to logical map to set every character in its new position.
+    for( std::size_t index = 0u; index < info->mNumberOfCharacters; ++index )
+    {
+      SetCharacter( paragraph.mWordsLayoutInfo,
+                    info->mCharacterParagraphIndex + info->mVisualToLogicalMap[index],
+                    *( characters.begin() + index ) );
+    }
+
+    // Sets the new 'x' position for each character.
+    float xPosition = 0.f;
+    for( TextViewProcessor::CharacterLayoutInfoContainer::iterator it = characters.begin(), endIt = characters.end(); it != endIt; ++it )
+    {
+      TextViewProcessor::CharacterLayoutInfo& character( *it );
+
+      character.mPosition.x = xPosition;
+      xPosition += character.mSize.width;
+    }
+
+    // Split the reordered text in words.
+    std::size_t previousPosition = 0u;
+    Vector<std::size_t> positions;
+    TextProcessor::SplitInWords( info->mText, positions );
+
+    // Sets the characters into the words they belong to.
+    for( Vector<size_t>::ConstIterator it = positions.Begin(), endIt = positions.End(); it != endIt; ++it )
+    {
+      const std::size_t position = *it;
+
+      TextViewProcessor::WordLayoutInfo word;
+      word.mCharactersLayoutInfo.insert( word.mCharactersLayoutInfo.end(),
+                                         characters.begin() + previousPosition,
+                                         characters.begin() + position );
+
+      if( !word.mCharactersLayoutInfo.empty() )
+      {
+        // Updates the layout of the word.
+        TextViewProcessor::UpdateLayoutInfo( word );
+
+        paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( word );
+      }
+
+      // white space or new paragraph.
+      TextViewProcessor::WordLayoutInfo space;
+      space.mCharactersLayoutInfo.insert( space.mCharactersLayoutInfo.end(),
+                                          characters.begin() + position,
+                                          characters.begin() + position + 1u );
+
+      TextViewProcessor::UpdateLayoutInfo( space );
+
+      paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( space );
+
+      previousPosition = position + 1u;
+    }
+
+    // The last word.
+    if( previousPosition < paragraph.mRightToLeftLayout->mText.GetLength() )
+    {
+      TextViewProcessor::WordLayoutInfo word;
+      word.mCharactersLayoutInfo.insert( word.mCharactersLayoutInfo.end(),
+                                         characters.begin() + previousPosition,
+                                         characters.end() );
+
+      TextViewProcessor::UpdateLayoutInfo( word );
+
+      paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( word );
+    }
+  }
+}
+
+/**
+ * Creates the bidirectional info needed to reorder each line of the paragraph.
+ *
+ * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info.
+ * @param[in,out] paragraph Layout info for the paragraph.
+ * @param[in] characterGlobalIndex Index to the character within the whole text.
+ * @param[in] lineLayoutInfoIndex Index to the table of lines.
+ */
+void CreateBidirectionalInfoForLines( TextView::RelayoutData& relayoutData,
+                                      TextViewProcessor::ParagraphLayoutInfo& paragraph,
+                                      std::size_t& characterGlobalIndex,
+                                      std::size_t& lineLayoutInfoIndex )
+{
+  const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number or laid out lines.
+  bool lineLayoutEnd = false;            // Whether lineLayoutInfoIndex points at the last laid out line.
+
+  // Clear previously created bidirectional info.
+  paragraph.ClearBidirectionalInfo();
+
+  std::size_t characterParagraphIndex = 0u;   // Index to the character (within the paragraph).
+  for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
+       wordIt != wordEndIt;
+       ++wordIt )
+  {
+    TextViewProcessor::WordLayoutInfo& word( *wordIt );
+
+    for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
+         characterIt != characterEndIt;
+         ++characterIt )
+    {
+      TextProcessor::BidirectionalLineInfo* bidirectionalLineInfo = NULL;
+
+      // Check if there is a new line.
+      const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex );
+
+      if( newLine )
+      {
+        // Point to the next line.
+        ++lineLayoutInfoIndex;
+        if( lineLayoutInfoIndex >= lineLayoutInfoSize )
+        {
+          // Arrived at last line.
+          lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector.
+        }
+
+        // Number of characters of the line.
+        const size_t numberOfCharacters = ( lineLayoutEnd ? relayoutData.mTextLayoutInfo.mNumberOfCharacters : relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex ) - characterGlobalIndex;
+
+        // There is right to left characters in this line. It needs to be reordered.
+        bidirectionalLineInfo = new TextProcessor::BidirectionalLineInfo();
+        bidirectionalLineInfo->mCharacterParagraphIndex = characterParagraphIndex;
+        bidirectionalLineInfo->mNumberOfCharacters = numberOfCharacters;
+
+        // Set all the Text's characters in the visual order and creates the mapping tables.
+        TextProcessor::ReorderLine( paragraph.mBidirectionalParagraphInfo,
+                                    bidirectionalLineInfo );
+
+        paragraph.mBidirectionalLinesInfo.PushBack( bidirectionalLineInfo );
+
+        for( std::size_t index = 0u; index < numberOfCharacters; ++index )
+        {
+          relayoutData.mCharacterLogicalToVisualMap.push_back( characterGlobalIndex + bidirectionalLineInfo->mLogicalToVisualMap[index] );
+          relayoutData.mCharacterVisualToLogicalMap.push_back( characterGlobalIndex + bidirectionalLineInfo->mVisualToLogicalMap[index] );
+        }
+      }
+
+      ++characterGlobalIndex;
+      ++characterParagraphIndex;
+    } // characters
+  } // words
+}
+
+void ReorderRightToLeftLayout( TextView::RelayoutData& relayoutData )
+{
+  // Reset conversion tables shared through public-api
+  relayoutData.mCharacterLogicalToVisualMap.clear();
+  relayoutData.mCharacterVisualToLogicalMap.clear();
+
+  std::size_t characterGlobalIndex = 0u; // Index to the global character (within the whole text).
+  std::size_t lineLayoutInfoIndex = 0u;  // Index to the line info.
+
+  for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end();
+       paragraphIt != paragraphEndIt;
+       ++paragraphIt )
+  {
+    TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt );
+
+    if( NULL != paragraph.mBidirectionalParagraphInfo )
+    {
+      // There is right to left text in this paragraph.
+
+      // Creates the bidirectional info needed to reorder each line of the paragraph.
+      CreateBidirectionalInfoForLines( relayoutData,
+                                       paragraph,
+                                       characterGlobalIndex,
+                                       lineLayoutInfoIndex );
+
+      // Reorder each line of the paragraph
+      ReorderLayout( paragraph );
+    }
+    else
+    {
+      // Identity in case the paragraph has no right to left text.
+      for( std::size_t index = 0u; index < paragraph.mNumberOfCharacters; ++index )
+      {
+        const std::size_t globalIndex = characterGlobalIndex + index;
+        relayoutData.mCharacterLogicalToVisualMap.push_back( globalIndex );
+        relayoutData.mCharacterVisualToLogicalMap.push_back( globalIndex );
+      }
+      characterGlobalIndex += paragraph.mNumberOfCharacters;
+    }
+  } // paragraphs
+}
+
 float CalculateXoffset( Toolkit::Alignment::Type horizontalTextAlignment, float parentWidth, float wholeTextWidth )
 {
   float xOffset( 0.f );
 float CalculateXoffset( Toolkit::Alignment::Type horizontalTextAlignment, float parentWidth, float wholeTextWidth )
 {
   float xOffset( 0.f );
@@ -513,8 +790,11 @@ void UpdateAlignment( const TextView::LayoutParameters& layoutParameters,
   const float textHorizontalOffset = CalculateXoffset( layoutParameters.mHorizontalAlignment, relayoutData.mTextViewSize.width, relayoutData.mTextSizeForRelayoutOption.width );
   const float textVerticalOffset = CalculateYoffset( layoutParameters.mVerticalAlignment, relayoutData.mTextViewSize.height, relayoutData.mTextSizeForRelayoutOption.height );
 
   const float textHorizontalOffset = CalculateXoffset( layoutParameters.mHorizontalAlignment, relayoutData.mTextViewSize.width, relayoutData.mTextSizeForRelayoutOption.width );
   const float textVerticalOffset = CalculateYoffset( layoutParameters.mVerticalAlignment, relayoutData.mTextViewSize.height, relayoutData.mTextSizeForRelayoutOption.height );
 
-  std::size_t lineJustificationIndex = 0u; // Index to the first position of the vector which stores all line justification info.
-  std::size_t infoTableCharacterIndex = 0u;
+  // Index to the global character (within the whole text).
+  std::size_t characterGlobalIndex = 0u;
+
+  // Index to the line info.
+  std::size_t lineLayoutInfoIndex = 0u;
 
   relayoutParameters.mIndices.mParagraphIndex = 0u;
 
 
   relayoutParameters.mIndices.mParagraphIndex = 0u;
 
@@ -527,10 +807,16 @@ void UpdateAlignment( const TextView::LayoutParameters& layoutParameters,
 
     float justificationOffset = 0.f;
 
 
     float justificationOffset = 0.f;
 
+    const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines.
+    bool lineLayoutEnd = false;            // Whether lineLayoutInfoIndex points at the last line.
+
     relayoutParameters.mIndices.mWordIndex = 0u;
 
     relayoutParameters.mIndices.mWordIndex = 0u;
 
-    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
-           endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
+    const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout;
+    TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo;
+
+    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(),
+           endWordLayoutIt = wordsLayoutInfo.end();
          wordLayoutIt != endWordLayoutIt;
          ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
     {
          wordLayoutIt != endWordLayoutIt;
          ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
     {
@@ -541,19 +827,24 @@ void UpdateAlignment( const TextView::LayoutParameters& layoutParameters,
       for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
              endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
            characterLayoutIt != endCharacterLayoutIt;
       for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
              endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
            characterLayoutIt != endCharacterLayoutIt;
-           ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex )
+           ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++characterGlobalIndex )
       {
         TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
 
       {
         TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
 
-        // Calculate line justification offset.
-        if( lineJustificationIndex < relayoutData.mLineJustificationInfo.size() )
+        // Check if there is a new line.
+        const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex );
+
+        if( newLine )
         {
         {
-          const TextView::LineJustificationInfo lineJustificationInfo( *( relayoutData.mLineJustificationInfo.begin() + lineJustificationIndex ) );
+          // Calculate line justification offset.
+          justificationOffset = CalculateJustificationOffset( layoutParameters.mLineJustification, relayoutData.mTextSizeForRelayoutOption.width, relayoutData.mLines[lineLayoutInfoIndex].mSize.width );
 
 
-          if( relayoutParameters.mIndices == lineJustificationInfo.mIndices )
+          // Point to the next line.
+          ++lineLayoutInfoIndex;
+          if( lineLayoutInfoIndex >= lineLayoutInfoSize )
           {
           {
-            justificationOffset = CalculateJustificationOffset( layoutParameters.mLineJustification, relayoutData.mTextSizeForRelayoutOption.width, lineJustificationInfo.mLineLength );
-            ++lineJustificationIndex; // increase the index to point the next position in the vector.
+            // Arrived at last line.
+            lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector.
           }
         }
 
           }
         }
 
@@ -565,7 +856,7 @@ void UpdateAlignment( const TextView::LayoutParameters& layoutParameters,
         // Updates the size and position table for text-input with the alignment offset.
         Vector3 positionOffset( characterLayoutInfo.mPosition );
 
         // Updates the size and position table for text-input with the alignment offset.
         Vector3 positionOffset( characterLayoutInfo.mPosition );
 
-        std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex;
+        std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + characterGlobalIndex;
         Toolkit::TextView::CharacterLayoutInfo& characterTableInfo( *infoTableIt );
 
         characterTableInfo.mPosition.x = positionOffset.x + characterLayoutInfo.mOffset.x;
         Toolkit::TextView::CharacterLayoutInfo& characterTableInfo( *infoTableIt );
 
         characterTableInfo.mPosition.x = positionOffset.x + characterLayoutInfo.mOffset.x;
@@ -646,7 +937,7 @@ void UpdateLayoutInfoTable( Vector4& minMaxXY,
                                                                                characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor ),
                                                                          positionOffset,
                                                                          ( TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType ),
                                                                                characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor ),
                                                                          positionOffset,
                                                                          ( TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType ),
-                                                                         false, // VCC set the correct direction if needed.
+                                                                         false,
                                                                          true,
                                                                          descender );
 
                                                                          true,
                                                                          descender );
 
@@ -657,6 +948,7 @@ void UpdateLayoutInfoTable( Vector4& minMaxXY,
 
 void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters,
                                  TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
 
 void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters,
                                  TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
+                                 const TextStyle& style,
                                  RelayoutParameters& relayoutParameters,
                                  FadeParameters& fadeParameters,
                                  TextView::RelayoutData& relayoutData )
                                  RelayoutParameters& relayoutParameters,
                                  FadeParameters& fadeParameters,
                                  TextView::RelayoutData& relayoutData )
@@ -813,35 +1105,40 @@ void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& lay
     Vector2 startPoint = Vector2::ZERO;
     Vector2 endPoint = Vector2::ZERO;
 
     Vector2 startPoint = Vector2::ZERO;
     Vector2 endPoint = Vector2::ZERO;
 
-    if( NULL == characterLayoutInfo.mGradientInfo )
-    {
-      characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo();
-    }
-
     if( !( rightFadeOut && leftFadeOut ) )
     {
       // Current implementation can't set gradient parameters for a text-actor exceeding at the same time the left and the right boundaries.
       if( rightFadeOut )
       {
     if( !( rightFadeOut && leftFadeOut ) )
     {
       // Current implementation can't set gradient parameters for a text-actor exceeding at the same time the left and the right boundaries.
       if( rightFadeOut )
       {
-        gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
+        gradientColor = style.GetTextColor();
 
         // Calculates gradient coeficients.
         characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mRightAlphaCoeficients.x * position.x + fadeParameters.mRightAlphaCoeficients.y );
         gradientColor.a *= std::max( 0.f, fadeParameters.mRightAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mRightAlphaCoeficients.y );
 
 
         // Calculates gradient coeficients.
         characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mRightAlphaCoeficients.x * position.x + fadeParameters.mRightAlphaCoeficients.y );
         gradientColor.a *= std::max( 0.f, fadeParameters.mRightAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mRightAlphaCoeficients.y );
 
-        startPoint = Vector2( std::max( 0.f, ( fadeParameters.mRightFadeThresholdOffset - position.x ) / size.width ), 0.5f );
-        endPoint = Vector2( std::min( 1.f, ( relayoutData.mTextViewSize.width - position.x ) / size.width ), 0.5f );
+        startPoint = Vector2( std::max( 0.f, std::min( 1.f, ( fadeParameters.mRightFadeThresholdOffset - position.x ) / size.width ) ), 0.5f );
+        endPoint = Vector2( std::min( 1.f, std::max( 0.f, ( relayoutData.mTextViewSize.width - position.x ) / size.width ) ), 0.5f );
+
+        if( NULL == characterLayoutInfo.mGradientInfo )
+        {
+          characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo();
+        }
       }
       else if( leftFadeOut )
       {
       }
       else if( leftFadeOut )
       {
-        gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
+        gradientColor = style.GetTextColor();
 
         // Calculates gradient coeficients.
         characterLayoutInfo.mColorAlpha = std::min( 1.f, fadeParameters.mLeftAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mLeftAlphaCoeficients.y );
         gradientColor.a *= gradientColor.a * std::max( 0.f, fadeParameters.mLeftAlphaCoeficients.x * position.x + fadeParameters.mLeftAlphaCoeficients.y );
 
 
         // Calculates gradient coeficients.
         characterLayoutInfo.mColorAlpha = std::min( 1.f, fadeParameters.mLeftAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mLeftAlphaCoeficients.y );
         gradientColor.a *= gradientColor.a * std::max( 0.f, fadeParameters.mLeftAlphaCoeficients.x * position.x + fadeParameters.mLeftAlphaCoeficients.y );
 
-        startPoint = Vector2( std::max( 0.f, ( fadeParameters.mLeftFadeThresholdOffset - position.x ) / size.width ), 0.5f );
-        endPoint = Vector2( std::min( 1.f, -position.x / size.width ), 0.5f );
+        startPoint = Vector2( std::max( 0.f, std::min( 1.f, ( fadeParameters.mLeftFadeThresholdOffset - position.x ) / size.width ) ), 0.5f );
+        endPoint = Vector2( std::min( 1.f, std::max( 0.f, -position.x / size.width ) ), 0.5f );
+
+        if( NULL == characterLayoutInfo.mGradientInfo )
+        {
+          characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo();
+        }
       }
     }
 
       }
     }
 
@@ -850,31 +1147,44 @@ void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& lay
       // Current implementation can't set gradient parameters for a text-actor exceeding at the same time the top and the bottom boundaries.
       if( bottomFadeOut )
       {
       // Current implementation can't set gradient parameters for a text-actor exceeding at the same time the top and the bottom boundaries.
       if( bottomFadeOut )
       {
-        gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
+        gradientColor = style.GetTextColor();
 
         // Calculates gradient coeficients.
         characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mBottomAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mBottomAlphaCoeficients.y );
         gradientColor.a *= std::max( 0.f, fadeParameters.mBottomAlphaCoeficients.x * position.y + fadeParameters.mBottomAlphaCoeficients.y );
 
 
         // Calculates gradient coeficients.
         characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mBottomAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mBottomAlphaCoeficients.y );
         gradientColor.a *= std::max( 0.f, fadeParameters.mBottomAlphaCoeficients.x * position.y + fadeParameters.mBottomAlphaCoeficients.y );
 
-        startPoint = Vector2( 0.5f, std::max( 0.f, ( fadeParameters.mBottomFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) );
-        endPoint = Vector2( 0.5f, std::min( 1.f, ( relayoutData.mTextViewSize.height - characterPositionMinusHeight ) / size.height ) );
+        startPoint = Vector2( 0.5f, std::max( 0.f, std::min( 1.f, ( fadeParameters.mBottomFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) ) );
+        endPoint = Vector2( 0.5f, std::min( 1.f, std::max( 0.f, ( relayoutData.mTextViewSize.height - characterPositionMinusHeight ) / size.height ) ) );
+
+        if( NULL == characterLayoutInfo.mGradientInfo )
+        {
+          characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo();
+        }
       }
       else if( topFadeOut )
       {
       }
       else if( topFadeOut )
       {
-        gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
+        gradientColor = style.GetTextColor();
 
         // Calculates gradient coeficients.
         characterLayoutInfo.mColorAlpha *= gradientColor.a * std::min( 1.f, fadeParameters.mTopAlphaCoeficients.x * position.y + fadeParameters.mTopAlphaCoeficients.y );
         gradientColor.a *= std::max( 0.f, fadeParameters.mTopAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mTopAlphaCoeficients.y );
 
 
         // Calculates gradient coeficients.
         characterLayoutInfo.mColorAlpha *= gradientColor.a * std::min( 1.f, fadeParameters.mTopAlphaCoeficients.x * position.y + fadeParameters.mTopAlphaCoeficients.y );
         gradientColor.a *= std::max( 0.f, fadeParameters.mTopAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mTopAlphaCoeficients.y );
 
-        startPoint = Vector2( 0.5f, std::max( 0.f, ( fadeParameters.mTopFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) );
-        endPoint = Vector2( 0.5f, std::min( 1.f,  -characterPositionMinusHeight / size.height ) );
+        startPoint = Vector2( 0.5f, std::max( 0.f, std::min( 1.f, ( fadeParameters.mTopFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) ) );
+        endPoint = Vector2( 0.5f, std::min( 1.f,  std::max( 0.f, -characterPositionMinusHeight / size.height ) ) );
+
+        if( NULL == characterLayoutInfo.mGradientInfo )
+        {
+          characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo();
+        }
       }
     }
 
       }
     }
 
-    characterLayoutInfo.mGradientInfo->mGradientColor = gradientColor;
-    characterLayoutInfo.mGradientInfo->mStartPoint = startPoint;
-    characterLayoutInfo.mGradientInfo->mEndPoint = endPoint;
+    if( NULL != characterLayoutInfo.mGradientInfo )
+    {
+      characterLayoutInfo.mGradientInfo->mGradientColor = gradientColor;
+      characterLayoutInfo.mGradientInfo->mStartPoint = startPoint;
+      characterLayoutInfo.mGradientInfo->mEndPoint = endPoint;
+    }
   }
   else
   {
   }
   else
   {
@@ -1034,16 +1344,18 @@ void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters,
   float bearingOffset = 0.f;
 
   // Create ellipsize text-actor.
   float bearingOffset = 0.f;
 
   // Create ellipsize text-actor.
+  std::size_t characterIndex = 0u;
   for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator ellipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.begin(),
          endEllipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.end();
        ellipsizeCharacterLayoutIt != endEllipsizeCharacterLayoutIt;
   for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator ellipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.begin(),
          endEllipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.end();
        ellipsizeCharacterLayoutIt != endEllipsizeCharacterLayoutIt;
-       ++ellipsizeCharacterLayoutIt )
+       ++ellipsizeCharacterLayoutIt, ++characterIndex )
   {
     const TextViewProcessor::CharacterLayoutInfo& ellipsizeCharacterLayoutInfo( *ellipsizeCharacterLayoutIt );
   {
     const TextViewProcessor::CharacterLayoutInfo& ellipsizeCharacterLayoutInfo( *ellipsizeCharacterLayoutIt );
+    const TextStyle& style = *( *( relayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin() + characterIndex ) );
 
     if( isColorGlyph ||
         ( isColorGlyph != ellipsizeCharacterLayoutInfo.mIsColorGlyph ) ||
 
     if( isColorGlyph ||
         ( isColorGlyph != ellipsizeCharacterLayoutInfo.mIsColorGlyph ) ||
-        ( ellipsizeStyle != ellipsizeCharacterLayoutInfo.mStyledText.mStyle ) )
+        ( ellipsizeStyle != style ) )
     {
       // The style is different, so a new text-actor is needed.
       if( !ellipsizeText.IsEmpty() )
     {
       // The style is different, so a new text-actor is needed.
       if( !ellipsizeText.IsEmpty() )
@@ -1061,8 +1373,8 @@ void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters,
       }
 
       // Resets the current ellipsize info.
       }
 
       // Resets the current ellipsize info.
-      ellipsizeText = ellipsizeCharacterLayoutInfo.mStyledText.mText;
-      ellipsizeStyle = ellipsizeCharacterLayoutInfo.mStyledText.mStyle;
+      ellipsizeText = Text( relayoutData.mTextLayoutInfo.mEllipsisText[characterIndex] );
+      ellipsizeStyle = style;
       ellipsizeSize = ellipsizeCharacterLayoutInfo.mSize;
       isColorGlyph = ellipsizeCharacterLayoutInfo.mIsColorGlyph;
 
       ellipsizeSize = ellipsizeCharacterLayoutInfo.mSize;
       isColorGlyph = ellipsizeCharacterLayoutInfo.mIsColorGlyph;
 
@@ -1071,7 +1383,7 @@ void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters,
     else
     {
       // Updates text and size with the new character.
     else
     {
       // Updates text and size with the new character.
-      ellipsizeText.Append( ellipsizeCharacterLayoutInfo.mStyledText.mText );
+      ellipsizeText.Append( relayoutData.mTextLayoutInfo.mEllipsisText[characterIndex] );
       TextViewProcessor::UpdateSize( ellipsizeSize, ellipsizeCharacterLayoutInfo.mSize );
     }
   }
       TextViewProcessor::UpdateSize( ellipsizeSize, ellipsizeCharacterLayoutInfo.mSize );
     }
   }
@@ -1131,8 +1443,11 @@ void EllipsizeLine( const TextView::LayoutParameters& layoutParameters,
 
     std::size_t wordCount = 0u;
 
 
     std::size_t wordCount = 0u;
 
-    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin() + firstIndices.mWordIndex,
-           endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin() + lastIndices.mWordIndex + 1u;
+    const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout;
+    TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo;
+
+    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin() + firstIndices.mWordIndex,
+           endWordLayoutIt = wordsLayoutInfo.begin() + lastIndices.mWordIndex + 1u;
          wordLayoutIt != endWordLayoutIt;
          ++wordLayoutIt, ++wordCount )
     {
          wordLayoutIt != endWordLayoutIt;
          ++wordLayoutIt, ++wordCount )
     {
@@ -1193,9 +1508,13 @@ void SetTextVisible( TextView::RelayoutData& relayoutData )
        ++paragraphLayoutIt )
   {
     TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
        ++paragraphLayoutIt )
   {
     TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
+    std::size_t characterIndex = 0u;
+
+    const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout;
+    TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo;
 
 
-    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
-           endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
+    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(),
+           endWordLayoutIt = wordsLayoutInfo.end();
          wordLayoutIt != endWordLayoutIt;
          ++wordLayoutIt )
     {
          wordLayoutIt != endWordLayoutIt;
          ++wordLayoutIt )
     {
@@ -1204,14 +1523,14 @@ void SetTextVisible( TextView::RelayoutData& relayoutData )
       for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
              endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
            characterLayoutIt != endCharacterLayoutIt;
       for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
              endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
            characterLayoutIt != endCharacterLayoutIt;
-           ++characterLayoutIt )
+           ++characterLayoutIt, ++characterIndex )
       {
         TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
 
         characterLayoutInfo.mIsVisible = true;
         delete characterLayoutInfo.mGradientInfo;
         characterLayoutInfo.mGradientInfo = NULL;
       {
         TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
 
         characterLayoutInfo.mIsVisible = true;
         delete characterLayoutInfo.mGradientInfo;
         characterLayoutInfo.mGradientInfo = NULL;
-        characterLayoutInfo.mColorAlpha = characterLayoutInfo.mStyledText.mStyle.GetTextColor().a;
+        characterLayoutInfo.mColorAlpha = ( *( paragraphLayoutInfo.mTextStyles.Begin() + characterIndex ) )->GetTextColor().a;
       } // end characters
     } // end words
   } // end paragraphs
       } // end characters
     } // end words
   } // end paragraphs
@@ -1272,10 +1591,14 @@ void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters
   {
     TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
 
   {
     TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
 
+    std::size_t characterIndex = 0u;
     relayoutParameters.mIndices.mWordIndex = 0u;
 
     relayoutParameters.mIndices.mWordIndex = 0u;
 
-    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
-           endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
+    const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout;
+    TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo;
+
+    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(),
+           endWordLayoutIt = wordsLayoutInfo.end();
          wordLayoutIt != endWordLayoutIt;
          ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
     {
          wordLayoutIt != endWordLayoutIt;
          ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
     {
@@ -1288,7 +1611,7 @@ void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters
       for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
              endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
            characterLayoutIt != endCharacterLayoutIt;
       for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
              endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
            characterLayoutIt != endCharacterLayoutIt;
-           ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex )
+           ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex, ++characterIndex )
       {
         TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
 
       {
         TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
 
@@ -1298,6 +1621,7 @@ void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters
         // Calculates the visibility for the current character.
         CalculateVisibilityForFade( layoutParameters,
                                     characterLayoutInfo,
         // Calculates the visibility for the current character.
         CalculateVisibilityForFade( layoutParameters,
                                     characterLayoutInfo,
+                                    *( *( paragraphLayoutInfo.mTextStyles.Begin() + characterIndex ) ),
                                     relayoutParameters,
                                     fadeParameters,
                                     relayoutData );
                                     relayoutParameters,
                                     fadeParameters,
                                     relayoutData );
@@ -1524,7 +1848,12 @@ void CreateTextActor( const TextView::VisualParameters& visualParameters,
   // Set the text-actor for the current traversed text.
   if( currentTextActorInfo.textActor )
   {
   // Set the text-actor for the current traversed text.
   if( currentTextActorInfo.textActor )
   {
-    currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
+    if( ( NULL != currentTextActorInfo.characterLayout ) &&
+        currentTextActorInfo.characterLayout->mSetText )
+    {
+      currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
+      currentTextActorInfo.characterLayout->mSetText = false;
+    }
     currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
     currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
 
     currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
     currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
 
@@ -1534,8 +1863,18 @@ void CreateTextActor( const TextView::VisualParameters& visualParameters,
                          paragraph.mSize.height );
   }
 
                          paragraph.mSize.height );
   }
 
+  float rightToLeftOffset = 0.f;
+  if( character.IsWhiteSpace() )
+  {
+    // In left to right text, a word never starts with a white space but
+    // it may happen in right to left text as the text is reversed.
+    // The text alignment and justification offset is calculated without this white space.
+    // It causes a missalignment which can be corrected by removing the size of the white space.
+    rightToLeftOffset = characterLayout.mSize.width * relayoutData.mShrinkFactor;
+  }
+
   currentTextActorInfo.text = Text( character );
   currentTextActorInfo.text = Text( character );
-  currentTextActorInfo.position = Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x,
+  currentTextActorInfo.position = Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x - rightToLeftOffset,
                                            characterLayout.mPosition.y + characterLayout.mOffset.y,
                                            characterLayout.mPosition.z );
   currentTextActorInfo.size = characterLayout.mSize * relayoutData.mShrinkFactor;
                                            characterLayout.mPosition.y + characterLayout.mOffset.y,
                                            characterLayout.mPosition.z );
   currentTextActorInfo.size = characterLayout.mSize * relayoutData.mShrinkFactor;
@@ -1543,8 +1882,6 @@ void CreateTextActor( const TextView::VisualParameters& visualParameters,
   currentTextActorInfo.color = style.GetTextColor();
   currentTextActorInfo.color.a = characterLayout.mColorAlpha;
 
   currentTextActorInfo.color = style.GetTextColor();
   currentTextActorInfo.color.a = characterLayout.mColorAlpha;
 
-  currentTextActorInfo.gradientInfo = characterLayout.mGradientInfo;
-
   TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor );
 
   if( createGlyphActors )
   TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor );
 
   if( createGlyphActors )
@@ -1570,6 +1907,9 @@ void CreateTextActor( const TextView::VisualParameters& visualParameters,
         textActor.SetTextStyle( style );
       }
     }
         textActor.SetTextStyle( style );
       }
     }
+    characterLayout.mSetText = true;
+    currentTextActorInfo.characterLayout = &characterLayout;
+
     characterLayout.mGlyphActor = textActor;
   }
 
     characterLayout.mGlyphActor = textActor;
   }
 
@@ -1589,12 +1929,13 @@ void CreateTextActor( const TextView::VisualParameters& visualParameters,
  */
 void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualParameters,
                                       TextView::RelayoutData& relayoutData,
  */
 void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualParameters,
                                       TextView::RelayoutData& relayoutData,
-                                      TextViewProcessor::ParagraphLayoutInfo& paragraph,
+                                      TextViewProcessor::ParagraphLayoutInfo& paragraphLayout,
                                       std::size_t& characterGlobalIndex,
                                       std::size_t& lineLayoutInfoIndex,
                                       bool createGlyphActors )
 {
   CurrentTextActorInfo currentTextActorInfo;
                                       std::size_t& characterGlobalIndex,
                                       std::size_t& lineLayoutInfoIndex,
                                       bool createGlyphActors )
 {
   CurrentTextActorInfo currentTextActorInfo;
+  currentTextActorInfo.characterLayout = NULL;
 
   const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines.
   bool lineLayoutEnd = false;            // Whether lineLayoutInfoIndex points at the last line.
 
   const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines.
   bool lineLayoutEnd = false;            // Whether lineLayoutInfoIndex points at the last line.
@@ -1610,14 +1951,24 @@ void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualPa
 
   std::vector<TextActor> textActorsToRemove; // Keep a vector of text-actors to be included into the cache.
 
 
   std::vector<TextActor> textActorsToRemove; // Keep a vector of text-actors to be included into the cache.
 
+  // Retrieve the layout info to traverse. If there is right to left text it retrieves the right to left layout.
+  const bool isRightToLeftLayout = NULL != paragraphLayout.mRightToLeftLayout;
+
+  TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayout.mWordsLayoutInfo;
+  Text& text = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mText : paragraphLayout.mText;
+  Vector<TextStyle*>& textStyles = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mTextStyles : paragraphLayout.mTextStyles;
+
+  // In case the previous right to left layout has been cleared, all text-actors have been removed as well. If this bool is set to true, text-actors will be created again.
+  const bool previousRightToLeftLayoutCleared = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mPreviousLayoutCleared : false;
+
   std::size_t characterParagraphIndex = 0u;   // Index to the character (within the paragraph).
   std::size_t characterParagraphIndex = 0u;   // Index to the character (within the paragraph).
-  for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
+  for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end();
        wordIt != wordEndIt;
        ++wordIt )
   {
        wordIt != wordEndIt;
        ++wordIt )
   {
-    TextViewProcessor::WordLayoutInfo& word( *wordIt );
+    TextViewProcessor::WordLayoutInfo& wordLayout( *wordIt );
 
 
-    for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
+    for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = wordLayout.mCharactersLayoutInfo.begin(), characterEndIt = wordLayout.mCharactersLayoutInfo.end();
          characterIt != characterEndIt;
          ++characterIt )
     {
          characterIt != characterEndIt;
          ++characterIt )
     {
@@ -1639,14 +1990,14 @@ void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualPa
       }
 
       // Do not create a glyph-actor if there is no text.
       }
 
       // Do not create a glyph-actor if there is no text.
-      const Character character = characterLayout.mStyledText.mText[0u]; // there are only one character per character layout.
-      const TextStyle& style = characterLayout.mStyledText.mStyle;
+      const Character character = text[characterParagraphIndex];
+      const TextStyle& style = *( *( textStyles.Begin() + characterParagraphIndex ) );
 
       bool appendCharacter = false;
 
       if( characterLayout.mIsColorGlyph ||
 
       bool appendCharacter = false;
 
       if( characterLayout.mIsColorGlyph ||
-          !character.IsWhiteSpace() || // A new paragraph character is also a white space.
-          ( character.IsWhiteSpace() && style.IsUnderlineEnabled() ) )
+          ( TextViewProcessor::NoSeparator == wordLayout.mType ) ||
+          ( ( TextViewProcessor::WordSeparator == wordLayout.mType ) && style.IsUnderlineEnabled() ) )
       {
         // Do not create a glyph-actor if it's a white space (without underline) or a new paragraph character.
 
       {
         // Do not create a glyph-actor if it's a white space (without underline) or a new paragraph character.
 
@@ -1673,9 +2024,6 @@ void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualPa
           characterLayout.mSetText = false;
           characterLayout.mSetStyle = false;
 
           characterLayout.mSetText = false;
           characterLayout.mSetStyle = false;
 
-          // There is a new style or a new line.
-          glyphActorCreatedForLine = true;
-
           if( characterLayout.mIsColorGlyph )
           {
             CreateEmoticon( visualParameters,
           if( characterLayout.mIsColorGlyph )
           {
             CreateEmoticon( visualParameters,
@@ -1686,14 +2034,17 @@ void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualPa
           {
             CreateTextActor( visualParameters,
                              relayoutData,
           {
             CreateTextActor( visualParameters,
                              relayoutData,
-                             paragraph,
+                             paragraphLayout,
                              characterLayout,
                              character,
                              style,
                              currentTextActorInfo,
                              characterLayout,
                              character,
                              style,
                              currentTextActorInfo,
-                             createGlyphActors );
+                             createGlyphActors || previousRightToLeftLayoutCleared );
           }
 
           }
 
+          // There is a new style or a new line.
+          glyphActorCreatedForLine = true;
+
           // Update style to be checked with next characters.
           currentStyle = style;
           currentGradientInfo = characterLayout.mGradientInfo;
           // Update style to be checked with next characters.
           currentStyle = style;
           currentGradientInfo = characterLayout.mGradientInfo;
@@ -1734,7 +2085,7 @@ void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualPa
       if( appendCharacter )
       {
         // Add the character to the current text-actor and update the size.
       if( appendCharacter )
       {
         // Add the character to the current text-actor and update the size.
-        if( characterLayout.mIsVisible && ( TextViewProcessor::ParagraphSeparator != word.mType ) )
+        if( characterLayout.mIsVisible && ( TextViewProcessor::ParagraphSeparator != wordLayout.mType ) )
         {
           currentTextActorInfo.text.Append( character );
 
         {
           currentTextActorInfo.text.Append( character );
 
@@ -1753,14 +2104,19 @@ void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualPa
   {
     if( currentTextActorInfo.textActor )
     {
   {
     if( currentTextActorInfo.textActor )
     {
-      currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
+      if( ( NULL != currentTextActorInfo.characterLayout ) &&
+          currentTextActorInfo.characterLayout->mSetText )
+      {
+        currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
+        currentTextActorInfo.characterLayout->mSetText = false;
+      }
       currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
       currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
 
       SetVisualParameters( currentTextActorInfo,
                            visualParameters,
                            relayoutData,
       currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
       currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
 
       SetVisualParameters( currentTextActorInfo,
                            visualParameters,
                            relayoutData,
-                           paragraph.mSize.height );
+                           paragraphLayout.mSize.height );
     }
   }
 
     }
   }
 
@@ -1827,7 +2183,12 @@ void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelay
   {
     TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt );
 
   {
     TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt );
 
-    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
+    std::size_t characterIndex = 0u;
+
+    const bool isRightToLeftLayout = NULL != paragraph.mRightToLeftLayout;
+    TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraph.mRightToLeftLayout->mWordsLayoutInfo : paragraph.mWordsLayoutInfo;
+
+    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end();
          wordIt != wordEndIt;
          ++wordIt )
     {
          wordIt != wordEndIt;
          ++wordIt )
     {
@@ -1835,9 +2196,10 @@ void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelay
 
       for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
            characterIt != characterEndIt;
 
       for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
            characterIt != characterEndIt;
-           ++characterIt )
+           ++characterIt, ++characterIndex )
       {
         TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
       {
         TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
+        const TextStyle& style = *( *( paragraph.mTextStyles.Begin() + characterIndex ) );
 
         // Check if current character is the first of a new line
         const bool isNewLine = ( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() ) &&
 
         // Check if current character is the first of a new line
         const bool isNewLine = ( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() ) &&
@@ -1847,7 +2209,7 @@ void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelay
           ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
         }
 
           ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
         }
 
-        if( character.mStyledText.mStyle.IsUnderlineEnabled() )
+        if( style.IsUnderlineEnabled() )
         {
           if( !textUnderlineStatus.mCurrentUnderlineStatus || // Current character is underlined but previous one it wasn't.
               isNewLine )                                     // Current character is underlined and is the first of current line.
         {
           if( !textUnderlineStatus.mCurrentUnderlineStatus || // Current character is underlined but previous one it wasn't.
               isNewLine )                                     // Current character is underlined and is the first of current line.
@@ -1927,8 +2289,12 @@ void SetUnderlineInfo( TextView::RelayoutData& relayoutData )
        ++paragraphIt )
   {
     TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt );
        ++paragraphIt )
   {
     TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt );
+    std::size_t characterIndex = 0u;
+
+    const bool isRightToLeftLayout = NULL != paragraph.mRightToLeftLayout;
+    TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraph.mRightToLeftLayout->mWordsLayoutInfo : paragraph.mWordsLayoutInfo;
 
 
-    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
+    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end();
          wordIt != wordEndIt;
          ++wordIt )
     {
          wordIt != wordEndIt;
          ++wordIt )
     {
@@ -1936,9 +2302,10 @@ void SetUnderlineInfo( TextView::RelayoutData& relayoutData )
 
       for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
            characterIt != characterEndIt;
 
       for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
            characterIt != characterEndIt;
-           ++characterIt )
+           ++characterIt, ++characterIndex )
       {
         TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
       {
         TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
+        TextStyle& style = *( *( paragraph.mTextStyles.Begin() + characterIndex ) );
 
         // Check if current character is the first of a new line
 
 
         // Check if current character is the first of a new line
 
@@ -1957,7 +2324,7 @@ void SetUnderlineInfo( TextView::RelayoutData& relayoutData )
           }
         }
 
           }
         }
 
-        if( character.mStyledText.mStyle.IsUnderlineEnabled() )
+        if( style.IsUnderlineEnabled() )
         {
           if( textUnderlineStatus.mCurrentUnderlineStatus )
           {
         {
           if( textUnderlineStatus.mCurrentUnderlineStatus )
           {
@@ -1982,7 +2349,7 @@ void SetUnderlineInfo( TextView::RelayoutData& relayoutData )
           const float positionOffset = ( underlineInfo.mMaxHeight - character.mSize.height ) - bearingOffset;
 
           // Sets the underline's parameters.
           const float positionOffset = ( underlineInfo.mMaxHeight - character.mSize.height ) - bearingOffset;
 
           // Sets the underline's parameters.
-          character.mStyledText.mStyle.SetUnderline( true, underlineInfo.mMaxThickness, underlineInfo.mPosition - positionOffset );
+          style.SetUnderline( true, underlineInfo.mMaxThickness, underlineInfo.mPosition - positionOffset );
 
           // Mark the character to be set the new style into the text-actor.
           character.mSetStyle = true;
 
           // Mark the character to be set the new style into the text-actor.
           character.mSetStyle = true;
@@ -2038,8 +2405,12 @@ void InsertToTextView( Actor textView,
   {
     TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
 
   {
     TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
 
-    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
-           endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
+    // Retrieve the layout info to traverse. If there is right to left text it retrieves the right to left layout.
+    const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout;
+    TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo;
+
+    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(),
+           endWordLayoutIt = wordsLayoutInfo.end();
          wordLayoutIt != endWordLayoutIt;
          ++wordLayoutIt )
     {
          wordLayoutIt != endWordLayoutIt;
          ++wordLayoutIt )
     {
index aff3ae3..5150186 100644 (file)
@@ -19,8 +19,9 @@
  */
 
 // INTERNAL INCLUDES
  */
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/alignment/alignment.h>
+#include <dali-toolkit/public-api/controls/text-view/text-view.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-impl.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-impl.h>
-#include <dali-toolkit/internal/controls/text-view/text-view-processor-types.h>
 
 namespace Dali
 {
 
 namespace Dali
 {
@@ -265,6 +266,13 @@ void CalculateLineLayout( float parentWidth,
                           LineLayoutInfo& layoutInfo );
 
 /**
                           LineLayoutInfo& layoutInfo );
 
 /**
+ * Reorders the text layout of each line of each paragraph of the text.
+ *
+ * @param[in,out] relayoutData The text-view's data structures.
+ */
+void ReorderRightToLeftLayout( TextView::RelayoutData& relayoutData );
+
+/**
  * Calculates the \e x offset position for the whole text.
  *
  * @param[in] horizontalTextAlignment The horizontal alignment type.
  * Calculates the \e x offset position for the whole text.
  *
  * @param[in] horizontalTextAlignment The horizontal alignment type.
@@ -358,12 +366,14 @@ void UpdateLayoutInfoTable( Vector4& minMaxXY,
  *
  * @param[in] layoutParameters The layout parameters.
  * @param[in] characterLayoutInfo Character layout info.
  *
  * @param[in] layoutParameters The layout parameters.
  * @param[in] characterLayoutInfo Character layout info.
+ * @param[in] style The style of the character. Used to get the color (and alpha) of the character.
  * @param[in,out] relayoutParameters Temporary layout parameters.
  * @param[in,out] fadeParameters Temporary fade parameters.
  * @param[in,out] relayoutData The text-view's data structures.
  */
 void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters,
                                  TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
  * @param[in,out] relayoutParameters Temporary layout parameters.
  * @param[in,out] fadeParameters Temporary fade parameters.
  * @param[in,out] relayoutData The text-view's data structures.
  */
 void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters,
                                  TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
+                                 const TextStyle& style,
                                  RelayoutParameters& relayoutParameters,
                                  FadeParameters& fadeParameters,
                                  TextView::RelayoutData& relayoutData );
                                  RelayoutParameters& relayoutParameters,
                                  FadeParameters& fadeParameters,
                                  TextView::RelayoutData& relayoutData );
@@ -391,7 +401,11 @@ void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters,
                                TextView::RelayoutData& relayoutData );
 
 /**
                                TextView::RelayoutData& relayoutData );
 
 /**
+ * Replace the text which exceeds the boundary by the ellipsis text.
  *
  *
+ * @param[in] layoutParameters The layout parameters.
+ * @param[in,out] ellipsisParameters Temporary ellipsis parameters.
+ * @param[in,out] relayoutData The text-view's data structures.
  */
 void EllipsizeLine( const TextView::LayoutParameters& layoutParameters,
                     EllipsizeParameters& ellipsizeParameters,
  */
 void EllipsizeLine( const TextView::LayoutParameters& layoutParameters,
                     EllipsizeParameters& ellipsizeParameters,
index 10933a7..613b0a6 100644 (file)
@@ -72,14 +72,6 @@ Vector3 NoShrinkWhenExceedPosition( const TextViewRelayout::RelayoutParameters&
                                              1.f, // Shrink factor
                                              subLineInfo );
 
                                              1.f, // Shrink factor
                                              subLineInfo );
 
-      // Stores some info to calculate the line justification in a post-process.
-      TextView::LineJustificationInfo justificationInfo;
-
-      justificationInfo.mIndices = relayoutParameters.mIndices;
-      justificationInfo.mLineLength = subLineInfo.mLineLength;
-
-      relayoutData.mLineJustificationInfo.push_back( justificationInfo );
-
       Toolkit::TextView::LineLayoutInfo lineInfo;
       lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;    // Index to the first character of the next line.
       lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
       Toolkit::TextView::LineLayoutInfo lineInfo;
       lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;    // Index to the first character of the next line.
       lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
@@ -234,10 +226,11 @@ void Relayout( Actor textView,
 {
   if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
   {
 {
   if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
   {
-    relayoutData.mLineJustificationInfo.clear();
     CalculateSizeAndPosition( layoutParameters,
                               relayoutData );
 
     CalculateSizeAndPosition( layoutParameters,
                               relayoutData );
 
+    TextViewRelayout::ReorderRightToLeftLayout( relayoutData );
+
     TextViewRelayout::SetUnderlineInfo( relayoutData );
   }
 
     TextViewRelayout::SetUnderlineInfo( relayoutData );
   }
 
index 98ee6b8..f74966d 100644 (file)
@@ -71,14 +71,6 @@ Vector3 SplitPosition( const TextViewRelayout::RelayoutParameters& relayoutParam
                                              1.f, // Shrink factor
                                              subLineInfo );
 
                                              1.f, // Shrink factor
                                              subLineInfo );
 
-      // Stores some info to calculate the line justification in a post-process.
-      TextView::LineJustificationInfo justificationInfo;
-
-      justificationInfo.mIndices = relayoutParameters.mIndices;
-      justificationInfo.mLineLength = subLineInfo.mLineLength;
-
-      relayoutData.mLineJustificationInfo.push_back( justificationInfo );
-
       Toolkit::TextView::LineLayoutInfo lineInfo;
       lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;    // Index to the first character of the next line.
       lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
       Toolkit::TextView::LineLayoutInfo lineInfo;
       lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;    // Index to the first character of the next line.
       lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
@@ -158,22 +150,6 @@ void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameter
       relayoutParameters.mWordSize = wordLayoutInfo.mSize;
       relayoutParameters.mIndices.mCharacterIndex = 0u;
 
       relayoutParameters.mWordSize = wordLayoutInfo.mSize;
       relayoutParameters.mIndices.mCharacterIndex = 0u;
 
-      if( relayoutParameters.mIsNewLine )
-      {
-        // Stores some info to calculate the line justification in a post-process.
-        const bool isSplitOriginal = layoutParameters.mExceedPolicy == TextView::SplitOriginal;
-
-        if( !isSplitOriginal )
-        {
-          TextView::LineJustificationInfo justificationInfo;
-
-          justificationInfo.mIndices = relayoutParameters.mIndices;
-          justificationInfo.mLineLength = relayoutParameters.mParagraphSize.width;
-
-          relayoutData.mLineJustificationInfo.push_back( justificationInfo );
-        }
-      }
-
       for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
              endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
            characterLayoutIt != endCharacterLayoutIt;
       for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
              endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
            characterLayoutIt != endCharacterLayoutIt;
@@ -290,10 +266,11 @@ void Relayout( Actor textView,
 {
   if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
   {
 {
   if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
   {
-    relayoutData.mLineJustificationInfo.clear();
     CalculateSizeAndPosition( layoutParameters,
                               relayoutData );
 
     CalculateSizeAndPosition( layoutParameters,
                               relayoutData );
 
+    TextViewRelayout::ReorderRightToLeftLayout( relayoutData );
+
     TextViewRelayout::SetUnderlineInfo( relayoutData );
   }
 
     TextViewRelayout::SetUnderlineInfo( relayoutData );
   }
 
index 4081150..b5bd9f6 100644 (file)
@@ -83,14 +83,6 @@ Vector3 OriginalPosition( const TextViewRelayout::RelayoutParameters& relayoutPa
         }
       }
 
         }
       }
 
-      // Stores some info to calculate the line justification in a post-process.
-      TextView::LineJustificationInfo justificationInfo;
-
-      justificationInfo.mIndices = relayoutParameters.mIndices;
-      justificationInfo.mLineLength = subLineInfo.mLineLength;
-
-      relayoutData.mLineJustificationInfo.push_back( justificationInfo );
-
       Toolkit::TextView::LineLayoutInfo lineInfo;
       lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;    // Index to the first character of the next line.
       lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
       Toolkit::TextView::LineLayoutInfo lineInfo;
       lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;    // Index to the first character of the next line.
       lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
@@ -147,14 +139,6 @@ Vector3 SplitWhenExceedPosition( const TextViewRelayout::RelayoutParameters& rel
                                              1.f, // Shrink factor.
                                              subLineInfo );
 
                                              1.f, // Shrink factor.
                                              subLineInfo );
 
-      // Stores some info to calculate the line justification in a post-process.
-      TextView::LineJustificationInfo justificationInfo;
-
-      justificationInfo.mIndices = relayoutParameters.mIndices;
-      justificationInfo.mLineLength = subLineInfo.mLineLength;
-
-      relayoutData.mLineJustificationInfo.push_back( justificationInfo );
-
       Toolkit::TextView::LineLayoutInfo lineInfo;
       lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;    // Index to the first character of the next line.
       lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
       Toolkit::TextView::LineLayoutInfo lineInfo;
       lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;    // Index to the first character of the next line.
       lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
@@ -211,14 +195,6 @@ Vector3 ShrinkWidthWhenExceedPosition( const TextViewRelayout::RelayoutParameter
                                              relayoutData.mShrinkFactor,
                                              subLineInfo );
 
                                              relayoutData.mShrinkFactor,
                                              subLineInfo );
 
-      // Stores some info to calculate the line justification in a post-process.
-      TextView::LineJustificationInfo justificationInfo;
-
-      justificationInfo.mIndices = relayoutParameters.mIndices;
-      justificationInfo.mLineLength = subLineInfo.mLineLength;
-
-      relayoutData.mLineJustificationInfo.push_back( justificationInfo );
-
       Toolkit::TextView::LineLayoutInfo lineInfo;
       lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;    // Index to the first character of the next line.
       lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
       Toolkit::TextView::LineLayoutInfo lineInfo;
       lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;    // Index to the first character of the next line.
       lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
@@ -242,8 +218,6 @@ void CalculatePositionsForShrinkWhenExceed( TextView::RelayoutData& relayoutData
   const float parentWidth = relayoutData.mTextViewSize.width;
   TextViewProcessor::TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo;
 
   const float parentWidth = relayoutData.mTextViewSize.width;
   TextViewProcessor::TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo;
 
-  relayoutData.mLineJustificationInfo.clear();
-
   // Reset the text height. This value is returned in order to shrink further or not the text.
   newTextHeight = 0.f;
 
   // Reset the text height. This value is returned in order to shrink further or not the text.
   newTextHeight = 0.f;
 
@@ -332,14 +306,6 @@ void CalculatePositionsForShrinkWhenExceed( TextView::RelayoutData& relayoutData
           lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
           lineInfo.mAscender = subLineInfo.mMaxAscender;                                // Ascender of this piece of paragraph.
           relayoutData.mLines.push_back( lineInfo );
           lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
           lineInfo.mAscender = subLineInfo.mMaxAscender;                                // Ascender of this piece of paragraph.
           relayoutData.mLines.push_back( lineInfo );
-
-          // Stores some info to calculate the line justification in a post-process.
-          TextView::LineJustificationInfo justificationInfo;
-
-          justificationInfo.mIndices = indices;
-          justificationInfo.mLineLength = subLineInfo.mLineLength;
-
-          relayoutData.mLineJustificationInfo.push_back( justificationInfo );
         }
         else
         {
         }
         else
         {
@@ -618,10 +584,11 @@ void Relayout( Actor textView,
 {
   if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
   {
 {
   if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
   {
-    relayoutData.mLineJustificationInfo.clear();
     CalculateSizeAndPosition( layoutParameters,
                               relayoutData );
 
     CalculateSizeAndPosition( layoutParameters,
                               relayoutData );
 
+    TextViewRelayout::ReorderRightToLeftLayout( relayoutData );
+
     TextViewRelayout::SetUnderlineInfo( relayoutData );
   }
 
     TextViewRelayout::SetUnderlineInfo( relayoutData );
   }
 
diff --git a/base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp b/base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp
new file mode 100644 (file)
index 0000000..8131b47
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2014 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.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace TextProcessor
+{
+
+BidirectionalParagraphInfo::BidirectionalParagraphInfo()
+: mDirection( FRIBIDI_TYPE_ON ),
+  mCharactersTypeBuffer(),
+  mLevelsBuffer(),
+  mLogicalUnicodeBuffer()
+{
+}
+
+BidirectionalParagraphInfo::~BidirectionalParagraphInfo()
+{
+}
+
+BidirectionalParagraphInfo::BidirectionalParagraphInfo( const BidirectionalParagraphInfo& info )
+: mDirection( info.mDirection ),
+  mCharactersTypeBuffer( info.mCharactersTypeBuffer ),
+  mLevelsBuffer( info.mLevelsBuffer ),
+  mLogicalUnicodeBuffer( info.mLogicalUnicodeBuffer )
+{
+}
+
+BidirectionalParagraphInfo& BidirectionalParagraphInfo::operator=( const BidirectionalParagraphInfo& info )
+{
+  if( this != &info )
+  {
+    mDirection = info.mDirection;
+    mCharactersTypeBuffer = info.mCharactersTypeBuffer;
+    mLevelsBuffer = info.mLevelsBuffer;
+    mLogicalUnicodeBuffer = info.mLogicalUnicodeBuffer;
+  }
+
+  return *this;
+}
+
+BidirectionalLineInfo::BidirectionalLineInfo()
+: mCharacterParagraphIndex(),
+  mNumberOfCharacters(),
+  mText(),
+  mVisualToLogicalMap(),
+  mLogicalToVisualMap()
+{
+}
+
+BidirectionalLineInfo::~BidirectionalLineInfo()
+{
+}
+
+BidirectionalLineInfo::BidirectionalLineInfo( const BidirectionalLineInfo& info )
+: mCharacterParagraphIndex( info.mCharacterParagraphIndex ),
+  mNumberOfCharacters( info.mNumberOfCharacters ),
+  mText( info.mText ),
+  mVisualToLogicalMap( info.mVisualToLogicalMap ),
+  mLogicalToVisualMap( info.mLogicalToVisualMap )
+{
+}
+
+BidirectionalLineInfo& BidirectionalLineInfo::operator=( const BidirectionalLineInfo& info )
+{
+  if( this != &info )
+  {
+    mCharacterParagraphIndex = info.mCharacterParagraphIndex;
+    mNumberOfCharacters = info.mNumberOfCharacters;
+    mText = info.mText;
+    mVisualToLogicalMap = info.mVisualToLogicalMap;
+    mLogicalToVisualMap = info.mLogicalToVisualMap;
+  }
+
+  return *this;
+}
+
+bool BeginsRightToLeftCharacter( const Text& text )
+{
+  for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
+  {
+    Character::CharacterDirection direction = text[i].GetCharacterDirection();
+    if( direction != Character::Neutral )
+    {
+      return ( direction == Character::RightToLeft || direction == Character::RightToLeftWeak );
+    }
+  }
+
+  return false;
+}
+
+bool ContainsRightToLeftCharacter( const Dali::Text& text )
+{
+  for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
+  {
+    Character::CharacterDirection direction = ( text[i] ).GetCharacterDirection();
+    if( ( Character::RightToLeft == direction ) || ( Character::RightToLeftWeak == direction ) )
+    {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void ProcessBidirectionalText( Text& paragraph, BidirectionalParagraphInfo* info )
+{
+  if( paragraph.IsEmpty() )
+  {
+    // nothing to do if the paragraph is empty.
+    return;
+  }
+
+  const std::size_t stringSize = paragraph.GetText().size();
+
+  // Text buffer in logical order. Coded in unicode.
+  info->mLogicalUnicodeBuffer.resize( stringSize + 1u, 0u );
+  FriBidiChar* logicalUnicodeBufferPointer = &info->mLogicalUnicodeBuffer[0u];
+
+  // Converts from utf8 to unicode.
+  const std::size_t length = fribidi_charset_to_unicode( FRIBIDI_CHAR_SET_UTF8, paragraph.GetText().c_str(), stringSize, logicalUnicodeBufferPointer );
+
+  // Character type buffer.
+  info->mCharactersTypeBuffer.resize( length, 0u );
+
+  // Levels buffer.
+  info->mLevelsBuffer.resize( length, 0u );
+
+  // Joining type buffer.
+  std::vector<FriBidiJoiningType> joiningTypeBuffer;
+  joiningTypeBuffer.resize( length, 0u );
+
+  // Pointers to the buffers.
+  FriBidiCharType* charactersTypeBufferPointer = &info->mCharactersTypeBuffer[0u];
+  FriBidiLevel* levelsBufferPointer = &info->mLevelsBuffer[0u];
+  FriBidiJoiningType* joiningTypeBufferPointer = &joiningTypeBuffer[0u];
+
+  // Retrieves the type of each character.
+  fribidi_get_bidi_types( logicalUnicodeBufferPointer, length, charactersTypeBufferPointer );
+
+  // Retrieves the paragraph direction.
+  info->mDirection = fribidi_get_par_direction( charactersTypeBufferPointer, length );
+
+  // Retrieve the embedding levels.
+  fribidi_get_par_embedding_levels( charactersTypeBufferPointer, length, &info->mDirection, levelsBufferPointer );
+
+  // Retrieve the joining types.
+  fribidi_get_joining_types( logicalUnicodeBufferPointer, length, joiningTypeBufferPointer );
+
+  fribidi_join_arabic( charactersTypeBufferPointer, length, levelsBufferPointer, joiningTypeBufferPointer );
+
+  const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC;
+
+  fribidi_shape( flags, levelsBufferPointer, length, joiningTypeBufferPointer, logicalUnicodeBufferPointer );
+
+  std::vector<char> bidiTextConverted;
+
+  bidiTextConverted.resize( length * 4u + 1u ); // Maximum bytes to represent one UTF-8 character is 6.
+                                                // Currently Dali doesn't support this UTF-8 extension. Dali only supports 'regular' UTF-8 which has a maximum of 4 bytes per character.
+
+  fribidi_unicode_to_charset( FRIBIDI_CHAR_SET_UTF8, logicalUnicodeBufferPointer, length, &bidiTextConverted[0] );
+
+  paragraph = Text( &bidiTextConverted[0u] );
+}
+
+void ReorderLine( BidirectionalParagraphInfo* paragraphInfo,
+                  BidirectionalLineInfo* lineInfo )
+{
+  const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC;
+
+  lineInfo->mVisualToLogicalMap.Resize( lineInfo->mNumberOfCharacters, 0u );
+  lineInfo->mLogicalToVisualMap.Resize( lineInfo->mNumberOfCharacters, 0u );
+
+  std::vector<FriBidiChar> visualUnicodeBuffer;
+  visualUnicodeBuffer.insert( visualUnicodeBuffer.end(),
+                              paragraphInfo->mLogicalUnicodeBuffer.begin() + lineInfo->mCharacterParagraphIndex,
+                              paragraphInfo->mLogicalUnicodeBuffer.begin() + ( lineInfo->mCharacterParagraphIndex + lineInfo->mNumberOfCharacters ) );
+
+  // Pointers to the buffers.
+  FriBidiCharType* charactersTypeBufferPointer = &paragraphInfo->mCharactersTypeBuffer[lineInfo->mCharacterParagraphIndex];
+  FriBidiLevel* levelsBufferPointer = &paragraphInfo->mLevelsBuffer[lineInfo->mCharacterParagraphIndex];
+  FriBidiChar* visualUnicodeBufferPointer = &visualUnicodeBuffer[0u];
+  FriBidiStrIndex* visualToLogicalMapPointer = &lineInfo->mVisualToLogicalMap[0u];
+
+  // Initialize the visual to logical mapping table to the identity. Otherwise fribidi_reorder_line fails to retrieve a valid mapping table.
+  for( std::size_t index = 0u; index < lineInfo->mNumberOfCharacters; ++index )
+  {
+    lineInfo->mVisualToLogicalMap[ index ] = index;
+  }
+
+  fribidi_reorder_line( flags,
+                        charactersTypeBufferPointer,
+                        lineInfo->mNumberOfCharacters,
+                        0u,
+                        paragraphInfo->mDirection,
+                        levelsBufferPointer,
+                        visualUnicodeBufferPointer,
+                        visualToLogicalMapPointer );
+
+  // Fill the logical to visual mapping table.
+  for( std::size_t index = 0u; index < lineInfo->mNumberOfCharacters; ++index )
+  {
+    lineInfo->mLogicalToVisualMap[ lineInfo->mVisualToLogicalMap[ index ] ] = index;
+  }
+
+  std::vector<char> bidiTextConverted;
+
+  bidiTextConverted.resize( lineInfo->mNumberOfCharacters * 4u + 1u ); // Maximum bytes to represent one UTF-8 character is 6.
+                                                                       // Currently Dali doesn't support this UTF-8 extension.
+                                                                       // Dali only supports 'regular' UTF-8 which has a maximum of 4 bytes per character.
+
+  fribidi_unicode_to_charset( FRIBIDI_CHAR_SET_UTF8, visualUnicodeBufferPointer, lineInfo->mNumberOfCharacters, &bidiTextConverted[0u] );
+
+  lineInfo->mText = Text( &bidiTextConverted[0u] );
+}
+
+} // namespace TextProcessor
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h b/base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h
new file mode 100644 (file)
index 0000000..77d6ee9
--- /dev/null
@@ -0,0 +1,157 @@
+#ifndef __DALI_TOOLKIT_TEXT_PROCESSOR_BIDIRECTIONAL_INFO_H__
+#define __DALI_TOOLKIT_TEXT_PROCESSOR_BIDIRECTIONAL_INFO_H__
+
+/*
+ * Copyright (c) 2014 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/text/text.h>
+
+// EXTERNAL INCLUDES
+#include <fribidi/fribidi.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace TextProcessor
+{
+
+/**
+ * Stores the text containing right to left characters and info for each character needed by fribidi to reorder a line.
+ */
+struct BidirectionalParagraphInfo
+{
+  /**
+   * Default constructor.
+   *
+   * Initializes all members to their default values.
+   */
+  BidirectionalParagraphInfo();
+
+  /**
+   * Default destructor.
+   */
+  ~BidirectionalParagraphInfo();
+
+  /**
+   * Copy constructor.
+   */
+  BidirectionalParagraphInfo( const BidirectionalParagraphInfo& info );
+
+  /**
+   * Assignment operator.
+   */
+  BidirectionalParagraphInfo& operator=( const BidirectionalParagraphInfo& info );
+
+  FriBidiParType               mDirection;            ///< The paragraph direction.
+  std::vector<FriBidiCharType> mCharactersTypeBuffer; ///< Character type buffer.
+  std::vector<FriBidiLevel>    mLevelsBuffer;         ///< Levels buffer.
+  std::vector<FriBidiChar>     mLogicalUnicodeBuffer; ///< Text buffer in logical order. Coded in unicode.
+};
+
+/**
+ * Stores the reordered text, the conversion tables for a paragraph's line,
+ * the index to the first character of the line and the number of characters.
+ */
+struct BidirectionalLineInfo
+{
+  /**
+   * Default constructor.
+   *
+   * Initializes all members to their default values.
+   */
+  BidirectionalLineInfo();
+
+  /**
+   * Default destructor.
+   */
+  ~BidirectionalLineInfo();
+
+  /**
+   * Copy constructor.
+   */
+  BidirectionalLineInfo( const BidirectionalLineInfo& info );
+
+  /**
+   * Assignment operator.
+   */
+  BidirectionalLineInfo& operator=( const BidirectionalLineInfo& info );
+
+  std::size_t mCharacterParagraphIndex; ///< Index within the paragraph of the first character of the line.
+  std::size_t mNumberOfCharacters;      ///< Number of characters of the line.
+  Text        mText;                    ///< Text in visual order.
+  Vector<int> mVisualToLogicalMap;      ///< The character position map from the visual output text to the logical input text.
+  Vector<int> mLogicalToVisualMap;      ///< The character position map from the logical input text to the visual output text.
+};
+
+/**
+ * Whether the text begins with right-to-left (bidirectional) character.
+ * @param [in] text The given text.
+ * @return \e true if the text begins right-to-left character.
+ */
+bool BeginsRightToLeftCharacter( const Text& text );
+
+/**
+ * Whether the text contains any right-to-left (bidirectional) character.
+ * @param [in] text The given text.
+ * @return \e true if the text contains right-to-left character.
+ */
+bool ContainsRightToLeftCharacter( const Text& text );
+
+/**
+ * Processes a bidirectional paragraph's text.
+ *
+ * It stores the paragraph's direction (the direction of the first non neutral character),
+ * the direction of all characters, and the ligatures in case of arabic glyphs.
+ *
+ * It doesn't reorder the paragraph as this task must be done per line.
+ * The stored info is needed to reorder each line of the paragraph.
+ *
+ * @param[in] paragraph The paragraph to be processed.
+ * @param[out] info Struct containing the needed info to reorder each line of the paragraph.
+ */
+void ProcessBidirectionalText( Text& paragraph,
+                               BidirectionalParagraphInfo* info );
+
+/**
+ * Reorders one line of the paragraph according the Unicode Bidirectional Algorithm.
+ *
+ * The result is the text in the visual order and the conversion tables: logical <--> visual order
+ *
+ * @param[in] paragraphInfo Struct containing the needed info to reorder each line of the paragraph.
+ * @param[in,out] lineInfo Struct containing (in) A character index pointing the first character of the line and the number of characters, (out) the reordered line and the conversion tables.
+ */
+void ReorderLine( BidirectionalParagraphInfo* paragraphInfo,
+                  BidirectionalLineInfo* lineInfo );
+
+} // namespace TextProcessor
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_PROCESSOR_BIDIRECTIONAL_INFO_H__
+
index 1f32dd9..b41b841 100644 (file)
@@ -18,9 +18,6 @@
 // FILE HEADER
 #include <dali-toolkit/internal/controls/text-view/text-processor.h>
 
 // FILE HEADER
 #include <dali-toolkit/internal/controls/text-view/text-processor.h>
 
-// EXTERNAL INCLUDES
-#include <fribidi/fribidi.h>
-
 namespace Dali
 {
 
 namespace Dali
 {
 
@@ -33,234 +30,78 @@ namespace Internal
 namespace TextProcessor
 {
 
 namespace TextProcessor
 {
 
-void SplitInParagraphs( const MarkupProcessor::StyledTextArray& text,
-                   std::vector<MarkupProcessor::StyledTextArray>& paragraphs )
+void SplitInParagraphs( const MarkupProcessor::StyledTextArray& styledTextArray,
+                        std::vector<Text>& paragraphs,
+                        std::vector< Vector<TextStyle*> >& styles )
 {
 {
-  MarkupProcessor::StyledTextArray paragraph;
-  for( MarkupProcessor::StyledTextArray::const_iterator it = text.begin(), endIt = text.end(); it != endIt; ++it )
+  // Stores the text for a paragraph.
+  Text paragraph;
+
+  // Stores the styles for each character of the paragraph.
+  Vector<TextStyle*> stylesForParagraph;
+
+  // Traverses all styled texts of the array.
+  for( MarkupProcessor::StyledTextArray::const_iterator it = styledTextArray.begin(), endIt = styledTextArray.end(); it != endIt; ++it )
   {
     const MarkupProcessor::StyledText& styledText( *it );
 
   {
     const MarkupProcessor::StyledText& styledText( *it );
 
+    // Traverses all the characters of the styled text (It may have more than one).
     for( size_t i = 0u, length = styledText.mText.GetLength(); i < length; ++i )
     {
       const Dali::Character character = styledText.mText[i];
 
       if( character.IsNewLine() ) // LF
       {
     for( size_t i = 0u, length = styledText.mText.GetLength(); i < length; ++i )
     {
       const Dali::Character character = styledText.mText[i];
 
       if( character.IsNewLine() ) // LF
       {
-        Text newText( character );
-        MarkupProcessor::StyledText newStyledText( newText, styledText.mStyle );
-        paragraph.push_back( newStyledText );
+        // The character is a new paragraph character.
 
 
-        paragraphs.push_back( paragraph );
-        paragraph.clear();
-      }
-      else
-      {
-        Text newText( character );
-        MarkupProcessor::StyledText newStyledText( newText, styledText.mStyle );
-        paragraph.push_back( newStyledText );
-      }
-    }
-  }
+        // Append the new paragraph character.
+        paragraph.Append( character );
 
 
-  // This paragraph could be empty if the last character of the previous paragraph is a 'new paragraph' character
-  // and is the last of the text.
-  paragraphs.push_back( paragraph );
-}
+        // Creates a new text style for the character and insert it to the vector of styles for that paragraph.
+        TextStyle* style = new TextStyle( styledText.mStyle );
+        stylesForParagraph.PushBack( style );
 
 
-void SplitInWords( const MarkupProcessor::StyledTextArray& paragraph,
-                   std::vector<MarkupProcessor::StyledTextArray>& words )
-{
-  MarkupProcessor::StyledTextArray word;
-  for( MarkupProcessor::StyledTextArray::const_iterator it = paragraph.begin(), endIt = paragraph.end(); it != endIt; ++it )
-  {
-    const MarkupProcessor::StyledText& styledText( *it );
-    const Dali::Character character = styledText.mText[0u];
+        // Inserts the paragraph and the styles to the vector of paragraphs and the vector of styles.
+        paragraphs.push_back( paragraph );
+        styles.push_back( stylesForParagraph );
 
 
-    if( character.IsWhiteSpace() )
-    {
-      // When a separator is found, the previous word is added to the list,
-      // then a new word is initialized and the separator is also added as a word.
-      if( !word.empty() )
-      {
-        words.push_back( word );
-        word.clear(); // initializes a new word.
+        // Clears the text and the vector of styles for the next paragraph.
+        paragraph = Text();
+        stylesForParagraph.Clear();
       }
       }
-
-      // Separator added as a word.
-      MarkupProcessor::StyledText separatorChar;
-      separatorChar.mText.Append( character );
-      separatorChar.mStyle = styledText.mStyle;
-
-      MarkupProcessor::StyledTextArray separatorWord;
-      separatorWord.push_back( separatorChar );
-
-      words.push_back( separatorWord );
-    }
-    else
-    {
-      MarkupProcessor::StyledText styledChar;
-      styledChar.mStyle = styledText.mStyle;
-      styledChar.mText.Append( character );
-
-      // Add the character to the current word.
-      word.push_back( styledChar );
-    }
-  }
-
-  //Finally the last word need to be added.
-  if( !word.empty() )
-  {
-    words.push_back( word );
-  }
-}
-
-bool BeginsRightToLeftCharacter( const MarkupProcessor::StyledTextArray& styledText )
-{
-  for( MarkupProcessor::StyledTextArray::const_iterator it = styledText.begin(), endIt = styledText.end(); it != endIt; ++it )
-  {
-    const Text& text( (*it).mText );
-
-    for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
-    {
-      Character::CharacterDirection direction = text[i].GetCharacterDirection();
-      if( direction != Character::Neutral )
+      else
       {
       {
-        return ( direction == Character::RightToLeft || direction == Character::RightToLeftWeak );
-      }
-    }
-  }
+        // The character is not a new paragraph character.
 
 
-  return false;
-}
+        // Append it to the paragraph's text
+        paragraph.Append( character );
 
 
-bool BeginsRightToLeftCharacter( const Text& text )
-{
-  for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
-  {
-    Character::CharacterDirection direction = text[i].GetCharacterDirection();
-    if( direction != Character::Neutral )
-    {
-      return ( direction == Character::RightToLeft || direction == Character::RightToLeftWeak );
-    }
-  }
-
-  return false;
-}
-
-bool ContainsRightToLeftCharacter( const MarkupProcessor::StyledTextArray& styledText )
-{
-  for( MarkupProcessor::StyledTextArray::const_iterator it = styledText.begin(), endIt = styledText.end(); it != endIt; ++it )
-  {
-    const Text& text( (*it).mText );
-
-    for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
-    {
-      Character::CharacterDirection direction = text[i].GetCharacterDirection();
-      if( ( Character::RightToLeft == direction ) || ( Character::RightToLeftWeak == direction ) )
-      {
-        return true;
+        // Add the style to the vector of styles for that paragraph.
+        TextStyle* style = new TextStyle( styledText.mStyle );
+        stylesForParagraph.PushBack( style );
       }
     }
   }
 
       }
     }
   }
 
-  return false;
-}
-
-bool ContainsRightToLeftCharacter( const Dali::Text& text )
-{
-  for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
-  {
-    Character::CharacterDirection direction = ( text[i] ).GetCharacterDirection();
-    if( ( Character::RightToLeft == direction ) || ( Character::RightToLeftWeak == direction ) )
-    {
-      return true;
-    }
-  }
-
-  return false;
+  // This paragraph could be empty if the last character of the previous paragraph is a 'new paragraph' character
+  // and is the last of the text.
+  paragraphs.push_back( paragraph );
+  styles.push_back( stylesForParagraph );
 }
 
 }
 
-void ConvertBidirectionalText( const MarkupProcessor::StyledTextArray& line,
-                               MarkupProcessor::StyledTextArray& convertedText,
-                               std::vector<int>& logicalToVisualMap,
-                               std::vector<int>& visualToLogicalMap )
+void SplitInWords( const Dali::Text& paragraph,
+                   Vector<std::size_t>& positions )
 {
 {
-  // Clean vectors first. This function doesn't use any previous value.
-  logicalToVisualMap.clear();
-  visualToLogicalMap.clear();
-  convertedText.clear();
-
-  if( line.empty() )
-  {
-    // nothing to do if the line is empty.
-    return;
-  }
-
-  // Get the plain text from the line to be reordered by the BiDirectional algorithm.
-  std::string textToBeConverted;
-  GetPlainString( line, textToBeConverted );
-
-  const std::size_t stringSize = textToBeConverted.size();
-
-  std::vector<FriBidiChar> logicalStrBuffer;
-  std::vector<FriBidiChar> visualStrBuffer;
-  // unicode length <= UTF-8 length in bytes (reserve one extra for terminator)
-  // pad these buffers with 0's, as it's unclear what fribidi_log2vis does w.r.t.
-  // the length of it's output content (appears the same as input content, and does
-  // not seem to generate bidi marks i.e. FRIBIDI_CHAR_LRM/FRIBIDI_CHAR_RLM)
-  logicalStrBuffer.resize( stringSize+1u, 0u );
-  visualStrBuffer.resize( stringSize+1u, 0u );
-  FriBidiChar *logicalStr( &logicalStrBuffer[0u] );
-  FriBidiChar *visualStr( &visualStrBuffer[0u] );
-
-  // Convert UTF-8 string to unicode string
-  const std::size_t length = fribidi_charset_to_unicode( FRIBIDI_CHAR_SET_UTF8, textToBeConverted.c_str(), stringSize, logicalStr );
-
-  if( 0u == length )
-  {
-    DALI_ASSERT_DEBUG( !"TextProcessor::ConvertBidirectionalText. Error when calling at fribidi_charset_to_unicode" );
-
-    return;
-  }
-
-  logicalToVisualMap.resize( length );
-  visualToLogicalMap.resize( length );
+  const std::size_t length = paragraph.GetLength();
 
 
-  // Convert and reorder the string as specified by the Unicode Bidirectional Algorithm
-  FriBidiCharType baseDirection = FRIBIDI_TYPE_ON;
-  fribidi_boolean log2vis = fribidi_log2vis( logicalStr, length, &baseDirection, visualStr, &logicalToVisualMap[0u], &visualToLogicalMap[0u], NULL );
+  // Magic number: Let's soupose there is ~6 characters per word. Used to do less memory reallocation inside Vector.
+  const size_t magicNumberOfWords = ( length / 6u ) + 1u;
 
 
-  if(log2vis)
-  {
-    // Convert the unicode string back to the UTF-8 string
-    std::vector<char> bidiTextConverted;
-
-    bidiTextConverted.resize( length * 4u + 1u ); // Maximum bytes to represent one UTF-8 character is 6.
-                                                // Currently Dali doesn't support this UTF-8 extension. Dali only supports 'regular' UTF-8 which has a maximum of 4 bytes per character.
-
-    fribidi_unicode_to_charset( FRIBIDI_CHAR_SET_UTF8, visualStr, length, &bidiTextConverted[0u] );
-
-    textToBeConverted = &bidiTextConverted[0u];
-
-    // After reorder the text, rebuild the text with the original styles is needed.
-    // To assign the original style is needed to use the characterLogicalToVisualMap table.
-    Text text( &bidiTextConverted[0u] );
-
-    // Split the line in words.
-    // Add the correct styles for the characters after they are reordered.
+  // Find the positions of the new paragraph characters.
+  positions.Reserve( magicNumberOfWords );
 
 
-    for( size_t i = 0u; i < length; ++i )
-    {
-      const Character character( text[i] );
-
-      MarkupProcessor::StyledText styledText;
-      styledText.mText.Append( character );
-      styledText.mStyle = line[visualToLogicalMap[i]].mStyle;
-
-      convertedText.push_back( styledText );
-    }
-  }
+  // Find the position of all white spaces. A new paragraph character is also considered a white space but it doesn't matter at this point.
+  paragraph.Find( Text::WHITE_SPACE, 0u, length - 1u, positions );
 }
 
 /**
 }
 
 /**
@@ -276,7 +117,7 @@ bool IsWhiteSpace( const MarkupProcessor::StyledTextArray& text, size_t offset )
   DALI_ASSERT_DEBUG( offset < text.size() );
 
   // assume 1 Character per StyledText
   DALI_ASSERT_DEBUG( offset < text.size() );
 
   // assume 1 Character per StyledText
-  return text[offset].mText[0u].IsWhiteSpace();
+  return ( *( text.begin() + offset ) ).mText[0u].IsWhiteSpace();
 }
 
 void FindNearestWord( const MarkupProcessor::StyledTextArray& text, size_t offset, size_t& start, size_t& end)
 }
 
 void FindNearestWord( const MarkupProcessor::StyledTextArray& text, size_t offset, size_t& start, size_t& end)
index 6324805..9814c09 100644 (file)
@@ -32,6 +32,8 @@ namespace Internal
 
 namespace TextProcessor
 {
 
 namespace TextProcessor
 {
+// Forward declarations.
+struct BidirectionalParagraphInfo;
 
 /**
  * Splits the given text in paragraphs.
 
 /**
  * Splits the given text in paragraphs.
@@ -39,60 +41,22 @@ namespace TextProcessor
  * @note Assumes the StyledTextArray has 1 Character per Text element. (which is the case for text in TextInput, but
  * not necessarily the case for text in TextView)
  *
  * @note Assumes the StyledTextArray has 1 Character per Text element. (which is the case for text in TextInput, but
  * not necessarily the case for text in TextView)
  *
- * @param [in] text The given text.
+ * @param [in] styledTextArray The given text.
  * @param [out] paragraphs The text split in paragraphs.
  * @param [out] paragraphs The text split in paragraphs.
+ * @param [out] styles The styles of each character of each paragraph.
  */
  */
-void SplitInParagraphs( const MarkupProcessor::StyledTextArray& text,
-                        std::vector<MarkupProcessor::StyledTextArray>& paragraphs );
+void SplitInParagraphs( const MarkupProcessor::StyledTextArray& styledTextArray,
+                        std::vector<Text>& paragraphs,
+                        std::vector< Vector<TextStyle*> >& styles );
 
 /**
 
 /**
- * Splits the given paragraph in words.
- *
- * @note Assumes the StyledTextArray has 1 Character per Text element. (which is the case for text in TextInput, but
- * not necessarily the case for text in TextView)
+ * Finds the position of all word separators (currently white spaces and new paragraph characters '\n') in the given text.
  *
  * @param [in] paragraph The given paragraph.
  *
  * @param [in] paragraph The given paragraph.
- * @param [out] words The paragraph split in words.
- */
-void SplitInWords( const MarkupProcessor::StyledTextArray& paragraph,
-                   std::vector<MarkupProcessor::StyledTextArray>& words );
-
-/**
- * Whether the text begins with right-to-left (bidirectional) character.
- * @param [in] text The given text.
- * @return \e true if the text begins right-to-left character.
- */
-bool BeginsRightToLeftCharacter( const Text& text );
-
-/**
- * @copydoc BeginsRightToLeftCharacter( const Text& text )
- */
-bool BeginsRightToLeftCharacter( const MarkupProcessor::StyledTextArray& text );
-
-/**
- * Whether the text contains any right-to-left (bidirectional) character.
- * @param [in] text The given text.
- * @return \e true if the text contains right-to-left character.
- */
-bool ContainsRightToLeftCharacter( const Text& text );
-
-/**
- * @copydoc ContainsRightToLeftCharacter( const Text& text )
- */
-bool ContainsRightToLeftCharacter( const MarkupProcessor::StyledTextArray& text );
-
-/**
- * Convert the text as specified by the Unicode Bidirectional Algorithm.
- * The text is converted only if it is bidirectional.
- * @param[in] line The line of text to be converted.
- * @param[out] convertedText The text converted.
- * @param[out] logicalToVisualMap The character position map from the logical input text to the visual output text.
- * @param[out] visualToLogicalMap The character position map from the visual output text to the logical input text.
+ * @param [out] positions Positions within the paragraph of all word sepatators.
  */
  */
- void ConvertBidirectionalText( const MarkupProcessor::StyledTextArray& line,
-                                MarkupProcessor::StyledTextArray& convertedText,
-                                std::vector<int>& logicalToVisualMap,
-                                std::vector<int>& visualToLogicalMap );
+void SplitInWords( const Text& paragraph,
+                   Vector<std::size_t>& positions );
 
 /**
  * Finds the nearest word in a string to a specified
 
 /**
  * Finds the nearest word in a string to a specified
index 3373ab7..ddcf00f 100644 (file)
@@ -73,12 +73,11 @@ CharacterLayoutInfo::CharacterLayoutInfo()
   mPosition(),
   mOffset(),
   mGlyphActor(),
   mPosition(),
   mOffset(),
   mGlyphActor(),
-  mStyledText(),
   mColorAlpha( 1.f ),
   mGradientInfo( NULL ),
   mIsVisible( true ),
   mColorAlpha( 1.f ),
   mGradientInfo( NULL ),
   mIsVisible( true ),
-  mSetText( true ),
-  mSetStyle( true ),
+  mSetText( false ),
+  mSetStyle( false ),
   mIsColorGlyph( false )
 {
 }
   mIsColorGlyph( false )
 {
 }
@@ -98,7 +97,6 @@ CharacterLayoutInfo::CharacterLayoutInfo( const CharacterLayoutInfo& character )
   mPosition( character.mPosition ),
   mOffset( character.mOffset ),
   mGlyphActor( character.mGlyphActor ),
   mPosition( character.mPosition ),
   mOffset( character.mOffset ),
   mGlyphActor( character.mGlyphActor ),
-  mStyledText( character.mStyledText ),
   mColorAlpha( character.mColorAlpha ),
   mGradientInfo( ( NULL == character.mGradientInfo ) ? NULL : new GradientInfo( *character.mGradientInfo ) ), // Copies the gradient info.
   mIsVisible( character.mIsVisible ),
   mColorAlpha( character.mColorAlpha ),
   mGradientInfo( ( NULL == character.mGradientInfo ) ? NULL : new GradientInfo( *character.mGradientInfo ) ), // Copies the gradient info.
   mIsVisible( character.mIsVisible ),
@@ -120,7 +118,6 @@ CharacterLayoutInfo& CharacterLayoutInfo::operator=( const CharacterLayoutInfo&
   mOffset = character.mOffset;
 
   mGlyphActor = character.mGlyphActor;
   mOffset = character.mOffset;
 
   mGlyphActor = character.mGlyphActor;
-  mStyledText = character.mStyledText;
 
   mColorAlpha = character.mColorAlpha;
 
 
   mColorAlpha = character.mColorAlpha;
 
index 0079170..be8f974 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h>
 #include <dali-toolkit/internal/controls/text-view/split-by-word-policies.h>
 #include <dali-toolkit/internal/controls/text-view/split-by-char-policies.h>
 #include <dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h>
 #include <dali-toolkit/internal/controls/text-view/split-by-word-policies.h>
 #include <dali-toolkit/internal/controls/text-view/split-by-char-policies.h>
+#include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-processor.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
 #include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-processor.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
 #include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
@@ -193,23 +194,38 @@ void TextView::InsertTextAt( std::size_t position, const std::string& text )
 
 void TextView::InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text )
 {
 
 void TextView::InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text )
 {
-  // Creates metadata with the Insert operation.
-  TextViewProcessorMetadata metadata;
-  metadata.mType = TextView::TextInserted;
-  metadata.mPosition = position;
-  metadata.mText = text;
+  std::string textStr;
+  MarkupProcessor::GetPlainString( text, textStr );
 
 
-  // Store metadata.
-  mTextViewProcessorOperations.push_back( metadata );
+  if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
+      TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
+  {
+    // Temporary fix. Creates the whole layout if there is rtl text.
 
 
-  // Updates current styled text.
-  mCurrentStyledText.insert( mCurrentStyledText.begin() + position, text.begin(), text.end() );
+    MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
+    textToSet.insert( textToSet.begin() + position, text.begin(), text.end() );
+    SetText( textToSet );
+  }
+  else
+  {
+    // Creates metadata with the Insert operation.
+    TextViewProcessorMetadata metadata;
+    metadata.mType = TextView::TextInserted;
+    metadata.mPosition = position;
+    metadata.mText = text;
 
 
-  // Request to be relaid out
-  RelayoutRequest();
+    // Store metadata.
+    mTextViewProcessorOperations.push_back( metadata );
 
 
-  // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
-  mRelayoutOperations = RELAYOUT_ALL;
+    // Updates current styled text.
+    mCurrentStyledText.insert( mCurrentStyledText.begin() + position, text.begin(), text.end() );
+
+    // Request to be relaid out
+    RelayoutRequest();
+
+    // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
+    mRelayoutOperations = RELAYOUT_ALL;
+  }
 }
 
 void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text )
 }
 
 void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text )
@@ -377,14 +393,18 @@ void TextView::SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask ma
   }
 
   // Sets the new style to the ellipsize text
   }
 
   // Sets the new style to the ellipsize text
-  if( !mLayoutParameters.mEllipsizeText.empty() )
+  // TODO: fix this as a call to SetEllipsizeText will trigger the creation of new text actors.
+  if( 0u < mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Count() )
   {
   {
-    for( MarkupProcessor::StyledTextArray::iterator it = mLayoutParameters.mEllipsizeText.begin(), endIt = mLayoutParameters.mEllipsizeText.end(); it != endIt; ++it )
+    for( Vector<TextStyle*>::Iterator it = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin(),
+           endIt = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.End();
+         it != endIt;
+         ++it )
     {
     {
-      (*it).mStyle.Copy( style, mask );
+      (*it)->Copy( style, mask );
     }
 
     }
 
-    SetEllipsizeText( mLayoutParameters.mEllipsizeText );
+    SetEllipsizeText( mRelayoutData.mTextLayoutInfo.mEllipsisText, mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles );
   }
 }
 
   }
 }
 
@@ -547,17 +567,35 @@ void TextView::SetEllipsizeText( const std::string& ellipsizeText )
   MarkupProcessor::StyledTextArray styledText;
   MarkupProcessor::GetStyledTextArray( ellipsizeText, styledText, IsMarkupProcessingEnabled() );
 
   MarkupProcessor::StyledTextArray styledText;
   MarkupProcessor::GetStyledTextArray( ellipsizeText, styledText, IsMarkupProcessingEnabled() );
 
+  // Creates the ellipsis layout info and sets the text and styles.
   SetEllipsizeText( styledText );
 }
 
 void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText )
 {
   SetEllipsizeText( styledText );
 }
 
 void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText )
 {
-  mLayoutParameters.mEllipsizeText = ellipsizeText;
+  // Converts the styled text array into a Text and a vector of TextStyles.
+  Text text;
+  Vector<TextStyle*> styles;
+  for( MarkupProcessor::StyledTextArray::const_iterator it = ellipsizeText.begin(), endIt = ellipsizeText.end(); it != endIt; ++it )
+  {
+    const MarkupProcessor::StyledText& styledText( *it );
 
 
-  mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
+    text.Append( styledText.mText );
+    styles.PushBack( new TextStyle( styledText.mStyle ) );
+  }
 
 
-  TextViewProcessor::CreateWordTextInfo( mLayoutParameters.mEllipsizeText,
-                                         mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
+  // Creates the ellipsis layout info and sets the text and styles.
+  SetEllipsizeText( text, styles );
+}
+
+void TextView::SetEllipsizeText( const Text& ellipsizeText, const Vector<TextStyle*>& ellipsizeStyles )
+{
+  // Sets the text and styles for the ellipsis text.
+  mRelayoutData.mTextLayoutInfo.mEllipsisText = ellipsizeText;
+  mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsizeStyles;
+
+  // Creates the ellipsis layout info.
+  CreateEllipsizeLayout();
 
   // Request to be relaid out
   RelayoutRequest();
 
   // Request to be relaid out
   RelayoutRequest();
@@ -567,13 +605,7 @@ void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsi
 
 std::string TextView::GetEllipsizeText() const
 {
 
 std::string TextView::GetEllipsizeText() const
 {
-  std::string text;
-  for( MarkupProcessor::StyledTextArray::const_iterator it = mLayoutParameters.mEllipsizeText.begin(), endIt = mLayoutParameters.mEllipsizeText.end(); it != endIt; ++it )
-  {
-    text.append( (*it).mText.GetText() );
-  }
-
-  return text;
+  return mRelayoutData.mTextLayoutInfo.mEllipsisText.GetText();
 }
 
 void TextView::GetTextLayoutInfo()
 }
 
 void TextView::GetTextLayoutInfo()
@@ -632,7 +664,6 @@ void TextView::GetTextLayoutInfo()
       {
         mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
       }
       {
         mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
       }
-
     }
   }
 }
     }
   }
 }
@@ -861,12 +892,8 @@ TextView::LayoutParameters::LayoutParameters()
   mVerticalAlignment( Toolkit::Alignment::VerticalCenter ),
   mLineJustification( Toolkit::TextView::Left ),
   mLineHeightOffset( 0.f ),
   mVerticalAlignment( Toolkit::Alignment::VerticalCenter ),
   mLineJustification( Toolkit::TextView::Left ),
   mLineHeightOffset( 0.f ),
-  mEllipsizeText(),
   mMarkUpEnabled( false )
 {
   mMarkUpEnabled( false )
 {
-  // Sets ellipsize text
-  MarkupProcessor::StyledTextArray styledEllipsize;
-  MarkupProcessor::GetStyledTextArray( std::string( "..." ), mEllipsizeText, false );
 }
 
 TextView::LayoutParameters::~LayoutParameters()
 }
 
 TextView::LayoutParameters::~LayoutParameters()
@@ -879,7 +906,6 @@ TextView::LayoutParameters::LayoutParameters( Toolkit::TextView::MultilinePolicy
                                               Toolkit::Alignment::Type             alignmentType,
                                               Toolkit::TextView::LineJustification lineJustification,
                                               float                                lineHeightOffset,
                                               Toolkit::Alignment::Type             alignmentType,
                                               Toolkit::TextView::LineJustification lineJustification,
                                               float                                lineHeightOffset,
-                                              const std::string&                   ellipsizeText,
                                               bool                                 markUpEnabled )
 : mMultilinePolicy( multilinePolicy ),
   mWidthExceedPolicy( widthExceedPolicy ),
                                               bool                                 markUpEnabled )
 : mMultilinePolicy( multilinePolicy ),
   mWidthExceedPolicy( widthExceedPolicy ),
@@ -888,7 +914,6 @@ TextView::LayoutParameters::LayoutParameters( Toolkit::TextView::MultilinePolicy
   mVerticalAlignment(),
   mLineJustification( lineJustification ),
   mLineHeightOffset( lineHeightOffset ),
   mVerticalAlignment(),
   mLineJustification( lineJustification ),
   mLineHeightOffset( lineHeightOffset ),
-  mEllipsizeText(),
   mMarkUpEnabled( markUpEnabled )
 {
   // Sets alignment
   mMarkUpEnabled( markUpEnabled )
 {
   // Sets alignment
@@ -901,10 +926,6 @@ TextView::LayoutParameters::LayoutParameters( Toolkit::TextView::MultilinePolicy
 
   mHorizontalAlignment = horizontalAlignment;
   mVerticalAlignment = verticalAlignment;
 
   mHorizontalAlignment = horizontalAlignment;
   mVerticalAlignment = verticalAlignment;
-
-  // Sets ellipsize text
-  MarkupProcessor::StyledTextArray styledEllipsize;
-  MarkupProcessor::GetStyledTextArray( ellipsizeText, mEllipsizeText, mMarkUpEnabled );
 }
 
 TextView::LayoutParameters::LayoutParameters( const TextView::LayoutParameters& layoutParameters )
 }
 
 TextView::LayoutParameters::LayoutParameters( const TextView::LayoutParameters& layoutParameters )
@@ -915,7 +936,6 @@ TextView::LayoutParameters::LayoutParameters( const TextView::LayoutParameters&
   mVerticalAlignment( layoutParameters.mVerticalAlignment ),
   mLineJustification( layoutParameters.mLineJustification ),
   mLineHeightOffset( layoutParameters.mLineHeightOffset ),
   mVerticalAlignment( layoutParameters.mVerticalAlignment ),
   mLineJustification( layoutParameters.mLineJustification ),
   mLineHeightOffset( layoutParameters.mLineHeightOffset ),
-  mEllipsizeText( layoutParameters.mEllipsizeText ),
   mMarkUpEnabled( layoutParameters.mMarkUpEnabled )
 {
 }
   mMarkUpEnabled( layoutParameters.mMarkUpEnabled )
 {
 }
@@ -929,7 +949,6 @@ TextView::LayoutParameters& TextView::LayoutParameters::operator=( const TextVie
   mVerticalAlignment = layoutParameters.mVerticalAlignment;
   mLineJustification = layoutParameters.mLineJustification;
   mLineHeightOffset = layoutParameters.mLineHeightOffset;
   mVerticalAlignment = layoutParameters.mVerticalAlignment;
   mLineJustification = layoutParameters.mLineJustification;
   mLineHeightOffset = layoutParameters.mLineHeightOffset;
-  mEllipsizeText = layoutParameters.mEllipsizeText;
   mMarkUpEnabled = layoutParameters.mMarkUpEnabled;
 
   return *this;
   mMarkUpEnabled = layoutParameters.mMarkUpEnabled;
 
   return *this;
@@ -1018,7 +1037,6 @@ TextView::TextView()
                      static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                      Toolkit::TextView::Left,
                      PointSize( 0.f ),
                      static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
                      Toolkit::TextView::Left,
                      PointSize( 0.f ),
-                     std::string( "..." ),
                      false ),
   mVisualParameters(),
   mRelayoutData(),
                      false ),
   mVisualParameters(),
   mRelayoutData(),
@@ -1034,8 +1052,8 @@ TextView::TextView()
   mPreviousSnapshotModeEnabled( false ),
   mMarkUpEnabled( false )
 {
   mPreviousSnapshotModeEnabled( false ),
   mMarkUpEnabled( false )
 {
-  TextViewProcessor::CreateWordTextInfo( mLayoutParameters.mEllipsizeText,
-                                         mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
+  // Creates the ellipsis layout info.
+  CreateEllipsizeLayout();
 }
 
 TextView::~TextView()
 }
 
 TextView::~TextView()
@@ -1149,9 +1167,8 @@ void TextView::OnInitialize()
 
 void TextView::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange )
 {
 
 void TextView::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange )
 {
-  mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
-  TextViewProcessor::CreateWordTextInfo( mLayoutParameters.mEllipsizeText,
-                                         mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
+  // Creates the ellipsis layout info.
+  CreateEllipsizeLayout();
 
   SetText( mCurrentStyledText );
 }
 
   SetText( mCurrentStyledText );
 }
@@ -1191,6 +1208,17 @@ void TextView::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
     }
   }
 
     }
   }
 
+  if( ( Toolkit::TextView::Fade == mLayoutParameters.mWidthExceedPolicy ) ||
+      ( Toolkit::TextView::Fade == mLayoutParameters.mHeightExceedPolicy ) )
+  {
+    if( mRelayoutOperations & RELAYOUT_ALIGNMENT )
+    {
+      // If the text of the alignment changes and a fade exceed policy is set,
+      // some characters may need new TextActor.
+      mRelayoutOperations = RELAYOUT_ALL;
+    }
+  }
+
   // Remove glyph-actors from text-view
   if( !mRelayoutData.mGlyphActors.empty() && ( mRelayoutOperations & RELAYOUT_REMOVE_TEXT_ACTORS ) )
   {
   // Remove glyph-actors from text-view
   if( !mRelayoutData.mGlyphActors.empty() && ( mRelayoutOperations & RELAYOUT_REMOVE_TEXT_ACTORS ) )
   {
@@ -1880,6 +1908,16 @@ Actor TextView::GetRootActor() const
   return rootActor;
 }
 
   return rootActor;
 }
 
+void TextView::CreateEllipsizeLayout()
+{
+  // Creates the ellipsis layout info for the ellipsis text and styles.
+  mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
+  mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.resize( mRelayoutData.mTextLayoutInfo.mEllipsisText.GetLength(), TextViewProcessor::CharacterLayoutInfo() );
+  TextViewProcessor::CreateWordTextInfo( mRelayoutData.mTextLayoutInfo.mEllipsisText,
+                                         mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles,
+                                         mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
+}
+
 void TextView::OnMarkupEnabledPeopertySet( Property::Value propertyValue )
 {
   bool newValue( propertyValue.Get<bool>() );
 void TextView::OnMarkupEnabledPeopertySet( Property::Value propertyValue )
 {
   bool newValue( propertyValue.Get<bool>() );
index 220871b..70c149a 100644 (file)
@@ -90,7 +90,7 @@ public:
 
     TextViewProcessorMetadataType    mType;               ///< Stores the type of operation.
     std::size_t                      mPosition;           ///< Character position within the text.
 
     TextViewProcessorMetadataType    mType;               ///< Stores the type of operation.
     std::size_t                      mPosition;           ///< Character position within the text.
-    std::size_t                      mNumberOfCharacters; ///< Number of characters to be removed/ replaced.
+    std::size_t                      mNumberOfCharacters; ///< Number of characters to be removed/replaced.
     MarkupProcessor::StyledTextArray mText;               ///< The new text.
     TextStyle::Mask                  mStyleMask;          ///< The style mask.
   };
     MarkupProcessor::StyledTextArray mText;               ///< The new text.
     TextStyle::Mask                  mStyleMask;          ///< The style mask.
   };
@@ -245,6 +245,11 @@ public:
   void SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText );
 
   /**
   void SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText );
 
   /**
+   * @copydoc SetEllipsizeText()
+   */
+  void SetEllipsizeText( const Text& ellipsizeText, const Vector<TextStyle*>& ellipsizeStyles );
+
+  /**
    * @copydoc GetEllipsizeText()
    */
   std::string GetEllipsizeText() const;
    * @copydoc GetEllipsizeText()
    */
   std::string GetEllipsizeText() const;
@@ -524,6 +529,11 @@ private:
   Actor GetRootActor() const;
 
   /**
   Actor GetRootActor() const;
 
   /**
+   * Creates the ellipsize text layout.
+   */
+  void CreateEllipsizeLayout();
+
+  /**
    * Handle SetProperty for markup processing.
    * @param[in] propertyValue The new property value.
    */
    * Handle SetProperty for markup processing.
    * @param[in] propertyValue The new property value.
    */
@@ -604,7 +614,6 @@ public:
                       Toolkit::Alignment::Type               alignment,
                       Toolkit::TextView::LineJustification   lineJustification,
                       float                                  lineHeightOffset,
                       Toolkit::Alignment::Type               alignment,
                       Toolkit::TextView::LineJustification   lineJustification,
                       float                                  lineHeightOffset,
-                      const std::string&                     ellipsizeText,
                       bool                                   markUpEnabled );
 
     /**
                       bool                                   markUpEnabled );
 
     /**
@@ -618,15 +627,14 @@ public:
     LayoutParameters& operator=( const LayoutParameters& layoutParameters );
 
     Toolkit::TextView::MultilinePolicy   mMultilinePolicy;     ///< Stores the multiline policy.
     LayoutParameters& operator=( const LayoutParameters& layoutParameters );
 
     Toolkit::TextView::MultilinePolicy   mMultilinePolicy;     ///< Stores the multiline policy.
-    TextView::ExceedPolicy               mExceedPolicy;        ///< Stores a combination of both policies;
+    TextView::ExceedPolicy               mExceedPolicy;        ///< Stores a combination of both policies.
     Toolkit::TextView::ExceedPolicy      mWidthExceedPolicy;   ///< Stores the text width exceed policy.
     Toolkit::TextView::ExceedPolicy      mHeightExceedPolicy;  ///< Stores the text height exceed policy.
     Toolkit::Alignment::Type             mHorizontalAlignment; ///< Stores the horizontal alignment for the whole text.
     Toolkit::Alignment::Type             mVerticalAlignment;   ///< Stores the vertical alignment for the whole text.
     Toolkit::TextView::LineJustification mLineJustification;   ///< Stores the line justification.
     float                                mLineHeightOffset;    ///< Line height offset to be addded to the font line height (measured in PointSize).
     Toolkit::TextView::ExceedPolicy      mWidthExceedPolicy;   ///< Stores the text width exceed policy.
     Toolkit::TextView::ExceedPolicy      mHeightExceedPolicy;  ///< Stores the text height exceed policy.
     Toolkit::Alignment::Type             mHorizontalAlignment; ///< Stores the horizontal alignment for the whole text.
     Toolkit::Alignment::Type             mVerticalAlignment;   ///< Stores the vertical alignment for the whole text.
     Toolkit::TextView::LineJustification mLineJustification;   ///< Stores the line justification.
     float                                mLineHeightOffset;    ///< Line height offset to be addded to the font line height (measured in PointSize).
-    MarkupProcessor::StyledTextArray     mEllipsizeText;       ///< Stores the ellipsize text
-    bool                                 mMarkUpEnabled:1;     ///< Is markup string scanning enabled
+    bool                                 mMarkUpEnabled:1;     ///< Is markup string scanning enabled.
   };
 
   /**
   };
 
   /**
@@ -658,15 +666,6 @@ public:
   };
 
   /**
   };
 
   /**
-   * Temporary data used to calculate line justification.
-   */
-  struct LineJustificationInfo
-  {
-    TextViewProcessor::TextInfoIndices mIndices;    ///< Indices to the first character of the new line.
-    float                              mLineLength; ///< Length of the line (or portion of line).
-  };
-
-  /**
    * The results of the relayout process.
    */
   struct RelayoutData
    * The results of the relayout process.
    */
   struct RelayoutData
@@ -696,7 +695,6 @@ public:
     Toolkit::TextView::CharacterLayoutInfoContainer mCharacterLayoutInfoTable;    ///< Stores layout info per character sorted by the character's visual index.
     Toolkit::TextView::LineLayoutInfoContainer      mLines;                       ///< Stores an index to the first character of each line.
     Size                                            mTextSizeForRelayoutOption;   ///< Stores the text size after relayout.
     Toolkit::TextView::CharacterLayoutInfoContainer mCharacterLayoutInfoTable;    ///< Stores layout info per character sorted by the character's visual index.
     Toolkit::TextView::LineLayoutInfoContainer      mLines;                       ///< Stores an index to the first character of each line.
     Size                                            mTextSizeForRelayoutOption;   ///< Stores the text size after relayout.
-    std::vector<LineJustificationInfo>              mLineJustificationInfo;       ///< Stores justification info per line.
     TextActorCache                                  mTextActorCache;              ///< Stores previously created text-actors to be reused.
   };
 
     TextActorCache                                  mTextActorCache;              ///< Stores previously created text-actors to be reused.
   };
 
index be29790..70a0309 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h>
 #include <dali-toolkit/internal/controls/text-view/text-processor.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h>
 #include <dali-toolkit/internal/controls/text-view/text-processor.h>
+#include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
 
 namespace Dali
 {
 
 namespace Dali
 {
@@ -39,26 +40,74 @@ namespace TextViewProcessor
 // Layout info.
 /////////////////////
 
 // Layout info.
 /////////////////////
 
+void RightToLeftParagraphLayout::Clear()
+{
+  mWordsLayoutInfo.clear();
+  mText = Text();
+  mTextStyles.Clear();
+}
+
 ParagraphLayoutInfo::ParagraphLayoutInfo()
 : mSize(),
   mAscender( 0.f ),
   mLineHeightOffset( 0.f ),
 ParagraphLayoutInfo::ParagraphLayoutInfo()
 : mSize(),
   mAscender( 0.f ),
   mLineHeightOffset( 0.f ),
+  mFirstCharacter( 0u ),
   mNumberOfCharacters( 0u ),
   mNumberOfCharacters( 0u ),
-  mWordsLayoutInfo()
+  mWordsLayoutInfo(),
+  mText(),
+  mTextStyles(),
+  mRightToLeftLayout( NULL ),
+  mBidirectionalParagraphInfo( NULL ),
+  mBidirectionalLinesInfo()
 {
 }
 
 ParagraphLayoutInfo::~ParagraphLayoutInfo()
 {
 {
 }
 
 ParagraphLayoutInfo::~ParagraphLayoutInfo()
 {
+  if( NULL != mRightToLeftLayout )
+  {
+    // TextStyle pointers are the same than the ones stored at ParagraphLayoutInfo::mTextStyles.
+    // Do not delete them, just clear the vector.
+    mRightToLeftLayout->mTextStyles.Clear();
+
+    delete mRightToLeftLayout;
+  }
+
+  // Clears text styles. It destroys TextStyle objects.
+  ClearStyles();
+
+  // Deletes the bidirectional info for the whole paragraph.
+  delete mBidirectionalParagraphInfo;
+
+  // Clears the bidirectional info for all lines. Destroys the BidirectionalLineInfo objects.
+  ClearBidirectionalInfo();
 }
 
 ParagraphLayoutInfo::ParagraphLayoutInfo( const ParagraphLayoutInfo& paragraph )
 : mSize( paragraph.mSize ),
   mAscender( paragraph.mAscender ),
   mLineHeightOffset( paragraph.mLineHeightOffset ),
 }
 
 ParagraphLayoutInfo::ParagraphLayoutInfo( const ParagraphLayoutInfo& paragraph )
 : mSize( paragraph.mSize ),
   mAscender( paragraph.mAscender ),
   mLineHeightOffset( paragraph.mLineHeightOffset ),
+  mFirstCharacter( paragraph.mFirstCharacter ),
   mNumberOfCharacters( paragraph.mNumberOfCharacters ),
   mNumberOfCharacters( paragraph.mNumberOfCharacters ),
-  mWordsLayoutInfo( paragraph.mWordsLayoutInfo )
+  mWordsLayoutInfo( paragraph.mWordsLayoutInfo ),
+  mText( paragraph.mText ),
+  mTextStyles(),
+  mRightToLeftLayout( NULL ),
+  // Copies bidirectional info for the whole paragraph.
+  mBidirectionalParagraphInfo( ( NULL == paragraph.mBidirectionalParagraphInfo ) ? NULL : new TextProcessor::BidirectionalParagraphInfo( *paragraph.mBidirectionalParagraphInfo ) ),
+  mBidirectionalLinesInfo()
 {
 {
+  // Copies styles.
+  for( Vector<TextStyle*>::ConstIterator it = paragraph.mTextStyles.Begin(), endIt = paragraph.mTextStyles.End(); it != endIt; ++it )
+  {
+    mTextStyles.PushBack( new TextStyle( *(*it) ) );
+  }
+
+  // Copies bidirectional info for each line.
+  for( Vector<TextProcessor::BidirectionalLineInfo*>::ConstIterator it = mBidirectionalLinesInfo.Begin(), endIt = mBidirectionalLinesInfo.End(); it != endIt; ++it )
+  {
+    mBidirectionalLinesInfo.PushBack( new TextProcessor::BidirectionalLineInfo( *( *it ) ) );
+  }
 }
 
 ParagraphLayoutInfo& ParagraphLayoutInfo::operator=( const ParagraphLayoutInfo& paragraph )
 }
 
 ParagraphLayoutInfo& ParagraphLayoutInfo::operator=( const ParagraphLayoutInfo& paragraph )
@@ -66,150 +115,207 @@ ParagraphLayoutInfo& ParagraphLayoutInfo::operator=( const ParagraphLayoutInfo&
   mSize = paragraph.mSize;
   mAscender = paragraph.mAscender;
   mLineHeightOffset = paragraph.mLineHeightOffset;
   mSize = paragraph.mSize;
   mAscender = paragraph.mAscender;
   mLineHeightOffset = paragraph.mLineHeightOffset;
+  mFirstCharacter = paragraph.mFirstCharacter;
   mNumberOfCharacters = paragraph.mNumberOfCharacters;
   mWordsLayoutInfo = paragraph.mWordsLayoutInfo;
   mNumberOfCharacters = paragraph.mNumberOfCharacters;
   mWordsLayoutInfo = paragraph.mWordsLayoutInfo;
+  mText = paragraph.mText;
 
 
-  return *this;
-}
+  // If it has styles, destroy them.
+  ClearStyles();
 
 
-void CreateParagraphInfo( const MarkupProcessor::StyledTextArray& paragraph,
-                          TextView::RelayoutData& relayoutData,
-                          ParagraphLayoutInfo& paragraphLayoutInfo )
-{
-  // Split the paragraph in words.
-  // TODO: Proper RTL support.
-  MarkupProcessor::StyledTextArray convertedParagraph;
-  if( TextProcessor::ContainsRightToLeftCharacter( paragraph ) )
+  // Copies styles.
+  for( Vector<TextStyle*>::ConstIterator it = paragraph.mTextStyles.Begin(), endIt = paragraph.mTextStyles.End(); it != endIt; ++it )
   {
   {
-    // If the text is bidirectional, the characters will be converted and reordered
-    // as specified by the Unicode Bidirectional Algorithm.
+    mTextStyles.PushBack( new TextStyle( *(*it) ) );
+  }
 
 
-    // Reorders the paragraph and converts arabic glyphs (if any).
-    TextProcessor::ConvertBidirectionalText( paragraph,
-                                             convertedParagraph,
-                                             relayoutData.mCharacterLogicalToVisualMap,
-                                             relayoutData.mCharacterVisualToLogicalMap);
+  // Copies the paragraph's bidirectiona info.
+  if( NULL == paragraph.mBidirectionalParagraphInfo )
+  {
+    // The source doesn't have bidirectiona info. Deletes the current one.
+    delete mBidirectionalParagraphInfo;
+    mBidirectionalParagraphInfo = NULL;
   }
   else
   {
   }
   else
   {
-    // No bidirectional text to process.
-    convertedParagraph = paragraph;
-
-    // Create trivial bidirectional map tables.
-    std::size_t index = 0u;
-    for( MarkupProcessor::StyledTextArray::const_iterator it = convertedParagraph.begin(), endIt = convertedParagraph.end(); it != endIt; ++it )
+    // The source has bidirectional info.
+    if( NULL != mBidirectionalParagraphInfo )
     {
     {
-      const MarkupProcessor::StyledText& styledText( *it );
-
-      for( std::size_t i = 0u, length = styledText.mText.GetLength(); i < length; ++i )
-      {
-        relayoutData.mCharacterLogicalToVisualMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index );
-        relayoutData.mCharacterVisualToLogicalMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index );
-        ++index;
-      }
+      // It it has, copy to it.
+      *mBidirectionalParagraphInfo = *paragraph.mBidirectionalParagraphInfo;
+    }
+    else
+    {
+      // If it doesn't have, create a new one.
+      mBidirectionalParagraphInfo = new TextProcessor::BidirectionalParagraphInfo( *paragraph.mBidirectionalParagraphInfo );
     }
   }
 
     }
   }
 
-  // Split the paragraph in words
-  std::vector<MarkupProcessor::StyledTextArray> words;
-  TextProcessor::SplitInWords( convertedParagraph, words );
+  // If it has bidirectiona info per line, destroy them.
+  ClearBidirectionalInfo();
 
 
-  // if last word has a new paragraph separator, create a new word.
-  if( !words.empty() )
+  // Copies bidirectional info per line.
+  for( Vector<TextProcessor::BidirectionalLineInfo*>::ConstIterator it = mBidirectionalLinesInfo.Begin(), endIt = mBidirectionalLinesInfo.End(); it != endIt; ++it )
   {
   {
-    MarkupProcessor::StyledTextArray& word( *( words.end() - 1u ) );
-    if( word.size() > 1u )
-    {
-      // do nothing if the word has only one character.
-      MarkupProcessor::StyledText& styledText( *( word.end() - 1u ) );
-      if( !styledText.mText.IsEmpty() )
-      {
-        const std::size_t length = styledText.mText.GetLength();
-        if( styledText.mText[length-1u].IsNewLine() )
-        {
-          // Last character of this word is a new paragraph character.
+    mBidirectionalLinesInfo.PushBack( new TextProcessor::BidirectionalLineInfo( *( *it ) ) );
+  }
 
 
-          // Remove paragraph separator character from current word.
-          styledText.mText.Remove( length - 1u, 1u );
+  return *this;
+}
 
 
-          // Create a new word with the paragraph separator character.
-          MarkupProcessor::StyledText newParagraphText( Text( styledText.mText[length-1u] ), styledText.mStyle );
+void ParagraphLayoutInfo::ClearBidirectionalInfo()
+{
+  // Destroys the bidirectional infor per line.
+  for( Vector<TextProcessor::BidirectionalLineInfo*>::Iterator it = mBidirectionalLinesInfo.Begin(), endIt = mBidirectionalLinesInfo.End(); it != endIt; ++it )
+  {
+    delete *it;
+  }
+  mBidirectionalLinesInfo.Clear();
+}
 
 
-          MarkupProcessor::StyledTextArray newParagraphWord;
-          newParagraphWord.push_back( newParagraphText );
+void ParagraphLayoutInfo::ClearStyles()
+{
+  // Destroys the styles.
+  for( Vector<TextStyle*>::Iterator it = mTextStyles.Begin(), endIt = mTextStyles.End(); it != endIt; ++it )
+  {
+    delete *it;
+  }
+  mTextStyles.Clear();
+}
 
 
-          words.push_back( newParagraphWord );
-        }
-      }
-    }
+void CreateParagraphInfo( TextView::RelayoutData& relayoutData,
+                          ParagraphLayoutInfo& paragraphLayoutInfo )
+{
+  if( TextProcessor::ContainsRightToLeftCharacter( paragraphLayoutInfo.mText ) )
+  {
+    // If the text is bidirectional, the characters will be converted and reordered
+    // as specified by the Unicode Bidirectional Algorithm.
+
+    paragraphLayoutInfo.mBidirectionalParagraphInfo = new TextProcessor::BidirectionalParagraphInfo();
+
+    TextProcessor::ProcessBidirectionalText( paragraphLayoutInfo.mText, paragraphLayoutInfo.mBidirectionalParagraphInfo );
   }
 
   }
 
-  std::string lastCharacterFont; // Keeps the font used by the last character. It's used to set the font to a word separator.
+  // Split the paragraph in words. It retrieves the positions of white spaces and the last '\n' if there is one.
+  Vector<std::size_t> positions;
+  TextProcessor::SplitInWords( paragraphLayoutInfo.mText, positions );
 
 
-  // Traverse all words.
-  for( std::vector<MarkupProcessor::StyledTextArray>::const_iterator wordIt = words.begin(), wordEndIt = words.end(); wordIt != wordEndIt; ++wordIt )
-  {
-    const MarkupProcessor::StyledTextArray& word( *wordIt );
+  const std::size_t lastCharacterIndex = paragraphLayoutInfo.mText.GetLength() - 1u;
+  const bool isLastCharacterParagraphSeparator = paragraphLayoutInfo.mText.IsNewLine( lastCharacterIndex );
 
 
-    // Data structures for the new word.
-    WordLayoutInfo wordLayoutInfo;
+  // The number of words is ~the number of white spaces found + 1u.
+  // White spaces are also words.
+  // New line characters are also white spaces. If the last character is a white space the +1 is not needed.
+  const std::size_t numberOfWords = 2u * positions.Count() + ( isLastCharacterParagraphSeparator ? 0u : 1u );
 
 
-    CreateWordTextInfo( word,
-                        wordLayoutInfo );
+  // Reserve space for all the words.
+  paragraphLayoutInfo.mWordsLayoutInfo.resize( numberOfWords, WordLayoutInfo() );
+
+  // Traverses all positions creating and setting all character layout info objects to every word.
+  std::size_t wordIndex = 0u;
+  Vector<std::size_t>::ConstIterator positionIt = positions.Begin();
+  Vector<std::size_t>::ConstIterator positionEndIt = positions.End();
+  std::size_t from = 0u;
+  for( std::size_t positionIndex = 0u, size = positions.Count() + 1u; positionIndex < size; ++positionIndex )
+  {
+    const bool isEndPosition = positionIt == positionEndIt;
+    const std::size_t to = isEndPosition ? lastCharacterIndex + 1u : *positionIt;
 
 
-    // White space's size could be different depending on the type of font. It's important to use the same font than the previous character to
-    // avoid 'jumps' of characters when there is a switch between one text-actor per character and one text-actor per line and/or style.
-    if( WordSeparator == wordLayoutInfo.mType )
+    if( from < to )
     {
     {
-      // If current word is a word separator (white space) then the font of the last character is set.
-      for( CharacterLayoutInfoContainer::iterator characterIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), characterEndIt = wordLayoutInfo.mCharactersLayoutInfo.end();
-           characterIt != characterEndIt;
-           ++characterIt )
-      {
-        CharacterLayoutInfo& characterLayout( *characterIt );
+      // The word is not a white space.
+      WordLayoutInfo& wordLayoutInfo = *( paragraphLayoutInfo.mWordsLayoutInfo.begin() + wordIndex );
+      ++wordIndex;
+      // Sets the index within the paragraph to the first character of the word.
+      wordLayoutInfo.mFirstCharacter = from;
+      // Creates character layout info objects.
+      wordLayoutInfo.mCharactersLayoutInfo.resize( ( to - from ), CharacterLayoutInfo() );
+    }
 
 
-        characterLayout.mStyledText.mStyle.SetFontName( lastCharacterFont );
-      }
+    if( !isEndPosition )
+    {
+      // Create a word for the white space.
+      WordLayoutInfo& wordLayoutInfo = *( paragraphLayoutInfo.mWordsLayoutInfo.begin() + wordIndex );
+      ++wordIndex;
+      // Sets the index within the paragraph to the white space.
+      wordLayoutInfo.mFirstCharacter = to;
+      wordLayoutInfo.mType = WordSeparator;
+
+      CharacterLayoutInfo characterLayoutInfo;
+      wordLayoutInfo.mCharactersLayoutInfo.push_back( characterLayoutInfo );
+    }
+
+    from = to + 1u;
+
+    if( !isEndPosition )
+    {
+      // next white space position.
+      ++positionIt;
     }
     else
     {
     }
     else
     {
-      // kepps the font of the last character.
-      if( !wordLayoutInfo.mCharactersLayoutInfo.empty() )
+      // All white space positiona have been traversed.
+      // It may be some extra words. i.e if the text is \n.
+      // Erase them.
+      paragraphLayoutInfo.mWordsLayoutInfo.erase( paragraphLayoutInfo.mWordsLayoutInfo.begin() + wordIndex, paragraphLayoutInfo.mWordsLayoutInfo.end() );
+
+      // Check if the last character is a new paragraph character.
+      if( isLastCharacterParagraphSeparator )
       {
       {
-        lastCharacterFont = ( *( wordLayoutInfo.mCharactersLayoutInfo.end() - 1u ) ).mStyledText.mStyle.GetFontName();
+        ( *( paragraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) ).mType = ParagraphSeparator;
       }
     }
       }
     }
+  }
 
 
-    // Update the max word width figure.
-    relayoutData.mTextLayoutInfo.mMaxWordWidth = std::max( relayoutData.mTextLayoutInfo.mMaxWordWidth, wordLayoutInfo.mSize.width );
+  // Traverse all words and fill the layout info.
+  for( WordLayoutInfoContainer::iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); it != endIt; ++it )
+  {
+    WordLayoutInfo& wordLayoutInfo( *it );
+
+    CreateWordTextInfo( paragraphLayoutInfo.mText,
+                        paragraphLayoutInfo.mTextStyles,
+                        wordLayoutInfo );
 
     // Update layout info for the current paragraph.
 
     // Update layout info for the current paragraph.
+    UpdateSize( paragraphLayoutInfo.mSize, wordLayoutInfo.mSize );
     paragraphLayoutInfo.mAscender = std::max( paragraphLayoutInfo.mAscender, wordLayoutInfo.mAscender );
     paragraphLayoutInfo.mNumberOfCharacters += wordLayoutInfo.mCharactersLayoutInfo.size();
     paragraphLayoutInfo.mAscender = std::max( paragraphLayoutInfo.mAscender, wordLayoutInfo.mAscender );
     paragraphLayoutInfo.mNumberOfCharacters += wordLayoutInfo.mCharactersLayoutInfo.size();
-    UpdateSize( paragraphLayoutInfo.mSize, wordLayoutInfo.mSize );
 
 
-    // Add the word to the current paragraph.
-    paragraphLayoutInfo.mWordsLayoutInfo.push_back( wordLayoutInfo );
+    // Update the max word width figure.
+    relayoutData.mTextLayoutInfo.mMaxWordWidth = std::max( relayoutData.mTextLayoutInfo.mMaxWordWidth, wordLayoutInfo.mSize.width );
   } // end of words
 }
 
 void UpdateLayoutInfo( ParagraphLayoutInfo& paragraphLayoutInfo, float lineHeightOffset )
 {
   // Update layout info.
   } // end of words
 }
 
 void UpdateLayoutInfo( ParagraphLayoutInfo& paragraphLayoutInfo, float lineHeightOffset )
 {
   // Update layout info.
+
+  // Initialize members to be updated.
   paragraphLayoutInfo.mSize = Size::ZERO;
   paragraphLayoutInfo.mAscender = 0.f;
   paragraphLayoutInfo.mNumberOfCharacters = 0u;
   paragraphLayoutInfo.mSize = Size::ZERO;
   paragraphLayoutInfo.mAscender = 0.f;
   paragraphLayoutInfo.mNumberOfCharacters = 0u;
+
+  // Traverses all words.
   for( WordLayoutInfoContainer::iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
        it != endIt;
        ++it )
   {
     WordLayoutInfo& word( *it );
 
   for( WordLayoutInfoContainer::iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
        it != endIt;
        ++it )
   {
     WordLayoutInfo& word( *it );
 
+    // Sets the index within the paragraph to the first character of the word.
+    word.mFirstCharacter = paragraphLayoutInfo.mNumberOfCharacters;
+
+    // Updates the paragraph's size.
     UpdateSize( paragraphLayoutInfo.mSize, word.mSize );
     UpdateSize( paragraphLayoutInfo.mSize, word.mSize );
+
+    // Updates the paragraph's max asender.
     paragraphLayoutInfo.mAscender = std::max( paragraphLayoutInfo.mAscender, word.mAscender );
     paragraphLayoutInfo.mAscender = std::max( paragraphLayoutInfo.mAscender, word.mAscender );
+
+    // Updates the paragraph's number of characters.
     paragraphLayoutInfo.mNumberOfCharacters += word.mCharactersLayoutInfo.size();
   }
 
     paragraphLayoutInfo.mNumberOfCharacters += word.mCharactersLayoutInfo.size();
   }
 
+  // Sets the line height offset.
   paragraphLayoutInfo.mSize.height += lineHeightOffset;
   paragraphLayoutInfo.mLineHeightOffset = lineHeightOffset;
 }
   paragraphLayoutInfo.mSize.height += lineHeightOffset;
   paragraphLayoutInfo.mLineHeightOffset = lineHeightOffset;
 }
@@ -476,6 +582,26 @@ void SplitParagraph( const TextInfoIndices& indices,
 
   // 6) update layout info of the first paragraph.
   UpdateLayoutInfo( firstParagraphLayoutInfo, lineHeightOffset );
 
   // 6) update layout info of the first paragraph.
   UpdateLayoutInfo( firstParagraphLayoutInfo, lineHeightOffset );
+
+  // 7) Split text and styles.
+
+  // Copies the whole text to the last part of the paragraph.
+  lastParagraphLayoutInfo.mText = firstParagraphLayoutInfo.mText;
+
+  // Removes from the first part of the paragraph the text that goes to the last part.
+  firstParagraphLayoutInfo.mText.Remove( indices.mCharacterParagraphIndex, firstParagraphLayoutInfo.mText.GetLength() - indices.mCharacterParagraphIndex );
+
+  // Removes from the last part of the paragraph the text that remains in the first part.
+  lastParagraphLayoutInfo.mText.Remove( 0u, indices.mCharacterParagraphIndex );
+
+  // Sets the character's styles for the last part of the paragraph.
+  lastParagraphLayoutInfo.mTextStyles.Insert( lastParagraphLayoutInfo.mTextStyles.End(),
+                                         firstParagraphLayoutInfo.mTextStyles.Begin() + indices.mCharacterParagraphIndex,
+                                         firstParagraphLayoutInfo.mTextStyles.End() );
+
+  // Removes the character's styles that go to the last part of the paragraph.
+  firstParagraphLayoutInfo.mTextStyles.Erase( firstParagraphLayoutInfo.mTextStyles.Begin() + indices.mCharacterParagraphIndex,
+                                         firstParagraphLayoutInfo.mTextStyles.End() );
 }
 
 void MergeParagraph( ParagraphLayoutInfo& firstParagraphLayoutInfo,
 }
 
 void MergeParagraph( ParagraphLayoutInfo& firstParagraphLayoutInfo,
@@ -528,14 +654,29 @@ void MergeParagraph( ParagraphLayoutInfo& firstParagraphLayoutInfo,
   // Merge layout info
 
   // Insert the layout of the words.
   // Merge layout info
 
   // Insert the layout of the words.
+  const std::size_t numberOfWords = firstParagraphLayoutInfo.mWordsLayoutInfo.size();
   firstParagraphLayoutInfo.mWordsLayoutInfo.insert( firstParagraphLayoutInfo.mWordsLayoutInfo.end(),
                                                    lastParagraphLayoutInfo.mWordsLayoutInfo.begin() + index, lastParagraphLayoutInfo.mWordsLayoutInfo.end() );
 
   firstParagraphLayoutInfo.mWordsLayoutInfo.insert( firstParagraphLayoutInfo.mWordsLayoutInfo.end(),
                                                    lastParagraphLayoutInfo.mWordsLayoutInfo.begin() + index, lastParagraphLayoutInfo.mWordsLayoutInfo.end() );
 
+  // Increase the index of the first character of each inserted word.
+  for( WordLayoutInfoContainer::iterator it = firstParagraphLayoutInfo.mWordsLayoutInfo.begin() + numberOfWords, endIt = firstParagraphLayoutInfo.mWordsLayoutInfo.end(); it != endIt; ++it )
+  {
+    WordLayoutInfo& word( *it );
+    word.mFirstCharacter += firstParagraphLayoutInfo.mNumberOfCharacters;
+  }
+
   // Update the size and other layout parameters.
   UpdateSize( firstParagraphLayoutInfo.mSize, lastParagraphLayoutInfo.mSize );
   firstParagraphLayoutInfo.mAscender = std::max( firstParagraphLayoutInfo.mAscender, lastParagraphLayoutInfo.mAscender );
   firstParagraphLayoutInfo.mLineHeightOffset = std::max( firstParagraphLayoutInfo.mLineHeightOffset, lastParagraphLayoutInfo.mLineHeightOffset );
   firstParagraphLayoutInfo.mNumberOfCharacters += lastParagraphLayoutInfo.mNumberOfCharacters;
   // Update the size and other layout parameters.
   UpdateSize( firstParagraphLayoutInfo.mSize, lastParagraphLayoutInfo.mSize );
   firstParagraphLayoutInfo.mAscender = std::max( firstParagraphLayoutInfo.mAscender, lastParagraphLayoutInfo.mAscender );
   firstParagraphLayoutInfo.mLineHeightOffset = std::max( firstParagraphLayoutInfo.mLineHeightOffset, lastParagraphLayoutInfo.mLineHeightOffset );
   firstParagraphLayoutInfo.mNumberOfCharacters += lastParagraphLayoutInfo.mNumberOfCharacters;
+
+  // Merge text and styles.
+  firstParagraphLayoutInfo.mText.Append( lastParagraphLayoutInfo.mText );
+  for( Vector<TextStyle*>::ConstIterator it = lastParagraphLayoutInfo.mTextStyles.Begin(), endIt = lastParagraphLayoutInfo.mTextStyles.End(); it != endIt; ++it )
+  {
+    firstParagraphLayoutInfo.mTextStyles.PushBack( new TextStyle( *(*it) ) );
+  }
 }
 
 WordLayoutInfo GetLastWordLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo )
 }
 
 WordLayoutInfo GetLastWordLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo )
index b43489c..3e9b0f0 100644 (file)
@@ -36,12 +36,10 @@ namespace TextViewProcessor
 /**
  * Creates a data structure with info to layout the paragraph, and data structures with useful info to modify the layout data structure if characters are added or removed.
  *
 /**
  * Creates a data structure with info to layout the paragraph, and data structures with useful info to modify the layout data structure if characters are added or removed.
  *
- * @param[in] paragraph The styled paragraph.
  * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text).
  * @param[out] paragraphLayoutInfo Layout info for the whole paragraph.
  */
  * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text).
  * @param[out] paragraphLayoutInfo Layout info for the whole paragraph.
  */
-void CreateParagraphInfo( const MarkupProcessor::StyledTextArray& line,
-                          TextView::RelayoutData& relayoutData,
+void CreateParagraphInfo( TextView::RelayoutData& relayoutData,
                           ParagraphLayoutInfo& paragraphLayoutInfo );
 
 /**
                           ParagraphLayoutInfo& paragraphLayoutInfo );
 
 /**
index b3a59c7..713c681 100644 (file)
@@ -19,7 +19,7 @@
 #include <dali-toolkit/internal/controls/text-view/text-view-processor-dbg.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/controls/text-view/text-view-processor-dbg.h>
 
 // INTERNAL INCLUDES
-#include <dali/public-api/actors/text-actor.h>
+#include <dali-toolkit/internal/controls/text-view/text-view-processor-types.h>
 
 namespace Dali
 {
 
 namespace Dali
 {
@@ -39,30 +39,9 @@ Debug::Filter* gTextViewProcessorLogFilter = Debug::Filter::New(Debug::NoLogging
 
 void dbgPrint( const WordLayoutInfo& word )
 {
 
 void dbgPrint( const WordLayoutInfo& word )
 {
-  for( CharacterLayoutInfoContainer::const_iterator characterIt = word.mCharactersLayoutInfo.begin(), endCharacterIt = word.mCharactersLayoutInfo.end();
-       characterIt != endCharacterIt;
-       ++characterIt )
-  {
-    const CharacterLayoutInfo& character( *characterIt );
-
-    std::cout << "[" << character.mSize << std::endl;
-    std::cout << " ascender " << character.mAscender << std::endl;
-
-    TextActor textActor = TextActor::DownCast( character.mGlyphActor );
-    if( textActor )
-    {
-      std::cout << "[" << textActor.GetText() << "]";
-    }
-    else
-    {
-      std::cout << "[ImageActor]" << std::endl;
-    }
-    std::cout << "{" << character.mStyledText.mText.GetText() << "}";
-  }
-  std::cout << "     size " << word.mSize << std::endl;
-  std::cout << " ascender " << word.mAscender << std::endl;
-  std::cout << " num char " << word.mCharactersLayoutInfo.size() << std::endl;
-  std::cout << "     type ";
+  std::cout << "       size " << word.mSize << std::endl;
+  std::cout << "   ascender " << word.mAscender << std::endl;
+  std::cout << "       type ";
   switch( word.mType )
   {
     case NoSeparator:
   switch( word.mType )
   {
     case NoSeparator:
@@ -81,11 +60,24 @@ void dbgPrint( const WordLayoutInfo& word )
       break;
     }
   }
       break;
     }
   }
+  std::cout << " first char " << word.mFirstCharacter << std::endl;
+  std::cout << "   num char " << word.mCharactersLayoutInfo.size() << std::endl;
+  for( CharacterLayoutInfoContainer::const_iterator characterIt = word.mCharactersLayoutInfo.begin(), endCharacterIt = word.mCharactersLayoutInfo.end();
+       characterIt != endCharacterIt;
+       ++characterIt )
+  {
+    const CharacterLayoutInfo& character( *characterIt );
+
+    std::cout << "[" << character.mSize << std::endl;
+    std::cout << " ascender " << character.mAscender << std::endl;
+  }
 }
 
 void dbgPrint( const ParagraphLayoutInfo& paragraph )
 {
   std::cout << "< ";
 }
 
 void dbgPrint( const ParagraphLayoutInfo& paragraph )
 {
   std::cout << "< ";
+  std::cout << "  text : [" << paragraph.mText.GetText() << "]" << std::endl;
+  std::cout << "  number of styles : " << paragraph.mTextStyles.Count() << std::endl;
   std::cout << paragraph.mSize;
   for( WordLayoutInfoContainer::const_iterator wordIt = paragraph.mWordsLayoutInfo.begin(), endWordIt = paragraph.mWordsLayoutInfo.end();
        wordIt != endWordIt;
   std::cout << paragraph.mSize;
   for( WordLayoutInfoContainer::const_iterator wordIt = paragraph.mWordsLayoutInfo.begin(), endWordIt = paragraph.mWordsLayoutInfo.end();
        wordIt != endWordIt;
@@ -157,6 +149,7 @@ void dbgPrint( const TextInfoIndices& indices )
   std::cout << "          paragraph : " << indices.mParagraphIndex << std::endl;
   std::cout << "               word : " << indices.mWordIndex << std::endl;
   std::cout << "               char : " << indices.mCharacterIndex << std::endl;
   std::cout << "          paragraph : " << indices.mParagraphIndex << std::endl;
   std::cout << "               word : " << indices.mWordIndex << std::endl;
   std::cout << "               char : " << indices.mCharacterIndex << std::endl;
+  std::cout << "  char in paragraph : " << indices.mCharacterParagraphIndex << std::endl;
 }
 
 void dbgPrint( const MarkupProcessor::StyledTextArray& textArray )
 }
 
 void dbgPrint( const MarkupProcessor::StyledTextArray& textArray )
@@ -169,18 +162,6 @@ void dbgPrint( const MarkupProcessor::StyledTextArray& textArray )
   }
 }
 
   }
 }
 
-void dbgPrintText( const WordLayoutInfo& word )
-{
-  for( CharacterLayoutInfoContainer::const_iterator characterIt = word.mCharactersLayoutInfo.begin(), endCharacterIt = word.mCharactersLayoutInfo.end();
-       characterIt != endCharacterIt;
-       ++characterIt )
-  {
-    const CharacterLayoutInfo& character( *characterIt );
-
-    std::cout << character.mStyledText.mText.GetText();
-  }
-}
-
 } // namespace TextViewProcessor
 
 } // namespace Internal
 } // namespace TextViewProcessor
 
 } // namespace Internal
index b5131e4..2529bb8 100644 (file)
  */
 
 // INTERNAL INCLUDES
  */
 
 // INTERNAL INCLUDES
-#include <dali/integration-api/debug.h>
 #include <dali-toolkit/public-api/markup-processor/markup-processor.h>
 #include <dali-toolkit/public-api/markup-processor/markup-processor.h>
-#include <dali-toolkit/internal/controls/text-view/text-view-processor-types.h>
+#include <dali/integration-api/debug.h>
 
 namespace Dali
 {
 
 
 namespace Dali
 {
 
+//Forward declarations.
+class TextStyle;
+
 namespace Toolkit
 {
 
 namespace Toolkit
 {
 
@@ -35,6 +37,12 @@ namespace Internal
 namespace TextViewProcessor
 {
 
 namespace TextViewProcessor
 {
 
+//Forward declarations.
+struct WordLayoutInfo;
+struct ParagraphLayoutInfo;
+struct TextLayoutInfo;
+struct TextInfoIndices;
+
 #if defined(DEBUG_ENABLED)
 extern Debug::Filter* gTextViewProcessorLogFilter;
 #endif
 #if defined(DEBUG_ENABLED)
 extern Debug::Filter* gTextViewProcessorLogFilter;
 #endif
@@ -46,8 +54,6 @@ void dbgPrint( const TextStyle& style );
 void dbgPrint( const TextInfoIndices& indices );
 void dbgPrint( const MarkupProcessor::StyledTextArray& text );
 
 void dbgPrint( const TextInfoIndices& indices );
 void dbgPrint( const MarkupProcessor::StyledTextArray& text );
 
-void dbgPrintText( const WordLayoutInfo& word );
-
 } // namespace TextViewProcessor
 
 } // namespace Internal
 } // namespace TextViewProcessor
 
 } // namespace Internal
index 1855b6e..43a5f4e 100644 (file)
@@ -58,20 +58,20 @@ TextSeparatorType GetTextSeparatorType( const Character& character )
   return ( character.IsNewLine() ? ParagraphSeparator : ( character.IsWhiteSpace() ? WordSeparator : NoSeparator ) );
 }
 
   return ( character.IsNewLine() ? ParagraphSeparator : ( character.IsWhiteSpace() ? WordSeparator : NoSeparator ) );
 }
 
-void ChooseFontFamilyName( MarkupProcessor::StyledText& text )
+void ChooseFontFamilyName( const Character& character, TextStyle& style )
 {
   DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "-->TextViewProcessor::ChooseFontFamilyName\n" );
 {
   DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "-->TextViewProcessor::ChooseFontFamilyName\n" );
-  DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "   input font name: [%s]\n", text.mStyle.GetFontName().c_str() );
+  DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "   input font name: [%s]\n", style.GetFontName().c_str() );
 
   bool userDefinedFontFamilyName = false;
 
   // First check if there is a font defined in the style and it supports the given text.
 
   bool userDefinedFontFamilyName = false;
 
   // First check if there is a font defined in the style and it supports the given text.
-  if( !text.mStyle.GetFontName().empty() )
+  if( !style.GetFontName().empty() )
   {
   {
-    const FontParameters fontParams( text.mStyle.GetFontName(), text.mStyle.GetFontStyle() , text.mStyle.GetFontPointSize() );
+    const FontParameters fontParams( style.GetFontName(), style.GetFontStyle() , style.GetFontPointSize() );
     const Font font = Font::New( fontParams );
 
     const Font font = Font::New( fontParams );
 
-    if( !font.IsDefaultSystemFont() && font.AllGlyphsSupported( text.mText ) )
+    if( !font.IsDefaultSystemFont() && font.AllGlyphsSupported( character ) )
     {
       userDefinedFontFamilyName = true;
     }
     {
       userDefinedFontFamilyName = true;
     }
@@ -82,20 +82,20 @@ void ChooseFontFamilyName( MarkupProcessor::StyledText& text )
     const Font defaultSystemFont = Font::New();
 
     // At this point no font is set or doesn't support the given text.
     const Font defaultSystemFont = Font::New();
 
     // At this point no font is set or doesn't support the given text.
-    if( !defaultSystemFont.AllGlyphsSupported( text.mText ) )
+    if( !defaultSystemFont.AllGlyphsSupported( character ) )
     {
       // If the default system font doesn't support the given text,
       // an appropiate font is selected.
     {
       // If the default system font doesn't support the given text,
       // an appropiate font is selected.
-      text.mStyle.SetFontName( Font::GetFamilyForText( text.mText ) );
+      style.SetFontName( Font::GetFamilyForText( character ) );
       // @TODO Font::GetFamilyForText() should return font family and font style.
     }
     else
     {
       // All characters are supported with default font, so use it
       // @TODO Font::GetFamilyForText() should return font family and font style.
     }
     else
     {
       // All characters are supported with default font, so use it
-      text.mStyle.SetFontName( "" );
+      style.SetFontName( "" );
     }
   }
     }
   }
-  DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "  output font name: [%s]\n", text.mStyle.GetFontName().c_str() );
+  DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "  output font name: [%s]\n", style.GetFontName().c_str() );
   DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "<--TextViewProcessor::ChooseFontFamilyName\n" );
 }
 
   DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "<--TextViewProcessor::ChooseFontFamilyName\n" );
 }
 
@@ -123,6 +123,7 @@ void GetIndicesFromGlobalCharacterIndex( const std::size_t index,
        ++paragraphIt, ++indices.mParagraphIndex )
   {
     const ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphIt );
        ++paragraphIt, ++indices.mParagraphIndex )
   {
     const ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphIt );
+    std::size_t currentCharactersTraversed = currentIndex; // stores how many characters have been traversed until this paragraph.
 
     if( currentIndex + paragraphLayoutInfo.mNumberOfCharacters > index )
     {
 
     if( currentIndex + paragraphLayoutInfo.mNumberOfCharacters > index )
     {
@@ -138,6 +139,7 @@ void GetIndicesFromGlobalCharacterIndex( const std::size_t index,
         {
           // The character is in this word
           indices.mCharacterIndex = index - currentIndex;
         {
           // The character is in this word
           indices.mCharacterIndex = index - currentIndex;
+          indices.mCharacterParagraphIndex = index - currentCharactersTraversed;
           found = true;
         }
         else
           found = true;
         }
         else
index ef9fb2a..c543e32 100644 (file)
@@ -71,13 +71,14 @@ void UpdateSize( Size& size1, const Size& size2, SizeGrowType type = GrowWidth )
 TextSeparatorType GetTextSeparatorType( const Character& character );
 
 /**
 TextSeparatorType GetTextSeparatorType( const Character& character );
 
 /**
- * Choose a suitable font family name for the given styled text.
+ * Choose a suitable font family name for the given character.
  *
  *
- * It may modify the text-style of the given text by setting a suitable font-family.
+ * It may modify the text-style of the given character by setting a suitable font-family.
  *
  *
- * @param[in,out] text Text with style.
+ * @param[in] character The character.
+ * @param[in,out] style The style of the character.
  */
  */
-void ChooseFontFamilyName( MarkupProcessor::StyledText& text );
+void ChooseFontFamilyName( const Character& character, TextStyle& style );
 
 /**
  * Retrieves the line, word and character indices for the given global character's index.
 
 /**
  * Retrieves the line, word and character indices for the given global character's index.
index a4d1873..15005cc 100644 (file)
 
 // INTERNAL INCLUDES
 #include <dali/public-api/actors/renderable-actor.h>
 
 // INTERNAL INCLUDES
 #include <dali/public-api/actors/renderable-actor.h>
-#include <dali-toolkit/public-api/markup-processor/markup-processor.h>
+#include <dali/public-api/text/text.h>
 
 namespace Dali
 {
 
 
 namespace Dali
 {
 
+class TextStyle;
+
 namespace Toolkit
 {
 
 namespace Internal
 {
 
 namespace Toolkit
 {
 
 namespace Internal
 {
 
+namespace TextProcessor
+{
+// Forward declarations.
+struct BidirectionalParagraphInfo;
+struct BidirectionalLineInfo;
+} // namespace TextProcessor
+
 namespace TextViewProcessor
 {
 
 namespace TextViewProcessor
 {
 
@@ -84,6 +93,7 @@ struct TextInfoIndices
   std::size_t mParagraphIndex;          ///< The paragraph index within the text.
   std::size_t mWordIndex;               ///< The word index within the paragraph.
   std::size_t mCharacterIndex;          ///< The character index within the word.
   std::size_t mParagraphIndex;          ///< The paragraph index within the text.
   std::size_t mWordIndex;               ///< The word index within the paragraph.
   std::size_t mCharacterIndex;          ///< The character index within the word.
+  std::size_t mCharacterParagraphIndex; ///< The character index within the paragraph.
 };
 
 /**
 };
 
 /**
@@ -161,10 +171,9 @@ struct CharacterLayoutInfo
   Vector3     mPosition;           ///< Position within the text-view
   Vector2     mOffset;             ///< Alignment and justification offset.
 
   Vector3     mPosition;           ///< Position within the text-view
   Vector2     mOffset;             ///< Alignment and justification offset.
 
-  RenderableActor             mGlyphActor;   ///< Handle to a text-actor.
-  MarkupProcessor::StyledText mStyledText;   ///< Stores the text and its style.
-  float                       mColorAlpha;   ///< Alpha component for the initial text color when text is faded.
-  GradientInfo*               mGradientInfo; ///< Stores gradient info.
+  RenderableActor mGlyphActor;     ///< Handle to a text-actor.
+  float           mColorAlpha;     ///< Alpha component for the initial text color when text is faded.
+  GradientInfo*   mGradientInfo;   ///< Stores gradient info.
 
   bool            mIsVisible:1;    ///< Whether the text-actor is visible.
   bool            mSetText:1;      ///< Whether a new text needs to be set in the text-actor.
 
   bool            mIsVisible:1;    ///< Whether the text-actor is visible.
   bool            mSetText:1;      ///< Whether a new text needs to be set in the text-actor.
@@ -205,11 +214,36 @@ struct WordLayoutInfo
   Size                              mSize;                      ///< Size of the word.
   float                             mAscender;                  ///< Max of all ascenders of all characters.
   TextSeparatorType                 mType;                      ///< Whether this word is a word separator, a line separator or is not a separator.
   Size                              mSize;                      ///< Size of the word.
   float                             mAscender;                  ///< Max of all ascenders of all characters.
   TextSeparatorType                 mType;                      ///< Whether this word is a word separator, a line separator or is not a separator.
+  std::size_t                       mFirstCharacter;            ///< Index to the first character of the word within the paragraph.
   CharacterLayoutInfoContainer      mCharactersLayoutInfo;      ///< Layout info for all characters.
 };
 typedef std::vector<WordLayoutInfo> WordLayoutInfoContainer;
 
 /**
   CharacterLayoutInfoContainer      mCharactersLayoutInfo;      ///< Layout info for all characters.
 };
 typedef std::vector<WordLayoutInfo> WordLayoutInfoContainer;
 
 /**
+ * Stores the reordered layout for right to left text.
+ */
+struct RightToLeftParagraphLayout
+{
+  RightToLeftParagraphLayout()
+  : mWordsLayoutInfo(),
+    mText(),
+    mTextStyles(),
+    mPreviousLayoutCleared( false )
+  {
+  }
+
+  WordLayoutInfoContainer mWordsLayoutInfo;         ///< Layout info for all words.
+  Text                    mText;                    ///< Stores the text.
+  Vector<TextStyle*>      mTextStyles;              ///< Stores the style per each character.
+  bool                    mPreviousLayoutCleared:1; ///< Whether the previous right to left layout has been cleared.
+
+  /**
+   * Clears the word layout vector, the text and the vector of styles.
+   */
+  void Clear();
+};
+
+/**
  * Layout information for a paragraph.
  */
 struct ParagraphLayoutInfo
  * Layout information for a paragraph.
  */
 struct ParagraphLayoutInfo
@@ -224,7 +258,7 @@ struct ParagraphLayoutInfo
   /**
    * Default destructor.
    *
   /**
    * Default destructor.
    *
-   * Clears all words.
+   * Clears all words, deletes all text styles, the paragraph bidirectional info and all bidirectional infor for each line.
    */
   ~ParagraphLayoutInfo();
 
    */
   ~ParagraphLayoutInfo();
 
@@ -238,11 +272,30 @@ struct ParagraphLayoutInfo
    */
   ParagraphLayoutInfo& operator=( const ParagraphLayoutInfo& paragraph );
 
    */
   ParagraphLayoutInfo& operator=( const ParagraphLayoutInfo& paragraph );
 
+  /**
+   * Deletes the bidirectional info for each line.
+   */
+  void ClearBidirectionalInfo();
+
+private:
+
+  /**
+   * Deletes all text styles.
+   */
+  void ClearStyles();
+
+public:
   Size                                          mSize;                       ///< Size of the paragraph.
   float                                         mAscender;                   ///< Max of all ascenders of all words.
   float                                         mLineHeightOffset;           ///< Line height offset.
   Size                                          mSize;                       ///< Size of the paragraph.
   float                                         mAscender;                   ///< Max of all ascenders of all words.
   float                                         mLineHeightOffset;           ///< Line height offset.
+  std::size_t                                   mFirstCharacter;             ///< Index to the first character of the paragraph.
   std::size_t                                   mNumberOfCharacters;         ///< Stores the number of characters.
   WordLayoutInfoContainer                       mWordsLayoutInfo;            ///< Layout info for all words.
   std::size_t                                   mNumberOfCharacters;         ///< Stores the number of characters.
   WordLayoutInfoContainer                       mWordsLayoutInfo;            ///< Layout info for all words.
+  Text                                          mText;                       ///< Stores the text.
+  Vector<TextStyle*>                            mTextStyles;                 ///< Stores the style per each character.
+  RightToLeftParagraphLayout*                   mRightToLeftLayout;          ///< Stores the reordered layout for the paragraph.
+  TextProcessor::BidirectionalParagraphInfo*    mBidirectionalParagraphInfo; ///< Contains bidirectional info for the whole paragraph. Set to NULL if the paragraph has left to right characters only.
+  Vector<TextProcessor::BidirectionalLineInfo*> mBidirectionalLinesInfo;     ///< Contains bidirectional info for each laid-out line.
 };
 typedef std::vector<ParagraphLayoutInfo> ParagraphLayoutInfoContainer;
 
 };
 typedef std::vector<ParagraphLayoutInfo> ParagraphLayoutInfoContainer;
 
@@ -259,6 +312,13 @@ struct TextLayoutInfo
   TextLayoutInfo();
 
   /**
   TextLayoutInfo();
 
   /**
+   * Defualt destructor.
+   *
+   * Clears the paragraph vector, the ellipsis text and deletes all ellipsis styles.
+   */
+  ~TextLayoutInfo();
+
+  /**
    * Copy constructor.
    */
   TextLayoutInfo( const TextLayoutInfo& text );
    * Copy constructor.
    */
   TextLayoutInfo( const TextLayoutInfo& text );
@@ -268,12 +328,21 @@ struct TextLayoutInfo
    */
   TextLayoutInfo& operator=( const TextLayoutInfo& text );
 
    */
   TextLayoutInfo& operator=( const TextLayoutInfo& text );
 
+private:
+  /**
+   * Deletes all the ellipsis text styles.
+   */
+  void ClearStyles();
+
+public:
   Size                         mWholeTextSize;        ///< width and height of the whole text.
   float                        mMaxWordWidth;         ///< maximum width between all words.
   float                        mMaxItalicsOffset;     ///< When rendering text-view in offscreen an extra width offset is needed to prevent italic characters to be cut if they are in the right edge.
   std::size_t                  mNumberOfCharacters;   ///< Stores the number of characters.
   ParagraphLayoutInfoContainer mParagraphsLayoutInfo; ///< Layout information for all paragraphs.
   WordLayoutInfo               mEllipsizeLayoutInfo;  ///< Layout information for the ellipsize text.
   Size                         mWholeTextSize;        ///< width and height of the whole text.
   float                        mMaxWordWidth;         ///< maximum width between all words.
   float                        mMaxItalicsOffset;     ///< When rendering text-view in offscreen an extra width offset is needed to prevent italic characters to be cut if they are in the right edge.
   std::size_t                  mNumberOfCharacters;   ///< Stores the number of characters.
   ParagraphLayoutInfoContainer mParagraphsLayoutInfo; ///< Layout information for all paragraphs.
   WordLayoutInfo               mEllipsizeLayoutInfo;  ///< Layout information for the ellipsize text.
+  Dali::Text                   mEllipsisText;         ///< The ellipsis text.
+  Vector<TextStyle*>           mEllipsisTextStyles;   ///< Stores the style per each character of the ellipsis text.
 };
 
 } // namespace TextViewProcessor
 };
 
 } // namespace TextViewProcessor
index a485a6e..40f1fab 100644 (file)
 #include <dali-toolkit/internal/controls/text-view/text-view-processor.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/controls/text-view/text-view-processor.h>
 
 // INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h>
 #include <dali-toolkit/internal/controls/text-view/text-processor.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.h>
 #include <dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h>
 #include <dali-toolkit/internal/controls/text-view/text-processor.h>
+#include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
 
 namespace Dali
 {
 
 namespace Dali
 {
@@ -84,7 +86,8 @@ void UpdateLayoutInfo( TextLayoutInfo& textLayoutInfo )
 TextInfoIndices::TextInfoIndices()
 : mParagraphIndex( 0u ),
   mWordIndex( 0u ),
 TextInfoIndices::TextInfoIndices()
 : mParagraphIndex( 0u ),
   mWordIndex( 0u ),
-  mCharacterIndex( 0u )
+  mCharacterIndex( 0u ),
+  mCharacterParagraphIndex( 0u )
 {
 }
 
 {
 }
 
@@ -93,7 +96,8 @@ TextInfoIndices::TextInfoIndices( const std::size_t paragraphIndex,
                                   const std::size_t characterIndex )
 : mParagraphIndex( paragraphIndex ),
   mWordIndex( wordIndex ),
                                   const std::size_t characterIndex )
 : mParagraphIndex( paragraphIndex ),
   mWordIndex( wordIndex ),
-  mCharacterIndex( characterIndex )
+  mCharacterIndex( characterIndex ),
+  mCharacterParagraphIndex( 0u )
 {
 }
 
 {
 }
 
@@ -101,7 +105,8 @@ bool TextInfoIndices::operator==( const TextInfoIndices& indices ) const
 {
   return ( ( mParagraphIndex == indices.mParagraphIndex ) &&
            ( mWordIndex == indices.mWordIndex ) &&
 {
   return ( ( mParagraphIndex == indices.mParagraphIndex ) &&
            ( mWordIndex == indices.mWordIndex ) &&
-           ( mCharacterIndex == indices.mCharacterIndex ) );
+           ( mCharacterIndex == indices.mCharacterIndex ) &&
+           ( mCharacterParagraphIndex == indices.mCharacterParagraphIndex ) );
 }
 
 /////////////////////
 }
 
 /////////////////////
@@ -114,8 +119,19 @@ TextLayoutInfo::TextLayoutInfo()
   mMaxItalicsOffset( 0.f ),
   mNumberOfCharacters( 0u ),
   mParagraphsLayoutInfo(),
   mMaxItalicsOffset( 0.f ),
   mNumberOfCharacters( 0u ),
   mParagraphsLayoutInfo(),
-  mEllipsizeLayoutInfo()
+  mEllipsizeLayoutInfo(),
+  mEllipsisText( "..." ),
+  mEllipsisTextStyles()
 {
 {
+  // Sets default styles for the default ellipsis text.
+  mEllipsisTextStyles.PushBack( new TextStyle() );
+  mEllipsisTextStyles.PushBack( new TextStyle() );
+  mEllipsisTextStyles.PushBack( new TextStyle() );
+}
+
+TextLayoutInfo::~TextLayoutInfo()
+{
+  ClearStyles();
 }
 
 TextLayoutInfo::TextLayoutInfo( const TextLayoutInfo& text )
 }
 
 TextLayoutInfo::TextLayoutInfo( const TextLayoutInfo& text )
@@ -124,8 +140,14 @@ TextLayoutInfo::TextLayoutInfo( const TextLayoutInfo& text )
   mMaxItalicsOffset( text.mMaxItalicsOffset ),
   mNumberOfCharacters( text.mNumberOfCharacters ),
   mParagraphsLayoutInfo( text.mParagraphsLayoutInfo ),
   mMaxItalicsOffset( text.mMaxItalicsOffset ),
   mNumberOfCharacters( text.mNumberOfCharacters ),
   mParagraphsLayoutInfo( text.mParagraphsLayoutInfo ),
-  mEllipsizeLayoutInfo( text.mEllipsizeLayoutInfo )
+  mEllipsizeLayoutInfo( text.mEllipsizeLayoutInfo ),
+  mEllipsisText( text.mEllipsisText ),
+  mEllipsisTextStyles()
 {
 {
+  for( Vector<TextStyle*>::ConstIterator it = text.mEllipsisTextStyles.Begin(), endIt = text.mEllipsisTextStyles.End(); it != endIt; ++it )
+  {
+    mEllipsisTextStyles.PushBack( new TextStyle( *(*it) ) );
+  }
 }
 
 TextLayoutInfo& TextLayoutInfo::operator=( const TextLayoutInfo& text )
 }
 
 TextLayoutInfo& TextLayoutInfo::operator=( const TextLayoutInfo& text )
@@ -138,11 +160,27 @@ TextLayoutInfo& TextLayoutInfo::operator=( const TextLayoutInfo& text )
     mNumberOfCharacters = text.mNumberOfCharacters;
     mParagraphsLayoutInfo = text.mParagraphsLayoutInfo;
     mEllipsizeLayoutInfo = text.mEllipsizeLayoutInfo;
     mNumberOfCharacters = text.mNumberOfCharacters;
     mParagraphsLayoutInfo = text.mParagraphsLayoutInfo;
     mEllipsizeLayoutInfo = text.mEllipsizeLayoutInfo;
-  }
+    mEllipsisText = text.mEllipsisText;
 
 
+    ClearStyles();
+
+    for( Vector<TextStyle*>::ConstIterator it = text.mEllipsisTextStyles.Begin(), endIt = text.mEllipsisTextStyles.End(); it != endIt; ++it )
+    {
+      mEllipsisTextStyles.PushBack( new TextStyle( *(*it) ) );
+    }
+  }
   return *this;
 }
 
   return *this;
 }
 
+void TextLayoutInfo::ClearStyles()
+{
+  for( Vector<TextStyle*>::Iterator it = mEllipsisTextStyles.Begin(), endIt = mEllipsisTextStyles.End(); it != endIt; ++it )
+  {
+    delete *it;
+  }
+  mEllipsisTextStyles.Clear();
+}
+
 /////////////////////////////////////////////////////////////////////////////////////////////
 
 void CreateTextInfo( const MarkupProcessor::StyledTextArray& text,
 /////////////////////////////////////////////////////////////////////////////////////////////
 
 void CreateTextInfo( const MarkupProcessor::StyledTextArray& text,
@@ -152,9 +190,11 @@ void CreateTextInfo( const MarkupProcessor::StyledTextArray& text,
   // * Traverse the given text spliting it in paragraphs and each paragraph in words.
   // * White spaces and new paragraph characters are alone in one word.
   // * Bidirectional text is processed in each paragraph.
   // * Traverse the given text spliting it in paragraphs and each paragraph in words.
   // * White spaces and new paragraph characters are alone in one word.
   // * Bidirectional text is processed in each paragraph.
+  //     It creates the conversion tables
+  //     It does the ligatures if there is arabic glyphs.
+  //     It doesn't reorder the text as it must be done for each line not for the paragraph.
   // * Generates a layout data structure to store layout information (size, position, ascender, text direction, etc) and metrics of all characters.
   // * Generates a layout data structure to store layout information (size, position, ascender, text direction, etc) and metrics of all characters.
-  // * Generates a text-actor data structure to store text, style and text-actors.
-  // TODO: finish and test the bidirectional implementation.
+  // * Store text for each paragraph and the style for each character.
 
   // Collect previously created text-actors.
   std::vector<TextActor> textActors;
 
   // Collect previously created text-actors.
   std::vector<TextActor> textActors;
@@ -168,49 +208,77 @@ void CreateTextInfo( const MarkupProcessor::StyledTextArray& text,
   }
 
   // Store the ellipsize layout info before clearing the previous created info.
   }
 
   // Store the ellipsize layout info before clearing the previous created info.
+  // TODO: fix this. Don't clear the ellipsis layout, store it somewhere else ...
   const WordLayoutInfo ellipsizeInfo = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo;
   const WordLayoutInfo ellipsizeInfo = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo;
+  Dali::Text           ellipsisText = relayoutData.mTextLayoutInfo.mEllipsisText;
+  Vector<TextStyle*>   ellipsisTextStyles = relayoutData.mTextLayoutInfo.mEllipsisTextStyles;
+  relayoutData.mTextLayoutInfo.mEllipsisTextStyles.Clear();
 
 
-  // clear previous created info.
+  // clear previously created info.
   relayoutData.mTextLayoutInfo = TextLayoutInfo();
   relayoutData.mCharacterLogicalToVisualMap.clear();
   relayoutData.mCharacterVisualToLogicalMap.clear();
 
   // Sets the ellipsize layout info.
   relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = ellipsizeInfo;
   relayoutData.mTextLayoutInfo = TextLayoutInfo();
   relayoutData.mCharacterLogicalToVisualMap.clear();
   relayoutData.mCharacterVisualToLogicalMap.clear();
 
   // Sets the ellipsize layout info.
   relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = ellipsizeInfo;
+  relayoutData.mTextLayoutInfo.mEllipsisText = ellipsisText;
+  relayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsisTextStyles;
 
   // Split the whole text in paragraphs.
 
   // Split the whole text in paragraphs.
-  std::vector<MarkupProcessor::StyledTextArray> paragraphs;
+  // It returns a vector of Text with all the paragraphs.
+  // and for each paragraph a vector of styles per character. TODO: don't create a style per character.
+  std::vector<Text> paragraphs;
+  std::vector< Vector<TextStyle*> > styles;
   TextProcessor::SplitInParagraphs( text,
   TextProcessor::SplitInParagraphs( text,
-                                    paragraphs );
+                                    paragraphs,
+                                    styles );
+
+  // Reserve space for the current number of paragraphs.
+  relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.resize( paragraphs.size(), ParagraphLayoutInfo() );
 
   // Traverse all paragraphs
 
   // Traverse all paragraphs
-  for( std::vector<MarkupProcessor::StyledTextArray>::const_iterator paragraphIt = paragraphs.begin(), paragraphEndIt = paragraphs.end(); paragraphIt != paragraphEndIt; ++paragraphIt )
+  std::size_t paragraphIndex = 0u;
+  std::vector<Text>::iterator paragraphIt, paragraphEndIt;
+  std::vector< Vector<TextStyle*> >::const_iterator styleIt, styleEndIt;
+  for( paragraphIt = paragraphs.begin(), paragraphEndIt = paragraphs.end(),
+         styleIt = styles.begin(), styleEndIt = styles.end();
+       ( paragraphIt != paragraphEndIt ) && ( styleIt != styleEndIt );
+       ++paragraphIndex,
+         ++paragraphIt,
+         ++styleIt )
   {
   {
-    const MarkupProcessor::StyledTextArray& paragraph( *paragraphIt );
+    // Gets the paragraph and the styles for each character.
+    Text& paragraph( *paragraphIt );
+    const Vector<TextStyle*>& textStyles( *styleIt );
+
+    // Retrieve the data structure for the current paragraph.
+    ParagraphLayoutInfo& paragraphLayoutInfo = *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndex );
 
 
-    // Data structures for the new paragraph
-    ParagraphLayoutInfo paragraphLayoutInfo;
+    // Sets text and styles.
+    paragraphLayoutInfo.mText = paragraph;
+    paragraphLayoutInfo.mTextStyles = textStyles;
 
 
-    // Fills the paragraph data structures with the layout info.
-    CreateParagraphInfo( paragraph,
-                         relayoutData,
-                         paragraphLayoutInfo );
+    // Fills the paragraph data structure with the layout info.
 
 
-    if( 0u < paragraphLayoutInfo.mNumberOfCharacters )
+    if( !paragraph.IsEmpty() )
     {
     {
+      CreateParagraphInfo( relayoutData,
+                           paragraphLayoutInfo );
+
       // do not add the line offset if the paragraph has no characters.
       paragraphLayoutInfo.mSize.height += layoutParameters.mLineHeightOffset;
       paragraphLayoutInfo.mLineHeightOffset = layoutParameters.mLineHeightOffset;
     }
     else
     {
       // do not add the line offset if the paragraph has no characters.
       paragraphLayoutInfo.mSize.height += layoutParameters.mLineHeightOffset;
       paragraphLayoutInfo.mLineHeightOffset = layoutParameters.mLineHeightOffset;
     }
     else
     {
-      // line height needs to be added for the last paragraph.
+      // This paragraph has no text. i.e. the previous paragraph ends with '\n'.
+      // Even though, line height needs to be set in order to align the whole text correctly.
 
       float lineHeight = 0.f;
       // Get the last character of the last paragraph.
 
       float lineHeight = 0.f;
       // Get the last character of the last paragraph.
-      if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() )
+      if( 0u < paragraphIndex )
       {
       {
-        const ParagraphLayoutInfo& paragraphInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) );
+        const ParagraphLayoutInfo& paragraphInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + ( paragraphIndex - 1u ) ) );
 
         const CharacterLayoutInfo characterInfo = GetLastCharacterLayoutInfo( paragraphInfo );
 
 
         const CharacterLayoutInfo characterInfo = GetLastCharacterLayoutInfo( paragraphInfo );
 
@@ -220,16 +288,21 @@ void CreateTextInfo( const MarkupProcessor::StyledTextArray& text,
       paragraphLayoutInfo.mSize.height = lineHeight;
     }
 
       paragraphLayoutInfo.mSize.height = lineHeight;
     }
 
+    // Fills the conversion tables used to get the logical or visual position of a character is case there is right to left text.
+    // If there is right to left text, it needs to be updated every time the text is relaid-out.
+    for( std::size_t index = 0u; index < paragraphLayoutInfo.mNumberOfCharacters; ++index )
+    {
+      relayoutData.mCharacterLogicalToVisualMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index );
+      relayoutData.mCharacterVisualToLogicalMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index );
+    }
+
     // Update layout info for the whole text.
     UpdateSize( relayoutData.mTextLayoutInfo.mWholeTextSize, paragraphLayoutInfo.mSize, GrowHeight );
     relayoutData.mTextLayoutInfo.mNumberOfCharacters += paragraphLayoutInfo.mNumberOfCharacters;
     // Update layout info for the whole text.
     UpdateSize( relayoutData.mTextLayoutInfo.mWholeTextSize, paragraphLayoutInfo.mSize, GrowHeight );
     relayoutData.mTextLayoutInfo.mNumberOfCharacters += paragraphLayoutInfo.mNumberOfCharacters;
-
-    // Add the paragraph to the current text.
-    relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.push_back( paragraphLayoutInfo );
   } // end of paragraphs
 }
 
   } // end of paragraphs
 }
 
-void UpdateTextInfo( const std::size_t position,
+void UpdateTextInfo( std::size_t position,
                      const MarkupProcessor::StyledTextArray& text,
                      const TextView::LayoutParameters& layoutParameters,
                      TextView::RelayoutData& relayoutData )
                      const MarkupProcessor::StyledTextArray& text,
                      const TextView::LayoutParameters& layoutParameters,
                      TextView::RelayoutData& relayoutData )
@@ -242,7 +315,7 @@ void UpdateTextInfo( const std::size_t position,
   // * Merge the last paragraph of the new text to the last part or the split paragraph.
   // * Add paragraphs between first and last of the new text.
   // * Merge the first part of the split paragraph with the first paragraph of the new text.
   // * Merge the last paragraph of the new text to the last part or the split paragraph.
   // * Add paragraphs between first and last of the new text.
   // * Merge the first part of the split paragraph with the first paragraph of the new text.
-  // * Update layout info and create new text actors if needed.
+  // * Update the layout info for the whole text.
 
   // Early returns:
 
 
   // Early returns:
 
@@ -269,6 +342,15 @@ void UpdateTextInfo( const std::size_t position,
     DALI_ASSERT_ALWAYS( !"TextViewProcessor::UpdateTextInfo (insert). Trying to insert text out of bounds." );
   }
 
     DALI_ASSERT_ALWAYS( !"TextViewProcessor::UpdateTextInfo (insert). Trying to insert text out of bounds." );
   }
 
+
+  // TODO
+  // If in the insertion is involved right to left text,
+  // check the neighbour characters is needed.
+  //   i.e. Arabic characters may have four different glyphs (isolated, end, middle, begin).
+  //        So check the neighbours on each side is needed in order to render
+  //        the correct ligatures.
+
+
   TextView::RelayoutData relayoutDataForNewText;
 
   // Creates layout info for the given text.
   TextView::RelayoutData relayoutDataForNewText;
 
   // Creates layout info for the given text.
@@ -277,8 +359,8 @@ void UpdateTextInfo( const std::size_t position,
                   layoutParameters,
                   relayoutDataForNewText );
 
                   layoutParameters,
                   relayoutDataForNewText );
 
-  // Update logical-to-visual and visual-to-logical tables.
-  // TODO: check that for mixed RTL/LTR text.
+  // Fills the conversion tables used to get the logical or visual position of a character is case there is right to left text.
+  // If there is right to left text, it needs to be updated every time the text is relaid-out.
   std::size_t index = 0u;
   for( std::size_t i = 0u; i < relayoutDataForNewText.mTextLayoutInfo.mNumberOfCharacters; ++i )
   {
   std::size_t index = 0u;
   for( std::size_t i = 0u; i < relayoutDataForNewText.mTextLayoutInfo.mNumberOfCharacters; ++i )
   {
@@ -335,6 +417,13 @@ void UpdateTextInfo( const std::size_t position,
 
         const WordLayoutInfo& wordLayoutInfo( *( paragraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) );
         textInfoIndices.mCharacterIndex = wordLayoutInfo.mCharactersLayoutInfo.size();
 
         const WordLayoutInfo& wordLayoutInfo( *( paragraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) );
         textInfoIndices.mCharacterIndex = wordLayoutInfo.mCharactersLayoutInfo.size();
+
+        // Sets the character index within the paragraph.
+        textInfoIndices.mCharacterParagraphIndex = 0u;
+        for( WordLayoutInfoContainer::const_iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); it != endIt; ++it )
+        {
+          textInfoIndices.mCharacterParagraphIndex += wordLayoutInfo.mCharactersLayoutInfo.size();
+        }
       }
     }
   }
       }
     }
   }
@@ -382,8 +471,8 @@ void UpdateTextInfo( const std::size_t position,
   UpdateLayoutInfo( relayoutData.mTextLayoutInfo );
 }
 
   UpdateLayoutInfo( relayoutData.mTextLayoutInfo );
 }
 
-void UpdateTextInfo( const std::size_t position,
-                     const std::size_t numberOfCharacters,
+void UpdateTextInfo( std::size_t position,
+                     std::size_t numberOfCharacters,
                      const TextView::LayoutParameters& layoutParameters,
                      TextView::RelayoutData& relayoutData,
                      const TextOperationOnRemove clearText )
                      const TextView::LayoutParameters& layoutParameters,
                      TextView::RelayoutData& relayoutData,
                      const TextOperationOnRemove clearText )
@@ -414,7 +503,8 @@ void UpdateTextInfo( const std::size_t position,
   // Asserts if trying to delete text out of bounds.
   DALI_ASSERT_ALWAYS( position + numberOfCharacters <= relayoutData.mTextLayoutInfo.mNumberOfCharacters && "TextViewProcessor::UpdateTextInfo. ERROR: trying to delete characters out of boundary" );
 
   // Asserts if trying to delete text out of bounds.
   DALI_ASSERT_ALWAYS( position + numberOfCharacters <= relayoutData.mTextLayoutInfo.mNumberOfCharacters && "TextViewProcessor::UpdateTextInfo. ERROR: trying to delete characters out of boundary" );
 
-  // Remove characters from character to visual map and vs //TODO: check this for RTL text!!
+  // Remove characters from character to visual map and vs.
+  // If there is right to left text, it needs to be updated every time the text is relaid-out.
   relayoutData.mCharacterLogicalToVisualMap.erase( relayoutData.mCharacterLogicalToVisualMap.end() - numberOfCharacters, relayoutData.mCharacterLogicalToVisualMap.end() );
   relayoutData.mCharacterVisualToLogicalMap.erase( relayoutData.mCharacterVisualToLogicalMap.end() - numberOfCharacters, relayoutData.mCharacterVisualToLogicalMap.end() );
 
   relayoutData.mCharacterLogicalToVisualMap.erase( relayoutData.mCharacterLogicalToVisualMap.end() - numberOfCharacters, relayoutData.mCharacterLogicalToVisualMap.end() );
   relayoutData.mCharacterVisualToLogicalMap.erase( relayoutData.mCharacterVisualToLogicalMap.end() - numberOfCharacters, relayoutData.mCharacterVisualToLogicalMap.end() );
 
@@ -521,6 +611,19 @@ void UpdateTextInfo( const std::size_t position,
       // As paragraphIndexBegin has been increased just to not to remove the paragraph, decrease now is needed to access it.
       ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex - 1u ) );
 
       // As paragraphIndexBegin has been increased just to not to remove the paragraph, decrease now is needed to access it.
       ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex - 1u ) );
 
+      // Remove the characters from the text and the styles.
+      paragraphLayout.mText.Remove( textInfoIndicesBegin.mCharacterParagraphIndex, paragraphLayout.mNumberOfCharacters - textInfoIndicesBegin.mCharacterParagraphIndex );
+
+      for( Vector<TextStyle*>::Iterator it = paragraphLayout.mTextStyles.Begin() + textInfoIndicesBegin.mCharacterParagraphIndex,
+             endIt = paragraphLayout.mTextStyles.End();
+           it != endIt;
+           ++it )
+      {
+        delete *it;
+      }
+      paragraphLayout.mTextStyles.Erase( paragraphLayout.mTextStyles.Begin() + textInfoIndicesBegin.mCharacterParagraphIndex,
+                                         paragraphLayout.mTextStyles.End() );
+
       if( ( textInfoIndicesBegin.mWordIndex + 1u < paragraphLayout.mWordsLayoutInfo.size() ) || ( 0u == textInfoIndicesBegin.mCharacterIndex ) )
       {
         // Remove extra words within current paragraph. (and current word if whole characters are removed)
       if( ( textInfoIndicesBegin.mWordIndex + 1u < paragraphLayout.mWordsLayoutInfo.size() ) || ( 0u == textInfoIndicesBegin.mCharacterIndex ) )
       {
         // Remove extra words within current paragraph. (and current word if whole characters are removed)
@@ -577,6 +680,21 @@ void UpdateTextInfo( const std::size_t position,
       // Get the last paragraph.
       ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndex ) );
 
       // Get the last paragraph.
       ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndex ) );
 
+      // Remove the characters from the text and the styles.
+      const std::size_t lastCharacterIndex = textInfoIndicesEnd.mCharacterParagraphIndex + 1u;
+
+      paragraphLayout.mText.Remove( 0u, lastCharacterIndex );
+
+      for( Vector<TextStyle*>::Iterator it = paragraphLayout.mTextStyles.Begin(),
+             endIt = paragraphLayout.mTextStyles.Begin() + lastCharacterIndex;
+           it != endIt;
+           ++it )
+      {
+        delete *it;
+      }
+      paragraphLayout.mTextStyles.Erase( paragraphLayout.mTextStyles.Begin(),
+                                         paragraphLayout.mTextStyles.Begin() + lastCharacterIndex );
+
       // Check if is needed remove the whole word. (If the character index is pointing just after the end of the word)
       const WordLayoutInfo& wordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex ) );
       bool removeWholeWord = wordLayout.mCharactersLayoutInfo.size() == textInfoIndicesEnd.mCharacterIndex + 1u;
       // Check if is needed remove the whole word. (If the character index is pointing just after the end of the word)
       const WordLayoutInfo& wordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex ) );
       bool removeWholeWord = wordLayout.mCharactersLayoutInfo.size() == textInfoIndicesEnd.mCharacterIndex + 1u;
@@ -634,6 +752,22 @@ void UpdateTextInfo( const std::size_t position,
     // Paragraph which contains the characters to be deleted.
     ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex ) );
 
     // Paragraph which contains the characters to be deleted.
     ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex ) );
 
+    // Remove the characters from the text and the styles.
+    const std::size_t firstCharacterIndex = textInfoIndicesBegin.mCharacterParagraphIndex;
+    const std::size_t lastCharacterIndex = textInfoIndicesEnd.mCharacterParagraphIndex + 1u;
+
+    paragraphLayout.mText.Remove( firstCharacterIndex, lastCharacterIndex - firstCharacterIndex );
+
+    for( Vector<TextStyle*>::Iterator it = paragraphLayout.mTextStyles.Begin() + firstCharacterIndex,
+           endIt = paragraphLayout.mTextStyles.Begin() + lastCharacterIndex;
+         it != endIt;
+         ++it )
+    {
+      delete *it;
+    }
+    paragraphLayout.mTextStyles.Erase( paragraphLayout.mTextStyles.Begin() + firstCharacterIndex,
+                                       paragraphLayout.mTextStyles.Begin() + lastCharacterIndex );
+
     // Remove the characters from the paragraph layout info. It returns whether the current paragraph can be merged with the next one.
     RemoveCharactersFromParagraphInfo( relayoutData,
                                        numberOfCharacters,
     // Remove the characters from the paragraph layout info. It returns whether the current paragraph can be merged with the next one.
     RemoveCharactersFromParagraphInfo( relayoutData,
                                        numberOfCharacters,
@@ -730,8 +864,8 @@ void UpdateTextInfo( const std::size_t position,
   relayoutData.mTextActorCache.InsertTextActors( removedTextActorsFromBegin );
 }
 
   relayoutData.mTextActorCache.InsertTextActors( removedTextActorsFromBegin );
 }
 
-void UpdateTextInfo( const std::size_t position,
-                     const std::size_t numberOfCharacters,
+void UpdateTextInfo( std::size_t position,
+                     std::size_t numberOfCharacters,
                      const MarkupProcessor::StyledTextArray& text,
                      const TextView::LayoutParameters& layoutParameters,
                      TextView::RelayoutData& relayoutData )
                      const MarkupProcessor::StyledTextArray& text,
                      const TextView::LayoutParameters& layoutParameters,
                      TextView::RelayoutData& relayoutData )
@@ -788,6 +922,17 @@ void UpdateTextInfo( const TextStyle& style,
   {
     ParagraphLayoutInfo& paragraph( *paragraphIt );
 
   {
     ParagraphLayoutInfo& paragraph( *paragraphIt );
 
+    std::size_t index = 0u;
+    for( Vector<TextStyle*>::Iterator it = paragraph.mTextStyles.Begin(), endIt = paragraph.mTextStyles.End(); it != endIt; ++it )
+    {
+      (*it)->Copy( style, mask );
+
+      // Checks if the font family supports all glyphs. If not, chooses a most suitable one.
+      ChooseFontFamilyName( paragraph.mText[index], *(*it) );
+
+      ++index;
+    }
+
     for( WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
          wordIt != wordEndIt;
          ++wordIt )
     for( WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
          wordIt != wordEndIt;
          ++wordIt )
@@ -800,11 +945,6 @@ void UpdateTextInfo( const TextStyle& style,
       {
         CharacterLayoutInfo& characterLayout( *characterIt );
 
       {
         CharacterLayoutInfo& characterLayout( *characterIt );
 
-        characterLayout.mStyledText.mStyle.Copy( style, mask );
-
-        // Checks if the font family supports all glyphs. If not, chooses a most suitable one.
-        ChooseFontFamilyName( characterLayout.mStyledText );
-
         // Mark the character to be set the new style into the text-actor.
         characterLayout.mSetStyle = true;
       } // end characters
         // Mark the character to be set the new style into the text-actor.
         characterLayout.mSetStyle = true;
       } // end characters
index b1426c9..800a96b 100644 (file)
@@ -39,33 +39,6 @@ namespace
 
 const std::string EMOJI_FONT_NAME( "SamsungEmoji" ); // Emoticons font family name.
 
 
 const std::string EMOJI_FONT_NAME( "SamsungEmoji" ); // Emoticons font family name.
 
-/**
- * Updates the word size and ascender.
- *
- * It's called after deleting some characters.
- *
- * @param[in] wordLayout The word layout info.
- */
-void UpdateLayoutInfo( WordLayoutInfo& wordLayout )
-{
-  // Initialize layout info for the whole word.
-  wordLayout.mSize = Size::ZERO;
-  wordLayout.mAscender = 0.f;
-
-  // Traverse the character layout info to update the word layout.
-  for( CharacterLayoutInfoContainer::iterator layoutIt = wordLayout.mCharactersLayoutInfo.begin(), layoutEndIt = wordLayout.mCharactersLayoutInfo.end();
-       layoutIt != layoutEndIt;
-       ++layoutIt )
-  {
-    // Layout info for the current character.
-    CharacterLayoutInfo& layoutInfo( *layoutIt );
-
-    // Update layout info for the current word.
-    UpdateSize( wordLayout.mSize, layoutInfo.mSize );
-    wordLayout.mAscender = std::max( wordLayout.mAscender, layoutInfo.mAscender );
-  }
-}
-
 } // namespace
 
 /////////////////////
 } // namespace
 
 /////////////////////
@@ -76,6 +49,7 @@ WordLayoutInfo::WordLayoutInfo()
 : mSize(),
   mAscender( 0.f ),
   mType( NoSeparator ),
 : mSize(),
   mAscender( 0.f ),
   mType( NoSeparator ),
+  mFirstCharacter( 0u ),
   mCharactersLayoutInfo()
 {
 }
   mCharactersLayoutInfo()
 {
 }
@@ -88,6 +62,7 @@ WordLayoutInfo::WordLayoutInfo( const WordLayoutInfo& word )
 : mSize( word.mSize ),
   mAscender( word.mAscender ),
   mType( word.mType ),
 : mSize( word.mSize ),
   mAscender( word.mAscender ),
   mType( word.mType ),
+  mFirstCharacter( word.mFirstCharacter ),
   mCharactersLayoutInfo( word.mCharactersLayoutInfo )
 {
 }
   mCharactersLayoutInfo( word.mCharactersLayoutInfo )
 {
 }
@@ -97,87 +72,103 @@ WordLayoutInfo& WordLayoutInfo::operator=( const WordLayoutInfo& word )
   mSize = word.mSize;
   mAscender = word.mAscender;
   mType = word.mType;
   mSize = word.mSize;
   mAscender = word.mAscender;
   mType = word.mType;
+  mFirstCharacter = word.mFirstCharacter;
   mCharactersLayoutInfo = word.mCharactersLayoutInfo;
 
   return *this;
 }
 
   mCharactersLayoutInfo = word.mCharactersLayoutInfo;
 
   return *this;
 }
 
-void CreateWordTextInfo( const MarkupProcessor::StyledTextArray& word,
+void CreateWordTextInfo( const Text& paragraph,
+                         Vector<TextStyle*>& textStyles,
                          WordLayoutInfo& wordLayoutInfo )
 {
   DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "-->TextViewProcessor::CreateWordTextInfo\n" );
   // Split in characters.
                          WordLayoutInfo& wordLayoutInfo )
 {
   DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "-->TextViewProcessor::CreateWordTextInfo\n" );
   // Split in characters.
-  for( MarkupProcessor::StyledTextArray::const_iterator charIt = word.begin(), charEndIt = word.end(); charIt != charEndIt; ++charIt )
+  std::size_t characterIndex = wordLayoutInfo.mFirstCharacter;
+  for( CharacterLayoutInfoContainer::iterator it = wordLayoutInfo.mCharactersLayoutInfo.begin(),
+         endIt =  wordLayoutInfo.mCharactersLayoutInfo.end();
+       it != endIt;
+       ++it, ++characterIndex )
   {
   {
-    const MarkupProcessor::StyledText& styledText( *charIt );
+    // Gets a reference of the character's layout info.
+    CharacterLayoutInfo& characterLayoutInfo( *it );
+
+    // Gets the character and the style for that character from the paragraph.
+    Character character = paragraph[characterIndex];
+    TextStyle* textStyle = *( textStyles.Begin() + characterIndex );
 
 
-    const std::size_t length = styledText.mText.GetLength();
+    // Checks whether the character is an emoticon.
+    characterLayoutInfo.mIsColorGlyph = GlyphImage::IsColorGlyph( character );
+    DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "  Is color glyph: %s\n", ( characterLayoutInfo.mIsColorGlyph ? "True" : "False" ) );
 
 
-    // It could be a group of characters.
-    for( std::size_t index = 0u; index < length; ++index )
+    if( characterLayoutInfo.mIsColorGlyph )
     {
     {
-      MarkupProcessor::StyledText styledCharacter;
-      styledCharacter.mStyle = styledText.mStyle;
-      Character character = styledText.mText[index];
-      styledCharacter.mText.Append( character );
+      // If the character is an emoticon a predefined font is set.
+      textStyle->SetFontName( EMOJI_FONT_NAME );
+    }
+    else
+    {
+      // Checks if the font family and the font style set in the text style supports the character.
+      // If not, it chooses the right font for the given character and style.
+      ChooseFontFamilyName( character, *textStyle );
+    }
 
 
-      // Create layout character info.
-      CharacterLayoutInfo characterLayoutInfo;
+    // Gets the metrics of the font.
+    const Font font = Font::New( FontParameters( textStyle->GetFontName(), textStyle->GetFontStyle(), textStyle->GetFontPointSize() ) );
+    const Font::Metrics metrics = font.GetMetrics( character );
+    const float ascender = font.GetAscender();
 
 
-      characterLayoutInfo.mIsColorGlyph = GlyphImage::IsColorGlyph( character );
-      DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "  Is color glyph: %s\n", ( characterLayoutInfo.mIsColorGlyph ? "True" : "False" ) );
+    // Fill Natural size info for current character.
 
 
-      if( characterLayoutInfo.mIsColorGlyph )
-      {
-        styledCharacter.mStyle.SetFontName( EMOJI_FONT_NAME );
-      }
-      else
-      {
-        //Choose the right font for the given character and style.
-        ChooseFontFamilyName( styledCharacter );
-      }
+    // The font line's height is used as character's height.
+    characterLayoutInfo.mSize.height = font.GetLineHeight();
 
 
-      // Gets the metrics of the font.
-      const Font font = Font::New( FontParameters( styledCharacter.mStyle.GetFontName(), styledCharacter.mStyle.GetFontStyle(), styledCharacter.mStyle.GetFontPointSize() ) );
-      const Font::Metrics metrics = font.GetMetrics( character );
-      const float ascender = font.GetAscender();
+    // The character's advance is used as charcter's width.
+    characterLayoutInfo.mSize.width = metrics.GetAdvance();
 
 
-      // The font line's height is used as character's height.
-      characterLayoutInfo.mSize.height = font.GetLineHeight();
+    // The ascender and bearing are used to position correctly glyphs of different font sizes.
+    characterLayoutInfo.mAscender = ascender;
+    characterLayoutInfo.mBearing = metrics.GetBearing();
 
 
-      // The character's advance is used as charcter's width.
-      characterLayoutInfo.mSize.width = metrics.GetAdvance();
+    if( character.IsNewLine() && !characterLayoutInfo.mIsColorGlyph )
+    {
+      // A new paragraph character '\n'  doesn't have any width.
+      characterLayoutInfo.mSize.width = 0.f;
+    }
 
 
-      // The ascender and bearing are used to position correctly glyphs of different font sizes.
-      characterLayoutInfo.mAscender = ascender;
-      characterLayoutInfo.mBearing = metrics.GetBearing();
+    // Set's the underline thickness and position.
+    // Both thickness and position includes the vertical pad adjust used in effects like glow or shadow.
+    if( textStyle->IsUnderlineEnabled() )
+    {
+      characterLayoutInfo.mUnderlineThickness = font.GetUnderlineThickness();
+      characterLayoutInfo.mUnderlinePosition = font.GetUnderlinePosition();
+    }
 
 
-      if( character.IsNewLine() && !characterLayoutInfo.mIsColorGlyph )
-      {
-        // A new paragraph character doesn't have any width.
-        characterLayoutInfo.mSize.width = 0.f;
-      }
+    // Updates the word size and ascender.
+    UpdateSize( wordLayoutInfo.mSize, characterLayoutInfo.mSize );
+    wordLayoutInfo.mAscender = std::max( wordLayoutInfo.mAscender, characterLayoutInfo.mAscender );
+  } // end of characters in the word.
+  DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "<--TextViewProcessor::CreateWordTextInfo\n" );
+}
 
 
-      // Set's the underline thickness and position.
-      // Both thickness and position includes the vertical pad adjust used in effects like glow or shadow.
-      if( styledCharacter.mStyle.IsUnderlineEnabled() )
-      {
-        characterLayoutInfo.mUnderlineThickness = font.GetUnderlineThickness();
-        characterLayoutInfo.mUnderlinePosition = font.GetUnderlinePosition();
-      }
+void UpdateLayoutInfo( WordLayoutInfo& wordLayout )
+{
+  // Initialize layout info for the whole word.
+  wordLayout.mSize = Size::ZERO;
+  wordLayout.mAscender = 0.f;
 
 
-      // stores the styled text.
-      characterLayoutInfo.mStyledText.mText = styledCharacter.mText;
-      characterLayoutInfo.mStyledText.mStyle = styledCharacter.mStyle;
+  // Traverse the character layout info to update the word layout.
+  for( CharacterLayoutInfoContainer::iterator layoutIt = wordLayout.mCharactersLayoutInfo.begin(), layoutEndIt = wordLayout.mCharactersLayoutInfo.end();
+       layoutIt != layoutEndIt;
+       ++layoutIt )
+  {
+    // Layout info for the current character.
+    CharacterLayoutInfo& layoutInfo( *layoutIt );
 
 
-      // Add character layout info to the word layout info and update it.
-      wordLayoutInfo.mCharactersLayoutInfo.push_back( characterLayoutInfo );
-      UpdateSize( wordLayoutInfo.mSize, characterLayoutInfo.mSize );
-      wordLayoutInfo.mAscender = std::max( wordLayoutInfo.mAscender, characterLayoutInfo.mAscender );
-      wordLayoutInfo.mType = GetTextSeparatorType( character );
-    } // end of each character in the group of characters.
-  } // end of characters in the word.
-  DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "<--TextViewProcessor::CreateWordTextInfo\n" );
+    // Update layout info for the current word.
+    UpdateSize( wordLayout.mSize, layoutInfo.mSize );
+    wordLayout.mAscender = std::max( wordLayout.mAscender, layoutInfo.mAscender );
+  }
 }
 
 void RemoveCharactersFromWordInfo( TextView::RelayoutData& relayoutData,
 }
 
 void RemoveCharactersFromWordInfo( TextView::RelayoutData& relayoutData,
index 7b2845c..82f36f0 100644 (file)
@@ -36,13 +36,25 @@ namespace TextViewProcessor
 /**
  * Creates a data structure with info to layout the word, and data structures with useful info to modify the layout data structure if characters are added or removed.
  *
 /**
  * Creates a data structure with info to layout the word, and data structures with useful info to modify the layout data structure if characters are added or removed.
  *
- * @param[in] word The styled word.
+ * @param[in] paragraphText The paragraph's text.
+ * @param[in] textStyles The styles for each character of the paragraph.
  * @param[out] wordLayoutInfo Layout info for all characters of the word.
  */
  * @param[out] wordLayoutInfo Layout info for all characters of the word.
  */
-void CreateWordTextInfo( const MarkupProcessor::StyledTextArray& word,
+void CreateWordTextInfo( const Text& paragraphText,
+                         Vector<TextStyle*>& textStyles,
                          WordLayoutInfo& wordLayoutInfo );
 
 /**
                          WordLayoutInfo& wordLayoutInfo );
 
 /**
+ * Updates the word size and ascender.
+ *
+ * It's called after deleting some characters, split a word in two,
+ * or when a new word is created when right to left text is reordered.
+ *
+ * @param[in] wordLayout The word layout info.
+ */
+void UpdateLayoutInfo( WordLayoutInfo& wordLayout );
+
+/**
  * Removes a given number of characters from the given word.
  *
  * It calls the RemoveCharactersFromWord() function to remove characters from the word.
  * Removes a given number of characters from the given word.
  *
  * It calls the RemoveCharactersFromWord() function to remove characters from the word.
index 4fa6bf8..f2331cc 100644 (file)
@@ -47,6 +47,7 @@ toolkit_base_src_files = \
    $(toolkit_base_src_dir)/controls/text-view/split-by-char-policies.cpp   \
    $(toolkit_base_src_dir)/controls/text-view/text-actor-cache.cpp   \
    $(toolkit_base_src_dir)/controls/text-view/text-processor.cpp   \
    $(toolkit_base_src_dir)/controls/text-view/split-by-char-policies.cpp   \
    $(toolkit_base_src_dir)/controls/text-view/text-actor-cache.cpp   \
    $(toolkit_base_src_dir)/controls/text-view/text-processor.cpp   \
+   $(toolkit_base_src_dir)/controls/text-view/text-processor-bidirectional-info.cpp  \
    $(toolkit_base_src_dir)/controls/text-view/text-view-impl.cpp   \
    $(toolkit_base_src_dir)/controls/text-view/text-view-character-processor.cpp  \
    $(toolkit_base_src_dir)/controls/text-view/text-view-paragraph-processor.cpp  \
    $(toolkit_base_src_dir)/controls/text-view/text-view-impl.cpp   \
    $(toolkit_base_src_dir)/controls/text-view/text-view-character-processor.cpp  \
    $(toolkit_base_src_dir)/controls/text-view/text-view-paragraph-processor.cpp  \