X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=base%2Fdali-toolkit%2Finternal%2Fcontrols%2Ftext-view%2Frelayout-utilities.cpp;h=b172976a36de59286354697574947dc89a6ee112;hp=84fd94323ca5178641fbafd70a0d3ccfb87a64a4;hb=1123d866f9342b8950fe63715f6eaa1be9a2c18f;hpb=0f217b9896d284c667e1251ee617e4ddadd4c9e3 diff --git a/base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp b/base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp index 84fd943..b172976 100644 --- a/base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp +++ b/base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp @@ -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 * - * 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, @@ -19,7 +19,11 @@ #include // INTERNAL INCLUDES +#include +#include +#include #include +#include // EXTERNAL INCLUDES #include @@ -40,7 +44,7 @@ const float MINIMUM_FADE_BOUNDARY = 0.05f; // When the fade boundary is the same RelayoutParameters::RelayoutParameters() : mPositionOffset(), - mLineSize(), + mParagraphSize(), mWordSize(), mCharacterSize(), mIndices(), @@ -48,7 +52,7 @@ RelayoutParameters::RelayoutParameters() mIsFirstCharacter( false ), mIsFirstCharacterOfWord( false ), mIsNewLine( false ), - mIsNewLineCharacter( false ), + mIsNewParagraphCharacter( false ), mIsWhiteSpace( false ), mIsVisible( false ) { @@ -131,14 +135,14 @@ TextUnderlineStatus::~TextUnderlineStatus() { } -SubLineLayoutInfo::SubLineLayoutInfo() +LineLayoutInfo::LineLayoutInfo() : mLineLength( 0.f ), mMaxCharHeight( 0.f ), mMaxAscender( 0.f ) { } -SubLineLayoutInfo::~SubLineLayoutInfo() +LineLayoutInfo::~LineLayoutInfo() { } @@ -184,7 +188,7 @@ bool IsExceedingHeight( const Vector3& position, const Size& size, const Size& p * @param[out] lineLength The length of the portion of line which doesn't exceed the parant's width * @param[out] endWhiteSpaceLength The length of white spaces which are at the end of the line. */ -void CalculateLineLength( const bool isWhiteSpace, const float width, const float parentWidth, bool& found, float& lineLength, float& endWhiteSpaceLength ) +void CalculateLineLength( bool isWhiteSpace, float width, float parentWidth, bool& found, float& lineLength, float& endWhiteSpaceLength ) { if( lineLength + width > parentWidth ) { @@ -213,9 +217,7 @@ struct CurrentTextActorInfo Vector3 position; Size size; Vector4 color; - Vector4 gradientColor; - Vector2 startPoint; - Vector2 endPoint; + TextViewProcessor::CharacterLayoutInfo* characterLayout; }; void SetVisualParameters( CurrentTextActorInfo& currentTextActorInfo, @@ -224,9 +226,13 @@ void SetVisualParameters( CurrentTextActorInfo& currentTextActorInfo, const float lineHeight ) { currentTextActorInfo.textActor.SetTextColor( currentTextActorInfo.color ); - currentTextActorInfo.textActor.SetGradientColor( currentTextActorInfo.gradientColor ); - currentTextActorInfo.textActor.SetGradientStartPoint( currentTextActorInfo.startPoint ); - currentTextActorInfo.textActor.SetGradientEndPoint( currentTextActorInfo.endPoint ); + if( ( NULL != currentTextActorInfo.characterLayout ) && + ( NULL != currentTextActorInfo.characterLayout->mGradientInfo ) ) + { + 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 // due to the trick used to implement it. @@ -241,12 +247,12 @@ void SetVisualParameters( CurrentTextActorInfo& currentTextActorInfo, currentTextActorInfo.textActor.SetBlendMode( !visualParameters.mSnapshotModeEnabled ? BlendingMode::ON : BlendingMode::OFF ); } -void CalculateSubLineLayout( const float parentWidth, - const TextViewProcessor::TextInfoIndices& indices, - const TextViewProcessor::LineLayoutInfo& lineLayoutInfo, - const HorizontalWrapType splitPolicy, - const float shrinkFactor, - SubLineLayoutInfo& subLineInfo ) +void CalculateLineLayout( float parentWidth, + const TextViewProcessor::TextInfoIndices& indices, + const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo, + HorizontalWrapType splitPolicy, + float shrinkFactor, + LineLayoutInfo& subLineInfo ) { subLineInfo.mLineLength = 0.f; subLineInfo.mMaxCharHeight = 0.f; @@ -258,8 +264,8 @@ void CalculateSubLineLayout( const float parentWidth, float lineOffset = 0.f; bool found = false; bool isFirstCharacter = true; - for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = lineLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex, - wordEndIt = lineLayoutInfo.mWordsLayoutInfo.end(); + for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = paragraphLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex, + wordEndIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); ( wordIt != wordEndIt ) && !found; ++wordIt ) { @@ -278,7 +284,7 @@ void CalculateSubLineLayout( const float parentWidth, break; } case WrapByWord: - case WrapByLine: // Fall through + case WrapByParagraphCharacter: // Fall through { splitByCharacter = false; break; @@ -288,7 +294,7 @@ void CalculateSubLineLayout( const float parentWidth, splitByCharacter = ( shrunkWordWidth > parentWidth ); break; } - case WrapByLineAndSplit: + case WrapByParagraphCharacterAndSplit: { if( ( 0u != characterIndex ) || ( ( 0u == characterIndex ) && ( lineOffset + shrunkWordWidth > parentWidth ) ) ) @@ -342,7 +348,335 @@ void CalculateSubLineLayout( const float parentWidth, subLineInfo.mMaxAscender *= shrinkFactor; } -float CalculateXoffset( const Toolkit::Alignment::Type horizontalTextAlignment, const float parentWidth, const float wholeTextWidth ) + +/** + * 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] characterGlobalIndex Index within the whole text of the first character of the paragraph. + * @param[in,out] rtlParagraph Layout info for the paragraph with rtl text. + * @param[in,out] relayoutData The text-view's data structures. + */ +void ReorderLayout( std::size_t characterGlobalIndex, + TextViewProcessor::ParagraphLayoutInfo& paragraph, + TextView::RelayoutData& relayoutData ) +{ + // 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::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& 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::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. + // Updates the text-view's layout info table with the new position of the character. + float xPosition = 0.f; + std::size_t index = 0u; + for( TextViewProcessor::CharacterLayoutInfoContainer::iterator it = characters.begin(), endIt = characters.end(); it != endIt; ++it, ++index ) + { + TextViewProcessor::CharacterLayoutInfo& character( *it ); + + // Set the 'x' position. + character.mPosition.x = xPosition; + + // Update layout info table. + relayoutData.mCharacterLayoutInfoTable[characterGlobalIndex + info->mVisualToLogicalMap[index]].mPosition = character.mPosition; + + // Update the position for the next character. + xPosition += character.mSize.width; + } + + // Split the reordered text in words. + std::size_t previousPosition = 0u; + Vector positions; + TextProcessor::SplitInWords( info->mText, positions ); + + // Sets the characters into the words they belong to. + for( Vector::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(); + + // For each character, it sets the character's direction. + + // Initialize the paragraph direction. Used to set the direction of weak characters. + const bool isParagraphRightToLeft = paragraph.mBidirectionalParagraphInfo->IsRightToLeftParagraph(); + bool isPreviousRightToLeft = isParagraphRightToLeft; + + for( std::size_t index = 0u; index < paragraph.mNumberOfCharacters; ++index ) + { + // Get the character's layout information (the one is shared with text-input) + Toolkit::TextView::CharacterLayoutInfo& info = *( relayoutData.mCharacterLayoutInfoTable.begin() + ( characterGlobalIndex + index ) ); + + // Gets the character's direction. + const Character::CharacterDirection direction = paragraph.mText[index].GetCharacterDirection(); + if( Character::RightToLeft == direction ) + { + info.mIsRightToLeftCharacter = true; + } + else if( Character::Neutral == direction ) + { + // For neutral characters it check's the next and previous directions. + // If they are equals set that direction. If they are not, sets the paragraph direction. + // If there is no next, sets the previous direction. + + // Check next character's direction. + bool isNextRightToLeft = isPreviousRightToLeft; + if( index < paragraph.mNumberOfCharacters - 1u ) + { + const Character::CharacterDirection nextDirection = paragraph.mText[index + 1u].GetCharacterDirection(); + isNextRightToLeft = Character::RightToLeft == nextDirection; + } + + info.mIsRightToLeftCharacter = isPreviousRightToLeft == isNextRightToLeft ? isPreviousRightToLeft : isParagraphRightToLeft; + } + else + { + info.mIsRightToLeftCharacter = false; + } + + isPreviousRightToLeft = info.mIsRightToLeftCharacter; + } + + 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. + + // Stores the current global character index as is needed in both functions. + const std::size_t currentGlobalIndex = characterGlobalIndex; + + // Creates the bidirectional info needed to reorder each line of the paragraph. + CreateBidirectionalInfoForLines( relayoutData, + paragraph, + characterGlobalIndex, + lineLayoutInfoIndex ); + + // Reorder each line of the paragraph + ReorderLayout( currentGlobalIndex, paragraph, relayoutData ); + } + 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 ); switch( horizontalTextAlignment ) @@ -371,7 +705,7 @@ float CalculateXoffset( const Toolkit::Alignment::Type horizontalTextAlignment, return xOffset; } -float CalculateYoffset( const Toolkit::Alignment::Type verticalTextAlignment, const float parentHeight, const float wholeTextHeight ) +float CalculateYoffset( Toolkit::Alignment::Type verticalTextAlignment, float parentHeight, float wholeTextHeight ) { float yOffset( 0.f ); switch( verticalTextAlignment ) @@ -400,7 +734,7 @@ float CalculateYoffset( const Toolkit::Alignment::Type verticalTextAlignment, co return yOffset; } -float CalculateJustificationOffset( const Toolkit::TextView::LineJustification justification, const float wholeTextWidth, const float lineLength ) +float CalculateJustificationOffset( Toolkit::TextView::LineJustification justification, float wholeTextWidth, float lineLength ) { float offset = 0.f; switch( justification ) @@ -430,7 +764,7 @@ float CalculateJustificationOffset( const Toolkit::TextView::LineJustification j return offset; } -bool IsVisible( const Vector3& position, const Size& size, const Size& parentSize, const VisibilityTestType type ) +bool IsVisible( const Vector3& position, const Size& size, const Size& parentSize, VisibilityTestType type ) { bool visible = false; @@ -512,24 +846,33 @@ 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 ); - 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.mLineIndex = 0u; + relayoutParameters.mIndices.mParagraphIndex = 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 ); 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; - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(), - endWordLayoutIt = lineLayoutInfo.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 ) { @@ -540,19 +883,24 @@ void UpdateAlignment( const TextView::LayoutParameters& layoutParameters, 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 ); - // 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. } } @@ -564,16 +912,17 @@ void UpdateAlignment( const TextView::LayoutParameters& layoutParameters, // Updates the size and position table for text-input with the alignment offset. Vector3 positionOffset( characterLayoutInfo.mPosition ); - std::vector::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex; + // Update layout info table. + std::vector::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + relayoutData.mCharacterVisualToLogicalMap[characterGlobalIndex]; Toolkit::TextView::CharacterLayoutInfo& characterTableInfo( *infoTableIt ); characterTableInfo.mPosition.x = positionOffset.x + characterLayoutInfo.mOffset.x; characterTableInfo.mPosition.y = positionOffset.y + characterLayoutInfo.mOffset.y; - positionOffset.x += characterLayoutInfo.mAdvance * relayoutData.mShrinkFactor; + positionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor; } // end characters } // end words - } // end lines + } // end paragraphs } void CalculateBearing( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, @@ -641,21 +990,22 @@ void UpdateLayoutInfoTable( Vector4& minMaxXY, const float descender = characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender; - const Toolkit::TextView::CharacterLayoutInfo characterLayoutTableInfo( Size( characterLayoutInfo.mAdvance * relayoutData.mShrinkFactor, - characterLayoutInfo.mHeight * relayoutData.mShrinkFactor ), + const Toolkit::TextView::CharacterLayoutInfo characterLayoutTableInfo( Size( characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor, + characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor ), positionOffset, - ( TextViewProcessor::LineSeparator == wordLayoutInfo.mType ), - false, // VCC set the correct direction if needed. - true, + ( TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType ), + false, // whether the character is right to left. The value is set in a next step in the CreateBidirectionalInfoForLines function + true, // whether the character is visible. descender ); relayoutData.mCharacterLayoutInfoTable.push_back( characterLayoutTableInfo ); - positionOffset.x += characterLayoutInfo.mAdvance * relayoutData.mShrinkFactor; + positionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor; } void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters, TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, + const TextStyle& style, RelayoutParameters& relayoutParameters, FadeParameters& fadeParameters, TextView::RelayoutData& relayoutData ) @@ -817,25 +1167,35 @@ void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& lay // 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 ); - 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 ) { - 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 ); - 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(); + } } } @@ -844,31 +1204,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 ) { - 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 ); - 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 ) { - 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 ); - 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.mGradientColor = gradientColor; - characterLayoutInfo.mStartPoint = startPoint; - characterLayoutInfo.mEndPoint = endPoint; + if( NULL != characterLayoutInfo.mGradientInfo ) + { + characterLayoutInfo.mGradientInfo->mGradientColor = gradientColor; + characterLayoutInfo.mGradientInfo->mStartPoint = startPoint; + characterLayoutInfo.mGradientInfo->mEndPoint = endPoint; + } } else { @@ -1028,16 +1401,18 @@ void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters, 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; - ++ellipsizeCharacterLayoutIt ) + ++ellipsizeCharacterLayoutIt, ++characterIndex ) { const TextViewProcessor::CharacterLayoutInfo& ellipsizeCharacterLayoutInfo( *ellipsizeCharacterLayoutIt ); + const TextStyle& style = *( *( relayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin() + characterIndex ) ); 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() ) @@ -1055,8 +1430,8 @@ void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters, } // 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; @@ -1065,7 +1440,7 @@ void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters, 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 ); } } @@ -1086,16 +1461,16 @@ void EllipsizeLine( const TextView::LayoutParameters& layoutParameters, EllipsizeParameters& ellipsizeParameters, TextView::RelayoutData& relayoutData ) { - // Traverses the text layout info from the first character of the laid out line + // Traverses the text layout info from the first character of the line // to the last one setting to each character its visibility. If needed, it adds the ellipsize text (...). - // Indices to the first character of the laid out line. + // Indices to the first character of the line. TextViewProcessor::TextInfoIndices firstIndices; TextViewProcessor::GetIndicesFromGlobalCharacterIndex( ellipsizeParameters.mFirstIndex, relayoutData.mTextLayoutInfo, firstIndices ); - // Indices to the last character of the laid out line. + // Indices to the last character of the line. TextViewProcessor::TextInfoIndices lastIndices; TextViewProcessor::GetIndicesFromGlobalCharacterIndex( ellipsizeParameters.mLastIndex, relayoutData.mTextLayoutInfo, @@ -1106,12 +1481,12 @@ void EllipsizeLine( const TextView::LayoutParameters& layoutParameters, ellipsizeParameters.mEllipsizeBoundary = relayoutData.mTextViewSize; ellipsizeParameters.mEllipsizeBoundary.width -= relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mSize.width; - for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin() + firstIndices.mLineIndex, - endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin() + lastIndices.mLineIndex + 1u; - lineLayoutIt != endLineLayoutIt; - ++lineLayoutIt ) + for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + firstIndices.mParagraphIndex, + endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + lastIndices.mParagraphIndex + 1u; + paragraphLayoutIt != endParagraphLayoutIt; + ++paragraphLayoutIt ) { - TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt ); + TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); ellipsizeParameters.mLineFits = ellipsizeParameters.mIsLineWidthFullyVisible && ellipsizeParameters.mIsLineHeightFullyVisible && ellipsizeParameters.mIsNextLineFullyVisibleHeight; @@ -1125,8 +1500,11 @@ void EllipsizeLine( const TextView::LayoutParameters& layoutParameters, std::size_t wordCount = 0u; - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin() + firstIndices.mWordIndex, - endWordLayoutIt = lineLayoutInfo.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 ) { @@ -1176,20 +1554,24 @@ void EllipsizeLine( const TextView::LayoutParameters& layoutParameters, } // end characters firstWord = false; } // end words - } // end lines + } // end paragraphs } void SetTextVisible( TextView::RelayoutData& relayoutData ) { - for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), - endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end(); - lineLayoutIt != endLineLayoutIt; - ++lineLayoutIt ) + for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), + endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); + paragraphLayoutIt != endParagraphLayoutIt; + ++paragraphLayoutIt ) { - TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt ); + 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 = lineLayoutInfo.mWordsLayoutInfo.begin(), - endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.end(); + for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(), + endWordLayoutIt = wordsLayoutInfo.end(); wordLayoutIt != endWordLayoutIt; ++wordLayoutIt ) { @@ -1198,18 +1580,17 @@ void SetTextVisible( TextView::RelayoutData& relayoutData ) for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt ) + ++characterLayoutIt, ++characterIndex ) { TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); characterLayoutInfo.mIsVisible = true; - characterLayoutInfo.mGradientColor = Vector4::ZERO; - characterLayoutInfo.mStartPoint = Vector2::ZERO; - characterLayoutInfo.mEndPoint = Vector2::ZERO; - characterLayoutInfo.mColorAlpha = characterLayoutInfo.mStyledText.mStyle.GetTextColor().a; + delete characterLayoutInfo.mGradientInfo; + characterLayoutInfo.mGradientInfo = NULL; + characterLayoutInfo.mColorAlpha = ( *( paragraphLayoutInfo.mTextStyles.Begin() + characterIndex ) )->GetTextColor().a; } // end characters } // end words - } // end lines + } // end paragraphs // Updates the visibility for text-input.. for( std::vector::iterator it = relayoutData.mCharacterLayoutInfoTable.begin(), @@ -1258,19 +1639,23 @@ void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters std::size_t infoTableCharacterIndex = 0u; - relayoutParameters.mIndices.mLineIndex = 0u; + relayoutParameters.mIndices.mParagraphIndex = 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 ); + std::size_t characterIndex = 0u; relayoutParameters.mIndices.mWordIndex = 0u; - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(), - endWordLayoutIt = lineLayoutInfo.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 ) { @@ -1283,7 +1668,7 @@ void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters 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 ); @@ -1293,12 +1678,13 @@ void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters // Calculates the visibility for the current character. CalculateVisibilityForFade( layoutParameters, characterLayoutInfo, + *( *( paragraphLayoutInfo.mTextStyles.Begin() + characterIndex ) ), relayoutParameters, fadeParameters, relayoutData ); // Updates the visibility for text-input.. - std::vector::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex; + std::vector::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + relayoutData.mCharacterVisualToLogicalMap[infoTableCharacterIndex]; Toolkit::TextView::CharacterLayoutInfo& characterLayoutTableInfo( *it ); @@ -1307,23 +1693,25 @@ void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters relayoutParameters.mIsFirstCharacterOfWord = false; } // end character } // end words - } // end lines + } // end paragraphs } void UpdateVisibilityForEllipsize( const TextView::LayoutParameters& layoutParameters, const TextView::VisualParameters& visualParameters, TextView::RelayoutData& relayoutData ) { - // Traverses the laid-out lines and checks which ones doesn't fit in the text-view's boundary. + // TODO check ellipsis with rtl text. + + // Traverses the lines and checks which ones doesn't fit in the text-view's boundary. for( Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineInfoIt = relayoutData.mLines.begin(), endLineInfoIt = relayoutData.mLines.end(); lineInfoIt != endLineInfoIt; ++lineInfoIt ) { const Toolkit::TextView::LineLayoutInfo& lineInfo( *lineInfoIt ); - // To check if a laid-out line fits in the text-view's boundary, + // To check if a line fits in the text-view's boundary, // get the position of the first character is needed and do the test - // with the laid-out line size. + // with the line size. // An bearing offset may have been applied to the first character so it's needed to // get the start position of the line. @@ -1500,7 +1888,7 @@ void CreateEmoticon( const TextView::VisualParameters& visualParameters, * * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in,out] line Layout info for the line. + * @param[in,out] paragraph Layout info for the paragraph. * @param[in,out] characterLayout Layout info for the character. * @param[in] character The character. * @param[in] style The character's style. @@ -1509,7 +1897,7 @@ void CreateEmoticon( const TextView::VisualParameters& visualParameters, */ void CreateTextActor( const TextView::VisualParameters& visualParameters, TextView::RelayoutData& relayoutData, - const TextViewProcessor::LineLayoutInfo& line, + const TextViewProcessor::ParagraphLayoutInfo& paragraph, TextViewProcessor::CharacterLayoutInfo& characterLayout, const Character& character, const TextStyle& style, @@ -1519,18 +1907,33 @@ void CreateTextActor( const TextView::VisualParameters& visualParameters, // 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 ); SetVisualParameters( currentTextActorInfo, visualParameters, relayoutData, - line.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.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; @@ -1538,10 +1941,6 @@ void CreateTextActor( const TextView::VisualParameters& visualParameters, currentTextActorInfo.color = style.GetTextColor(); currentTextActorInfo.color.a = characterLayout.mColorAlpha; - currentTextActorInfo.gradientColor = characterLayout.mGradientColor; - currentTextActorInfo.startPoint = characterLayout.mStartPoint; - currentTextActorInfo.endPoint = characterLayout.mEndPoint; - TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); if( createGlyphActors ) @@ -1567,6 +1966,9 @@ void CreateTextActor( const TextView::VisualParameters& visualParameters, textActor.SetTextStyle( style ); } } + characterLayout.mSetText = true; + currentTextActorInfo.characterLayout = &characterLayout; + characterLayout.mGlyphActor = textActor; } @@ -1575,46 +1977,59 @@ void CreateTextActor( const TextView::VisualParameters& visualParameters, } /** - * Traverses the whole line initializating renderable-actor handles and updating them with the new size and position. + * Traverses the whole paragraph initializating renderable-actor handles and updating them with the new size and position. * * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in,out] line Layout info for the line. + * @param[in,out] paragraph Layout info for the paragraph. * @param[in,out] characterGlobalIndex Index to the character within the whole text. - * @param[in,out] lineLayoutInfoIndex Index to the table of laid out lines. + * @param[in,out] lineLayoutInfoIndex Index to the table of lines. * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles. */ -void UpdateTextActorInfoForLine( const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData, - TextViewProcessor::LineLayoutInfo& line, - std::size_t& characterGlobalIndex, - std::size_t& lineLayoutInfoIndex, - bool createGlyphActors ) +void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualParameters, + TextView::RelayoutData& relayoutData, + TextViewProcessor::ParagraphLayoutInfo& paragraphLayout, + std::size_t& characterGlobalIndex, + std::size_t& lineLayoutInfoIndex, + bool createGlyphActors ) { + // TODO: Check if there is text-actor created only with white spaces. Check first in RTL text. + CurrentTextActorInfo currentTextActorInfo; + currentTextActorInfo.characterLayout = NULL; - const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of laid out lines. - bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last laid out line. + const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines. + bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last line. bool glyphActorCreatedForLine = false; // Whether a renderable actor has been created for this line. TextStyle currentStyle; // style for the current text-actor. - Vector4 currentGradientColor; // gradient color for the current text-actor. - Vector2 currentStartPoint; // start point for the current text-actor. - Vector2 currentEndPoint; // end point for the current text-actor. + TextViewProcessor::GradientInfo* currentGradientInfo = NULL; // gradient color for the current text-actor. + // start point for the current text-actor. + // end point for the current text-actor. bool currentIsColorGlyph = false; // Whether current glyph is an emoticon. std::vector textActorsToRemove; // Keep a vector of text-actors to be included into the cache. - std::size_t characterLineIndex = 0u; // Index to the character (within the line). - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = line.mWordsLayoutInfo.begin(), wordEndIt = line.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 != paragraphLayout.mRightToLeftLayout; + + TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayout.mWordsLayoutInfo; + Text& text = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mText : paragraphLayout.mText; + Vector& 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). + for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end(); 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 ) { @@ -1636,33 +2051,40 @@ void UpdateTextActorInfoForLine( const TextView::VisualParameters& visualParamet } // 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 || - !character.IsWhiteSpace() || // A new line 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 line character. + // Do not create a glyph-actor if it's a white space (without underline) or a new paragraph character. - // Creates one glyph-actor for each counsecutive group of characters, with the same style, per line, or if it's an emoticon. + // Check if the character has the same gradient info than the current one. + bool differentGradientInfo = false; + if( characterLayout.mGradientInfo && currentGradientInfo ) + { + differentGradientInfo = ( characterLayout.mGradientInfo->mGradientColor != currentGradientInfo->mGradientColor ) || + ( characterLayout.mGradientInfo->mStartPoint != currentGradientInfo->mStartPoint ) || + ( characterLayout.mGradientInfo->mEndPoint != currentGradientInfo->mEndPoint ); + } + else if( ( NULL != currentGradientInfo ) || ( NULL != characterLayout.mGradientInfo ) ) + { + differentGradientInfo = true; + } + // Creates one glyph-actor for each counsecutive group of characters, with the same style, per line, or if it's an emoticon. if( !glyphActorCreatedForLine || characterLayout.mIsColorGlyph || + differentGradientInfo || ( characterLayout.mIsColorGlyph != currentIsColorGlyph ) || - ( style != currentStyle ) || - ( characterLayout.mGradientColor != currentGradientColor ) || - ( characterLayout.mStartPoint != currentStartPoint ) || - ( characterLayout.mEndPoint != currentEndPoint ) ) + ( style != currentStyle ) ) { characterLayout.mSetText = false; characterLayout.mSetStyle = false; - // There is a new style or a new line. - glyphActorCreatedForLine = true; - if( characterLayout.mIsColorGlyph ) { CreateEmoticon( visualParameters, @@ -1673,19 +2095,20 @@ void UpdateTextActorInfoForLine( const TextView::VisualParameters& visualParamet { CreateTextActor( visualParameters, relayoutData, - line, + paragraphLayout, 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; - currentGradientColor = characterLayout.mGradientColor; - currentStartPoint = characterLayout.mStartPoint; - currentEndPoint = characterLayout.mEndPoint; + currentGradientInfo = characterLayout.mGradientInfo; currentIsColorGlyph = characterLayout.mIsColorGlyph; characterLayout.mGlyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); @@ -1714,7 +2137,7 @@ void UpdateTextActorInfoForLine( const TextView::VisualParameters& visualParamet characterLayout.mGlyphActor.Reset(); } } - } // no white space / new line char + } // no white space / new paragraph char else { appendCharacter = true; @@ -1723,7 +2146,7 @@ void UpdateTextActorInfoForLine( const TextView::VisualParameters& visualParamet if( appendCharacter ) { // Add the character to the current text-actor and update the size. - if( characterLayout.mIsVisible && ( TextViewProcessor::LineSeparator != word.mType ) ) + if( characterLayout.mIsVisible && ( TextViewProcessor::ParagraphSeparator != wordLayout.mType ) ) { currentTextActorInfo.text.Append( character ); @@ -1734,7 +2157,7 @@ void UpdateTextActorInfoForLine( const TextView::VisualParameters& visualParamet } ++characterGlobalIndex; - ++characterLineIndex; + ++characterParagraphIndex; } // characters } // words @@ -1742,14 +2165,19 @@ void UpdateTextActorInfoForLine( const TextView::VisualParameters& visualParamet { 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, - line.mSize.height ); + paragraphLayout.mSize.height ); } } @@ -1761,29 +2189,30 @@ void UpdateTextActorInfo( const TextView::VisualParameters& visualParameters, TextView::RelayoutData& relayoutData, bool createGlyphActors ) { - if( relayoutData.mTextLayoutInfo.mLinesLayoutInfo.empty() ) + if( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) { - // nothing to do if there is no lines. + // nothing to do if there is no paragraphs. return; } std::size_t characterGlobalIndex = 0u; // Index to the global character (within the whole text). - std::size_t lineLayoutInfoIndex = 0u; // Index to the laid out line info. + std::size_t lineLayoutInfoIndex = 0u; // Index to the line info. - for( TextViewProcessor::LineLayoutInfoContainer::iterator lineIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), lineEndIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end(); - lineIt != lineEndIt; - ++lineIt ) + for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); + paragraphIt != paragraphEndIt; + ++paragraphIt ) { - TextViewProcessor::LineLayoutInfo& line( *lineIt ); + TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt ); - UpdateTextActorInfoForLine( visualParameters, - relayoutData, - line, - characterGlobalIndex, - lineLayoutInfoIndex, - createGlyphActors ); - } // lines + UpdateTextActorInfoForParagraph( visualParameters, + relayoutData, + paragraph, + characterGlobalIndex, + lineLayoutInfoIndex, + createGlyphActors ); + } // paragraphs + // Set visual parameters for ellipsis renderable actors. for( std::vector::iterator it = relayoutData.mEllipsizedGlyphActors.begin(), endIt = relayoutData.mEllipsizedGlyphActors.end(); it != endIt; @@ -1804,18 +2233,23 @@ void UpdateTextActorInfo( const TextView::VisualParameters& visualParameters, void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelayout::TextUnderlineStatus& textUnderlineStatus ) { - // Traverse the whole text to find all groups of consecutive underlined characters in the same laid-out line. + // Traverse the whole text to find all groups of consecutive underlined characters in the same line. // - // Note that relayoutData.mTextLayoutInfo contains layout info per line but these lines are the result of split the whole text every time a '\n' is found. - // According with the layout option, one of this lines could be laid-out in more than one. + // Note that relayoutData.mTextLayoutInfo contains layout info per paragraph but these paragraphs are the result of split the whole text every time a '\n' is found. + // According with the layout option, one of this paragraphs could be laid-out in more than one line. - for( TextViewProcessor::LineLayoutInfoContainer::iterator lineIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), lineEndIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end(); - lineIt != lineEndIt; - ++lineIt ) + for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); + paragraphIt != paragraphEndIt; + ++paragraphIt ) { - TextViewProcessor::LineLayoutInfo& line( *lineIt ); + TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt ); + + std::size_t characterIndex = 0u; - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = line.mWordsLayoutInfo.begin(), wordEndIt = line.mWordsLayoutInfo.end(); + 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 ) { @@ -1823,11 +2257,12 @@ void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelay for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end(); characterIt != characterEndIt; - ++characterIt ) + ++characterIt, ++characterIndex ) { TextViewProcessor::CharacterLayoutInfo& character( *characterIt ); + const TextStyle& style = *( *( paragraph.mTextStyles.Begin() + characterIndex ) ); - // Check if current character is the first of a new laid-out line + // Check if current character is the first of a new line const bool isNewLine = ( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() ) && ( textUnderlineStatus.mCharacterGlobalIndex == ( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) ).mCharacterGlobalIndex ); if( isNewLine ) @@ -1835,10 +2270,10 @@ void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelay ++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 laid-out line. + isNewLine ) // Current character is underlined and is the first of current line. { // Create a new underline info for the current underlined characters. UnderlineInfo underlineInfo; @@ -1872,15 +2307,15 @@ void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelay ++textUnderlineStatus.mCharacterGlobalIndex; } // end characters. } // end words. - } // end lines. + } // end paragraphs. } void SetUnderlineInfo( TextView::RelayoutData& relayoutData ) { - // Stores for each group of consecutive underlined characters in each laid-out line its maximum thicknes, its position of that thickness and the maximum character's height. + // Stores for each group of consecutive underlined characters in each line its maximum thicknes, its position of that thickness and the maximum character's height. TextViewRelayout::TextUnderlineStatus textUnderlineStatus; - // Traverse the whole text to find all groups of consecutive underlined characters in the same laid-out line. + // Traverse the whole text to find all groups of consecutive underlined characters in the same line. CalculateUnderlineInfo( relayoutData, textUnderlineStatus ); if( textUnderlineStatus.mUnderlineInfo.empty() ) @@ -1910,13 +2345,17 @@ void SetUnderlineInfo( TextView::RelayoutData& relayoutData ) float currentLineHeight = 0.f; float currentLineAscender = 0.f; - for( TextViewProcessor::LineLayoutInfoContainer::iterator lineIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), lineEndIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end(); - lineIt != lineEndIt; - ++lineIt ) + for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); + paragraphIt != paragraphEndIt; + ++paragraphIt ) { - TextViewProcessor::LineLayoutInfo& line( *lineIt ); + 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 = line.mWordsLayoutInfo.begin(), wordEndIt = line.mWordsLayoutInfo.end(); + for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end(); wordIt != wordEndIt; ++wordIt ) { @@ -1924,11 +2363,12 @@ void SetUnderlineInfo( TextView::RelayoutData& relayoutData ) for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end(); characterIt != characterEndIt; - ++characterIt ) + ++characterIt, ++characterIndex ) { TextViewProcessor::CharacterLayoutInfo& character( *characterIt ); + TextStyle& style = *( *( paragraph.mTextStyles.Begin() + characterIndex ) ); - // Check if current character is the first of a new laid-out line + // Check if current character is the first of a new line bool isNewLine = false; @@ -1945,7 +2385,7 @@ void SetUnderlineInfo( TextView::RelayoutData& relayoutData ) } } - if( character.mStyledText.mStyle.IsUnderlineEnabled() ) + if( style.IsUnderlineEnabled() ) { if( textUnderlineStatus.mCurrentUnderlineStatus ) { @@ -1970,7 +2410,7 @@ void SetUnderlineInfo( TextView::RelayoutData& relayoutData ) 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; @@ -1996,7 +2436,7 @@ void SetUnderlineInfo( TextView::RelayoutData& relayoutData ) ++textUnderlineStatus.mCharacterGlobalIndex; } // end of characters. } // end of word. - } // end of lines. + } // end of paragraphs. } void RemoveGlyphActors( Actor textView, @@ -2019,15 +2459,19 @@ void InsertToTextView( Actor textView, { // Add text-actors to the text-view. - for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), - endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end(); - lineLayoutIt != endLineLayoutIt; - ++lineLayoutIt ) + for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), + endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); + paragraphLayoutIt != endParagraphLayoutIt; + ++paragraphLayoutIt ) { - TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt ); + TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); + + // 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 = lineLayoutInfo.mWordsLayoutInfo.begin(), - endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.end(); + for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(), + endWordLayoutIt = wordsLayoutInfo.end(); wordLayoutIt != endWordLayoutIt; ++wordLayoutIt ) { @@ -2048,7 +2492,7 @@ void InsertToTextView( Actor textView, } } // end character } // end words - } // end lines + } // end paragraphs for( std::vector::iterator it = relayoutData.mEllipsizedGlyphActors.begin(), endIt = relayoutData.mEllipsizedGlyphActors.end();