TextView - Right to Left implementation.
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / text-view / split-by-new-line-char-policies.cpp
index b1b55de..f74966d 100644 (file)
@@ -1,30 +1,27 @@
-//
-// Copyright (c) 2014 Samsung Electronics Co., Ltd.
-//
-// Licensed under the Flora License, Version 1.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://floralicense.org/license/
-//
-// 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.
-//
+/*
+ * 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 "split-by-new-line-char-policies.h"
-
-// EXTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h>
 
 // INTERNAL INCLUDES
-
-#include "relayout-utilities.h"
-#include "text-view-processor.h"
 #include <dali/integration-api/debug.h>
+#include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
+#include <dali-toolkit/internal/controls/text-view/text-view-processor.h>
 
 namespace Dali
 {
@@ -53,7 +50,7 @@ Vector3 SplitPosition( const TextViewRelayout::RelayoutParameters& relayoutParam
       ( wordOffset + relayoutParameters.mCharacterSize.width > relayoutData.mTextViewSize.width ) )
   {
     if( !relayoutParameters.mIsNewLine &&
-        ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewLineCharacter ) )
+        ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewParagraphCharacter ) )
     {
       // Current character is a white space. Don't want to move a white space to the next line.
       // These white spaces are placed just in the edge.
@@ -61,31 +58,23 @@ Vector3 SplitPosition( const TextViewRelayout::RelayoutParameters& relayoutParam
     }
     else
     {
-      const TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin() + relayoutParameters.mIndices.mLineIndex ) );
+      const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + relayoutParameters.mIndices.mParagraphIndex ) );
 
-      TextViewRelayout::SubLineLayoutInfo subLineInfo;
+      TextViewRelayout::LineLayoutInfo subLineInfo;
       subLineInfo.mLineLength = 0.f;
       subLineInfo.mMaxCharHeight = 0.f;
       subLineInfo.mMaxAscender = 0.f;
-      TextViewRelayout::CalculateSubLineLayout( relayoutData.mTextViewSize.width,
-                                                relayoutParameters.mIndices,
-                                                lineLayoutInfo,
-                                                TextViewRelayout::WrapByLineAndSplit,
-                                                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 );
+      TextViewRelayout::CalculateLineLayout( relayoutData.mTextViewSize.width,
+                                             relayoutParameters.mIndices,
+                                             paragraphLayoutInfo,
+                                             TextViewRelayout::WrapByParagraphCharacterAndSplit,
+                                             1.f, // Shrink factor
+                                             subLineInfo );
 
       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 line.
-      lineInfo.mAscender = subLineInfo.mMaxAscender;                                // Ascender of this piece of line.
+      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 );
 
       return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f );
@@ -132,144 +121,118 @@ void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameter
   }
 
   relayoutParameters.mIsFirstCharacter = true;
-  relayoutParameters.mIndices.mLineIndex = 0;
+  relayoutParameters.mIndices.mParagraphIndex = 0u;
   relayoutParameters.mPositionOffset = Vector3::ZERO;
-  relayoutParameters.mCharacterGlobalIndex = 0;
+  relayoutParameters.mCharacterGlobalIndex = 0u;
 
-  for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
-       endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
-       lineLayoutIt != endLineLayoutIt;
-       ++lineLayoutIt, ++relayoutParameters.mIndices.mLineIndex )
+  for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(),
+       endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end();
+       paragraphLayoutIt != endParagraphLayoutIt;
+       ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex )
   {
-    TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
+    TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
 
-    relayoutParameters.mLineSize = lineLayoutInfo.mSize * relayoutData.mShrinkFactor;
+    relayoutParameters.mParagraphSize = paragraphLayoutInfo.mSize * relayoutData.mShrinkFactor;
 
     relayoutParameters.mIsNewLine = true;
-    relayoutParameters.mIndices.mGroupIndex = 0;
+    relayoutParameters.mIndices.mWordIndex = 0u;
 
-    for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(),
-         endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end();
-         groupLayoutIt != endGroupLayoutIt;
-         ++groupLayoutIt, ++relayoutParameters.mIndices.mGroupIndex )
+    for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
+           endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
+         wordLayoutIt != endWordLayoutIt;
+         ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
     {
-      TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *groupLayoutIt );
+      TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
+      relayoutParameters.mIsWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType;
+      relayoutParameters.mIsNewParagraphCharacter = TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType;
 
-      relayoutParameters.mIndices.mWordIndex = 0;
+      relayoutParameters.mIsFirstCharacterOfWord = true;
+      relayoutParameters.mWordSize = wordLayoutInfo.mSize;
+      relayoutParameters.mIndices.mCharacterIndex = 0u;
 
-      for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.begin(),
-           endWordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.end();
-           wordLayoutIt != endWordLayoutIt;
-           ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
+      for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
+             endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
+           characterLayoutIt != endCharacterLayoutIt;
+           ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex )
       {
-        TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
-        relayoutParameters.mIsWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType;
-        relayoutParameters.mIsNewLineCharacter = TextViewProcessor::LineSeparator == wordLayoutInfo.mType;
+        TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
+        relayoutParameters.mCharacterSize = characterLayoutInfo.mSize;
 
-        relayoutParameters.mIsFirstCharacterOfWord = true;
-        relayoutParameters.mWordSize = wordLayoutInfo.mSize;
-        relayoutParameters.mIndices.mCharacterIndex = 0;
+        relayoutParameters.mCharacterSize = characterLayoutInfo.mSize;
 
-        if( relayoutParameters.mIsNewLine )
+        switch( layoutParameters.mExceedPolicy )
         {
-          // Stores some info to calculate the line justification in a post-process.
-          const bool isSplitOriginal = layoutParameters.mExceedPolicy == TextView::SplitOriginal;
-
-          if( !isSplitOriginal )
+          case TextView::OriginalShrink:
+          case TextView::SplitShrink:
+          case TextView::ShrinkFade: // Fall Through
           {
-            TextView::LineJustificationInfo justificationInfo;
-
-            justificationInfo.mIndices = relayoutParameters.mIndices;
-            justificationInfo.mLineLength = relayoutParameters.mLineSize.width;
-
-            relayoutData.mLineJustificationInfo.push_back( justificationInfo );
+            DALI_LOG_WARNING( "SplitByNewLineChar::CalculateSizeAndPosition() policy not implemented.\n" );
+            break;
           }
-        }
-
-        for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
-             endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
-             characterLayoutIt != endCharacterLayoutIt;
-             ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex )
-        {
-          TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
-          relayoutParameters.mCharacterSize = characterLayoutInfo.mSize;
-
-          relayoutParameters.mCharacterSize = characterLayoutInfo.mSize;
-
-          switch( layoutParameters.mExceedPolicy )
+          case TextView::Original: // Fall Through
+          case TextView::ShrinkOriginal: // Fall Through
+          case TextView::Shrink: // Fall Through
+          case TextView::OriginalFade: // Fall Through
+          case TextView::FadeOriginal: // Fall Through
+          case TextView::Fade: // Fall Through
+          case TextView::EllipsizeEndOriginal: // Fall Through
+          case TextView::EllipsizeEnd: // Fall Through
           {
-            case TextView::OriginalShrink:
-            case TextView::SplitShrink:
-            case TextView::ShrinkFade: // Fall Through
-            {
-              DALI_LOG_WARNING( "SplitByNewLineChar::CalculateSizeAndPosition() policy not implemented.\n" );
-              break;
-            }
-            case TextView::Original: // Fall Through
-            case TextView::ShrinkOriginal: // Fall Through
-            case TextView::Shrink: // Fall Through
-            case TextView::OriginalFade: // Fall Through
-            case TextView::FadeOriginal: // Fall Through
-            case TextView::Fade: // Fall Through
-            case TextView::EllipsizeEndOriginal: // Fall Through
-            case TextView::EllipsizeEnd: // Fall Through
+            if( relayoutParameters.mIsNewLine )
             {
-              if( relayoutParameters.mIsNewLine )
-              {
-                relayoutParameters.mPositionOffset.x = 0.f;
-                relayoutParameters.mPositionOffset.y += lineLayoutInfo.mSize.height * relayoutData.mShrinkFactor;
-              }
-
-              characterLayoutInfo.mPosition = relayoutParameters.mPositionOffset;
-
-              relayoutParameters.mPositionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor;
-
-              if( relayoutParameters.mIsNewLine ||
-                  relayoutParameters.mIsFirstCharacter )
-              {
-                Toolkit::TextView::LineLayoutInfo lineInfo;
-                lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;  // Index to the first character of the next line.
-                lineInfo.mSize = relayoutParameters.mLineSize;                              // Size of this piece of line.
-                lineInfo.mAscender = lineLayoutInfo.mAscender * relayoutData.mShrinkFactor; // Ascender of this piece of line.
-                relayoutData.mLines.push_back( lineInfo );
-              }
-              break;
+              relayoutParameters.mPositionOffset.x = 0.f;
+              relayoutParameters.mPositionOffset.y += paragraphLayoutInfo.mSize.height * relayoutData.mShrinkFactor;
             }
-            case TextView::SplitOriginal:
-            case TextView::SplitFade: // Fall Through
-            {
-              characterLayoutInfo.mPosition = SplitPosition( relayoutParameters,
-                                                             layoutParameters,
-                                                             relayoutData );
 
-              relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f );
-              break;
-            }
-            default:
+            characterLayoutInfo.mPosition = relayoutParameters.mPositionOffset;
+
+            relayoutParameters.mPositionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor;
+
+            if( relayoutParameters.mIsNewLine ||
+                relayoutParameters.mIsFirstCharacter )
             {
-              DALI_LOG_WARNING( "SplitByNewLineChar::CalculateSizeAndPosition() Layout configuration not possible.\n" );
-              break;
+              Toolkit::TextView::LineLayoutInfo lineInfo;
+              lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;       // Index to the first character of the next line.
+              lineInfo.mSize = relayoutParameters.mParagraphSize;                              // Size of this piece of paragraph.
+              lineInfo.mAscender = paragraphLayoutInfo.mAscender * relayoutData.mShrinkFactor; // Ascender of this piece of paragraph.
+              relayoutData.mLines.push_back( lineInfo );
             }
+            break;
           }
+          case TextView::SplitOriginal:
+          case TextView::SplitFade:
+          case TextView::SplitEllipsizeEnd: // Fall Through
+          {
+            characterLayoutInfo.mPosition = SplitPosition( relayoutParameters,
+                                                           layoutParameters,
+                                                           relayoutData );
 
-          // Get last line info and calculate the bearing (used to align glyphs with the baseline).
-          TextViewRelayout::CalculateBearing( characterLayoutInfo, relayoutData );
-
-          // updates min and max position to calculate the text size for split by new line char.
-          TextViewRelayout::UpdateLayoutInfoTable( minMaxXY,
-                                                   wordGroupLayoutInfo,
-                                                   wordLayoutInfo,
-                                                   characterLayoutInfo,
-                                                   relayoutParameters,
-                                                   relayoutData );
-
-          ++relayoutParameters.mCharacterGlobalIndex;
-          relayoutParameters.mIsFirstCharacter = false;
-          relayoutParameters.mIsNewLine = false;
-        } // end characters
-      } // end words
-    } // end group of words
-  } // end lines
+            relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f );
+            break;
+          }
+          default:
+          {
+            DALI_LOG_WARNING( "SplitByNewLineChar::CalculateSizeAndPosition() Layout configuration not possible.\n" );
+            break;
+          }
+        }
+
+        // Get last line info and calculate the bearing (used to align glyphs with the baseline).
+        TextViewRelayout::CalculateBearing( characterLayoutInfo, relayoutData );
+
+        // updates min and max position to calculate the text size for split by new line char.
+        TextViewRelayout::UpdateLayoutInfoTable( minMaxXY,
+                                                 wordLayoutInfo,
+                                                 characterLayoutInfo,
+                                                 relayoutParameters,
+                                                 relayoutData );
+
+        ++relayoutParameters.mCharacterGlobalIndex;
+        relayoutParameters.mIsFirstCharacter = false;
+        relayoutParameters.mIsNewLine = false;
+      } // end characters
+    } // end words
+  } // end paragraphs
 
   if( relayoutData.mCharacterLayoutInfoTable.empty() )
   {
@@ -281,14 +244,14 @@ void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameter
     relayoutData.mTextSizeForRelayoutOption.height = minMaxXY.w - minMaxXY.y;
   }
 
-  // Check if the last character is a new line character. In that case the height should be added.
-  if( !relayoutData.mTextLayoutInfo.mLinesLayoutInfo.empty() )
+  // Check if the last character is a new paragraph character. In that case the height should be added.
+  if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() )
   {
-    const TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end() - 1 ) );
+    const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) );
 
-    if( lineLayoutInfo.mWordGroupsLayoutInfo.empty() ) // if it's empty, it means the last character is a new line character.
+    if( paragraphLayoutInfo.mWordsLayoutInfo.empty() ) // if it's empty, it means the last character is a new paragraph character.
     {
-      relayoutData.mTextSizeForRelayoutOption.height += lineLayoutInfo.mSize.height * relayoutData.mShrinkFactor;
+      relayoutData.mTextSizeForRelayoutOption.height += paragraphLayoutInfo.mSize.height * relayoutData.mShrinkFactor;
     }
   }
 }
@@ -303,10 +266,11 @@ void Relayout( Actor textView,
 {
   if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
   {
-    relayoutData.mLineJustificationInfo.clear();
     CalculateSizeAndPosition( layoutParameters,
                               relayoutData );
 
+    TextViewRelayout::ReorderRightToLeftLayout( relayoutData );
+
     TextViewRelayout::SetUnderlineInfo( relayoutData );
   }
 
@@ -323,22 +287,18 @@ void Relayout( Actor textView,
                                         relayoutData );
   }
 
-  if( relayoutOperationMask & TextView::RELAYOUT_INITIALIZE_TEXT_ACTORS )
-  {
-    TextViewProcessor::InitializeTextActorInfo( relayoutData );
-  }
-
-  if( relayoutOperationMask & TextView::RELAYOUT_TEXT_ACTOR_UPDATE )
+  const bool initializeTextActors = relayoutOperationMask & TextView::RELAYOUT_INITIALIZE_TEXT_ACTORS;
+  const bool updateTextActors = relayoutOperationMask & TextView::RELAYOUT_TEXT_ACTOR_UPDATE;
+  if( initializeTextActors || updateTextActors )
   {
     TextViewRelayout::UpdateTextActorInfo( visualParameters,
-                                           relayoutData );
+                                           relayoutData,
+                                           initializeTextActors );
   }
 
-  if( ( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW ) ||
-      ( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST ) )
+  if( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW )
   {
-    TextViewRelayout::InsertToTextView( relayoutOperationMask,
-                                        textView,
+    TextViewRelayout::InsertToTextView( textView,
                                         relayoutData );
   }
 }