* 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,
// FILE HEADER
#include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h>
-
// EXTERNAL INCLUDES
#include <cmath>
+#include <dali/public-api/text/text-actor-parameters.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-dbg.h>
namespace Dali
{
RelayoutParameters::RelayoutParameters()
: mPositionOffset(),
- mLineSize(),
+ mParagraphSize(),
mWordSize(),
mCharacterSize(),
mIndices(),
mIsFirstCharacter( false ),
mIsFirstCharacterOfWord( false ),
mIsNewLine( false ),
- mIsNewLineCharacter( false ),
+ mIsNewParagraphCharacter( false ),
mIsWhiteSpace( false ),
mIsVisible( false )
{
{
}
-SubLineLayoutInfo::SubLineLayoutInfo()
+LineLayoutInfo::LineLayoutInfo()
: mLineLength( 0.f ),
mMaxCharHeight( 0.f ),
mMaxAscender( 0.f )
{
}
-SubLineLayoutInfo::~SubLineLayoutInfo()
+LineLayoutInfo::~LineLayoutInfo()
{
}
* @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 )
{
Vector3 position;
Size size;
Vector4 color;
- Vector4 gradientColor;
- Vector2 startPoint;
- Vector2 endPoint;
+ TextViewProcessor::CharacterLayoutInfo* characterLayout;
};
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.
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;
float endWhiteSpaceLength = 0.f;
- std::size_t wordIndex = indices.mWordIndex;
std::size_t characterIndex = indices.mCharacterIndex;
float lineOffset = 0.f;
bool found = false;
bool isFirstCharacter = true;
- for( TextViewProcessor::WordGroupLayoutInfoContainer::const_iterator wordGroupIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin() + indices.mGroupIndex,
- wordGroupEndIt = lineLayoutInfo.mWordGroupsLayoutInfo.end();
- ( wordGroupIt != wordGroupEndIt ) && !found;
- ++wordGroupIt )
+ for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = paragraphLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex,
+ wordEndIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
+ ( wordIt != wordEndIt ) && !found;
+ ++wordIt )
{
- const TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *wordGroupIt );
-
- for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = wordGroupLayoutInfo.mWordsLayoutInfo.begin() + wordIndex,
- wordEndIt = wordGroupLayoutInfo.mWordsLayoutInfo.end();
- ( wordIt != wordEndIt ) && !found;
- ++wordIt )
- {
- const TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordIt );
+ const TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordIt );
- const float shrunkWordWidth = wordLayoutInfo.mSize.width * shrinkFactor;
- const bool isWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType;
+ const float shrunkWordWidth = wordLayoutInfo.mSize.width * shrinkFactor;
+ const bool isWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType;
- bool splitByCharacter = false;
+ bool splitByCharacter = false;
- switch( splitPolicy )
+ switch( splitPolicy )
+ {
+ case WrapByCharacter:
+ {
+ splitByCharacter = true;
+ break;
+ }
+ case WrapByWord:
+ case WrapByParagraphCharacter: // Fall through
+ {
+ splitByCharacter = false;
+ break;
+ }
+ case WrapByWordAndSplit:
+ {
+ splitByCharacter = ( shrunkWordWidth > parentWidth );
+ break;
+ }
+ case WrapByParagraphCharacterAndSplit:
{
- case WrapByCharacter:
+ if( ( 0u != characterIndex ) ||
+ ( ( 0u == characterIndex ) && ( lineOffset + shrunkWordWidth > parentWidth ) ) )
{
splitByCharacter = true;
- break;
}
- case WrapByWord:
- case WrapByLine: // Fall through
+ else
{
+ lineOffset += shrunkWordWidth;
splitByCharacter = false;
- break;
- }
- case WrapByWordAndSplit:
- {
- splitByCharacter = ( shrunkWordWidth > parentWidth );
- break;
- }
- case WrapByLineAndSplit:
- {
- if( ( 0 != characterIndex ) ||
- ( ( 0 == characterIndex ) && ( lineOffset + shrunkWordWidth > parentWidth ) ) )
- {
- splitByCharacter = true;
- }
- else
- {
- lineOffset += shrunkWordWidth;
- splitByCharacter = false;
- }
}
}
+ }
- if( splitByCharacter )
+ if( splitByCharacter )
+ {
+ for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator charIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + characterIndex,
+ charEndIt = wordLayoutInfo.mCharactersLayoutInfo.end();
+ ( charIt != charEndIt ) && !found;
+ ++charIt )
{
- for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator charIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + characterIndex,
- charEndIt = wordLayoutInfo.mCharactersLayoutInfo.end();
- ( charIt != charEndIt ) && !found;
- ++charIt )
+ const TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *charIt );
+ CalculateLineLength( isWhiteSpace, characterLayoutInfo.mSize.width * shrinkFactor, parentWidth, found, subLineInfo.mLineLength, endWhiteSpaceLength );
+ if( !found || isFirstCharacter )
{
- const TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *charIt );
- CalculateLineLength( isWhiteSpace, characterLayoutInfo.mSize.width * shrinkFactor, parentWidth, found, subLineInfo.mLineLength, endWhiteSpaceLength );
- if( !found || isFirstCharacter )
- {
- subLineInfo.mMaxCharHeight = std::max( subLineInfo.mMaxCharHeight, characterLayoutInfo.mSize.height );
- subLineInfo.mMaxAscender = std::max( subLineInfo.mMaxAscender, characterLayoutInfo.mAscender );
- }
-
- // All characters for word 'wordIndex' have been processed.
- // Next word need to process all characters, so the characterIndex is reset to 0.
- characterIndex = 0;
- isFirstCharacter = false;
+ subLineInfo.mMaxCharHeight = std::max( subLineInfo.mMaxCharHeight, characterLayoutInfo.mSize.height );
+ subLineInfo.mMaxAscender = std::max( subLineInfo.mMaxAscender, characterLayoutInfo.mAscender );
}
- lineOffset += subLineInfo.mLineLength;
+ // All characters for word 'wordIndex' have been processed.
+ // Next word need to process all characters, so the characterIndex is reset to 0.
+ characterIndex = 0u;
+ isFirstCharacter = false;
}
- else
+
+ lineOffset += subLineInfo.mLineLength;
+ }
+ else
+ {
+ CalculateLineLength( isWhiteSpace, shrunkWordWidth, parentWidth, found, subLineInfo.mLineLength, endWhiteSpaceLength );
+ if( !found || isFirstCharacter )
{
- CalculateLineLength( isWhiteSpace, shrunkWordWidth, parentWidth, found, subLineInfo.mLineLength, endWhiteSpaceLength );
- if( !found || isFirstCharacter )
- {
- subLineInfo.mMaxCharHeight = std::max( subLineInfo.mMaxCharHeight, wordLayoutInfo.mSize.height );
- subLineInfo.mMaxAscender = std::max( subLineInfo.mMaxAscender, wordLayoutInfo.mAscender );
- }
- isFirstCharacter = false;
+ subLineInfo.mMaxCharHeight = std::max( subLineInfo.mMaxCharHeight, wordLayoutInfo.mSize.height );
+ subLineInfo.mMaxAscender = std::max( subLineInfo.mMaxAscender, wordLayoutInfo.mAscender );
}
+ isFirstCharacter = false;
}
-
- // All words for group 'groupIndex' have been processed.
- // Next group need to process all words, so the wordIndex is reset to 0.
- wordIndex = 0;
}
subLineInfo.mMaxCharHeight *= shrinkFactor;
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<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.
+ // 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<std::size_t> positions;
+ TextProcessor::SplitInWords( info->mText, positions );
+
+ // Whether last character is a word or a paragraph separator.
+ const std::size_t lastCharacterIndex = info->mText.GetLength() - 1u;
+ const bool isLastCharacterParagraphSeparator = info->mText.IsNewLine( lastCharacterIndex );
+ const bool isLastCharacterWordSeparator = info->mText.IsWhiteSpace( lastCharacterIndex );
+
+ // Sets the characters into the words they belong to.
+ for( Vector<std::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 );
+
+ space.mType = TextViewProcessor::WordSeparator;
+
+ 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() );
+
+ if( isLastCharacterParagraphSeparator )
+ {
+ word.mType = TextViewProcessor::ParagraphSeparator;
+ }
+ else if( isLastCharacterWordSeparator )
+ {
+ word.mType = TextViewProcessor::WordSeparator;
+ }
+ 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 )
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 )
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 )
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;
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 = 0; // Index to the first position of the vector which stores all line justification info.
- std::size_t infoTableCharacterIndex = 0;
+ // 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 = 0;
+ 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 );
- relayoutParameters.mIndices.mGroupIndex = 0;
float justificationOffset = 0.f;
- for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(),
- endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end();
- groupLayoutIt != endGroupLayoutIt;
- ++groupLayoutIt, ++relayoutParameters.mIndices.mGroupIndex )
+ 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;
+
+ 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 )
{
- TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *groupLayoutIt );
+ TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
- relayoutParameters.mIndices.mWordIndex = 0;
+ 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, ++characterGlobalIndex )
{
- TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
+ TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
- relayoutParameters.mIndices.mCharacterIndex = 0;
+ // Check if there is a new line.
+ const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex );
- for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
- endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
- characterLayoutIt != endCharacterLayoutIt;
- ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex )
+ if( newLine )
{
- TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
-
// Calculate line justification offset.
- if( lineJustificationIndex < relayoutData.mLineJustificationInfo.size() )
- {
- const TextView::LineJustificationInfo lineJustificationInfo( *( relayoutData.mLineJustificationInfo.begin() + lineJustificationIndex ) );
+ justificationOffset = CalculateJustificationOffset( layoutParameters.mLineJustification, relayoutData.mTextSizeForRelayoutOption.width, relayoutData.mLines[lineLayoutInfoIndex].mSize.width );
- if( relayoutParameters.mIndices == lineJustificationInfo.mIndices )
- {
- justificationOffset = CalculateJustificationOffset( layoutParameters.mLineJustification, relayoutData.mTextSizeForRelayoutOption.width, lineJustificationInfo.mLineLength );
- ++lineJustificationIndex; // increase the index to point the next position in the vector.
- }
+ // 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.
}
+ }
- // Deletes the offsets if the exceed policies are EllipsizeEnd.
- const float horizontalOffset = textHorizontalOffset + justificationOffset;
- characterLayoutInfo.mOffset.x = ( ellipsizeAlignToLeft && ( horizontalOffset < 0.f ) ) ? 0.f : horizontalOffset;
- characterLayoutInfo.mOffset.y = ( ellipsizeAlignToTop && ( textVerticalOffset < 0.f ) ) ? 0.f : textVerticalOffset;
+ // Deletes the offsets if the exceed policies are EllipsizeEnd.
+ const float horizontalOffset = textHorizontalOffset + justificationOffset;
+ characterLayoutInfo.mOffset.x = ( ellipsizeAlignToLeft && ( horizontalOffset < 0.f ) ) ? 0.f : horizontalOffset;
+ characterLayoutInfo.mOffset.y = ( ellipsizeAlignToTop && ( textVerticalOffset < 0.f ) ) ? 0.f : textVerticalOffset;
- // 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;
- Toolkit::TextView::CharacterLayoutInfo& characterTableInfo( *infoTableIt );
+ // Update layout info table.
+ std::vector<Toolkit::TextView::CharacterLayoutInfo>::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;
+ characterTableInfo.mPosition.x = positionOffset.x + characterLayoutInfo.mOffset.x;
+ characterTableInfo.mPosition.y = positionOffset.y + characterLayoutInfo.mOffset.y;
- positionOffset.x += characterLayoutInfo.mAdvance * relayoutData.mShrinkFactor;
- } // end characters
- } // end words
- } // end group of words
- } // end lines
+ positionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor;
+ } // end characters
+ } // end words
+ } // end paragraphs
}
void CalculateBearing( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
// gggggggggg
// gggggggggg
- const Toolkit::TextView::LineLayoutInfo& lineInfo( *( relayoutData.mLines.end() - 1 ) );
+ const Toolkit::TextView::LineLayoutInfo& lineInfo( *( relayoutData.mLines.end() - 1u ) );
const float bearingOffset = ( lineInfo.mSize.height - lineInfo.mAscender ) - ( characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender );
characterLayoutInfo.mPosition.y -= bearingOffset * relayoutData.mShrinkFactor;
}
void UpdateLayoutInfoTable( Vector4& minMaxXY,
- TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo,
TextViewProcessor::WordLayoutInfo& wordLayoutInfo,
TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
RelayoutParameters& relayoutParameters,
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 ),
- ( TextViewProcessor::RTL == wordGroupLayoutInfo.mDirection ),
- 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 )
// 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();
+ }
}
}
// 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
{
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() )
}
// 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;
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 );
}
-
}
if( !ellipsizeText.IsEmpty() )
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,
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 + 1;
- 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;
ellipsizeParameters.mEllipsizeBoundary.width = ellipsizeParameters.mLineWidth;
}
- bool firstGroup = true;
- bool lastGroup = false;
- std::size_t groupCount = 0;
-
bool firstWord = true;
bool lastWord = false;
- for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin() + firstIndices.mGroupIndex,
- endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin() + lastIndices.mGroupIndex + 1;
- groupLayoutIt != endGroupLayoutIt;
- ++groupLayoutIt, ++groupCount )
+ std::size_t wordCount = 0u;
+
+ 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 )
{
- TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *groupLayoutIt );
+ TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
- if( groupCount == lastIndices.mGroupIndex - firstIndices.mGroupIndex )
+ if( wordCount == lastIndices.mWordIndex - firstIndices.mWordIndex )
{
- lastGroup = true;
+ lastWord = true;
}
- std::size_t wordCount = 0;
- const std::size_t firstWordIndex = firstGroup ? firstIndices.mWordIndex : 0u;
- const std::size_t lastWordIndex = lastGroup ? lastIndices.mWordIndex : wordGroupLayoutInfo.mWordsLayoutInfo.size() - 1;
-
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.begin() + firstWordIndex,
- endWordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.begin() + lastWordIndex + 1;
- wordLayoutIt != endWordLayoutIt;
- ++wordLayoutIt, ++wordCount )
+ const std::size_t firstCharacterIndex = firstWord ? firstIndices.mCharacterIndex : 0u;
+ const std::size_t lastCharacterIndex = lastWord ? lastIndices.mCharacterIndex : wordLayoutInfo.mCharactersLayoutInfo.size() - 1u;
+ for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + firstCharacterIndex,
+ endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + lastCharacterIndex + 1u;
+ characterLayoutIt != endCharacterLayoutIt;
+ ++characterLayoutIt )
{
- TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
+ TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
- if( lastGroup && ( wordCount == lastIndices.mWordIndex - firstWordIndex ) )
+ if( ellipsizeParameters.mEllipsizeLine )
{
- lastWord = true;
- }
-
- const std::size_t firstCharacterIndex = firstWord ? firstIndices.mCharacterIndex : 0u;
- const std::size_t lastCharacterIndex = lastWord ? lastIndices.mCharacterIndex : wordLayoutInfo.mCharactersLayoutInfo.size() - 1;
- for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + firstCharacterIndex,
- endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + lastCharacterIndex + 1;
- characterLayoutIt != endCharacterLayoutIt;
- ++characterLayoutIt )
- {
- TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
+ // Calculates the character visibility and whether it needs to be replace by ellipsized text.
+ CalculateVisibilityForEllipsize( layoutParameters,
+ characterLayoutInfo,
+ ellipsizeParameters,
+ relayoutData );
- if( ellipsizeParameters.mEllipsizeLine )
+ if( ellipsizeParameters.mCreateEllipsizedTextActors )
{
- // Calculates the character visibility and whether it needs to be replace by ellipsized text.
- CalculateVisibilityForEllipsize( layoutParameters,
- characterLayoutInfo,
- ellipsizeParameters,
- relayoutData );
-
- if( ellipsizeParameters.mCreateEllipsizedTextActors )
- {
- // Create ellipsize text-actors if the character needs to be replaced.
- CreateEllipsizeTextActor( ellipsizeParameters,
- relayoutData );
- }
+ // Create ellipsize text-actors if the character needs to be replaced.
+ CreateEllipsizeTextActor( ellipsizeParameters,
+ relayoutData );
}
- else
+ }
+ else
+ {
+ if( ( TextView::EllipsizeEnd == layoutParameters.mExceedPolicy ) ||
+ ( TextView::SplitEllipsizeEnd == layoutParameters.mExceedPolicy ))
{
- if( ( TextView::EllipsizeEnd == layoutParameters.mExceedPolicy ) ||
- ( TextView::SplitEllipsizeEnd == layoutParameters.mExceedPolicy ))
+ if( !ellipsizeParameters.mIsLineHeightFullyVisible )
{
- if( !ellipsizeParameters.mIsLineHeightFullyVisible )
- {
- // Make characters invisible.
- characterLayoutInfo.mIsVisible = false;
- }
+ // Make characters invisible.
+ characterLayoutInfo.mIsVisible = false;
}
}
- } // end characters
- firstWord = false;
- } // end words
- firstGroup = false;
- } // end groups
- } // end lines
+ }
+ } // end characters
+ firstWord = false;
+ } // end words
+ } // 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;
- for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(),
- endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end();
- groupLayoutIt != endGroupLayoutIt;
- ++groupLayoutIt )
+ 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 )
{
- TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *groupLayoutIt );
+ TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.begin(),
- endWordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.end();
- wordLayoutIt != endWordLayoutIt;
- ++wordLayoutIt )
+ for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
+ endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
+ characterLayoutIt != endCharacterLayoutIt;
+ ++characterLayoutIt, ++characterIndex )
{
- TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
+ TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
- for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
- endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
- characterLayoutIt != endCharacterLayoutIt;
- ++characterLayoutIt )
- {
- 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;
- } // end characters
- } // end words
- } // end group of words
- } // end lines
+ characterLayoutInfo.mIsVisible = true;
+ delete characterLayoutInfo.mGradientInfo;
+ characterLayoutInfo.mGradientInfo = NULL;
+ characterLayoutInfo.mColorAlpha = ( *( paragraphLayoutInfo.mTextStyles.Begin() + characterIndex ) )->GetTextColor().a;
+ } // end characters
+ } // end words
+ } // end paragraphs
// Updates the visibility for text-input..
for( std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator it = relayoutData.mCharacterLayoutInfoTable.begin(),
// Calculates the fade thresholds (from where the text starts to fade out). If any of the fade boundaries is zero, it sets a very small value just to avoid a zero division.
fadeParameters.mRightFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mRight );
- fadeParameters.mRightFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mRight > 0 ? fadeParameters.mRightFadeBoundary : MINIMUM_FADE_BOUNDARY );
+ fadeParameters.mRightFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mRight > 0u ? fadeParameters.mRightFadeBoundary : MINIMUM_FADE_BOUNDARY );
fadeParameters.mRightFadeThreshold = relayoutData.mTextViewSize.width - fadeParameters.mRightFadeBoundary;
fadeParameters.mRightFadeThresholdOffset = relayoutData.mTextViewSize.width - fadeParameters.mRightFadeBoundaryOffset;
fadeParameters.mLeftFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mLeft );
- fadeParameters.mLeftFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mLeft > 0 ? fadeParameters.mLeftFadeBoundary : MINIMUM_FADE_BOUNDARY );
+ fadeParameters.mLeftFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mLeft > 0u ? fadeParameters.mLeftFadeBoundary : MINIMUM_FADE_BOUNDARY );
fadeParameters.mLeftFadeThreshold = fadeParameters.mLeftFadeBoundary;
fadeParameters.mLeftFadeThresholdOffset = fadeParameters.mLeftFadeBoundaryOffset;
fadeParameters.mTopFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mTop );
- fadeParameters.mTopFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mTop > 0 ? fadeParameters.mTopFadeBoundary : MINIMUM_FADE_BOUNDARY );
+ fadeParameters.mTopFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mTop > 0u ? fadeParameters.mTopFadeBoundary : MINIMUM_FADE_BOUNDARY );
fadeParameters.mTopFadeThreshold = fadeParameters.mTopFadeBoundary;
fadeParameters.mTopFadeThresholdOffset = fadeParameters.mTopFadeBoundaryOffset;
fadeParameters.mBottomFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mBottom );
- fadeParameters.mBottomFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mBottom > 0 ? fadeParameters.mBottomFadeBoundary : MINIMUM_FADE_BOUNDARY );
+ fadeParameters.mBottomFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mBottom > 0u ? fadeParameters.mBottomFadeBoundary : MINIMUM_FADE_BOUNDARY );
fadeParameters.mBottomFadeThreshold = relayoutData.mTextViewSize.height - fadeParameters.mBottomFadeBoundary;
fadeParameters.mBottomFadeThresholdOffset = relayoutData.mTextViewSize.height - fadeParameters.mBottomFadeBoundaryOffset;
fadeParameters.mTopAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mTopFadeThresholdOffset, 1.f ), Vector2( 0.f, 0.f ) );
fadeParameters.mBottomAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mBottomFadeThresholdOffset, 1.f ), Vector2( relayoutData.mTextViewSize.height, 0.f ) );
- // Traverses all groups of characters and calculates the visibility.
+ // Traverses all characters and calculates the visibility.
- std::size_t infoTableCharacterIndex = 0;
+ std::size_t infoTableCharacterIndex = 0u;
- relayoutParameters.mIndices.mLineIndex = 0;
+ 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 );
- relayoutParameters.mIndices.mGroupIndex = 0;
+ std::size_t characterIndex = 0u;
+ relayoutParameters.mIndices.mWordIndex = 0u;
- for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(),
- endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end();
- groupLayoutIt != endGroupLayoutIt;
- ++groupLayoutIt, ++relayoutParameters.mIndices.mGroupIndex )
+ 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 )
{
- TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *groupLayoutIt );
+ TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
- 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, ++infoTableCharacterIndex, ++characterIndex )
{
- TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
+ TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
- relayoutParameters.mIsFirstCharacterOfWord = true;
- relayoutParameters.mWordSize = wordLayoutInfo.mSize;
- relayoutParameters.mIndices.mCharacterIndex = 0;
+ relayoutParameters.mIsVisible = true;
+ fadeParameters.mIsPartiallyVisible = false;
- for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
- endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
- characterLayoutIt != endCharacterLayoutIt;
- ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex )
- {
- TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
-
- relayoutParameters.mIsVisible = true;
- fadeParameters.mIsPartiallyVisible = false;
-
- // Calculates the visibility for the current group of characters.
- CalculateVisibilityForFade( layoutParameters,
- characterLayoutInfo,
- relayoutParameters,
- fadeParameters,
- relayoutData );
+ // 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<Toolkit::TextView::CharacterLayoutInfo>::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex;
+ // Updates the visibility for text-input..
+ std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + relayoutData.mCharacterVisualToLogicalMap[infoTableCharacterIndex];
- Toolkit::TextView::CharacterLayoutInfo& characterLayoutTableInfo( *it );
+ Toolkit::TextView::CharacterLayoutInfo& characterLayoutTableInfo( *it );
- characterLayoutTableInfo.mIsVisible = relayoutParameters.mIsVisible;
+ characterLayoutTableInfo.mIsVisible = relayoutParameters.mIsVisible;
- relayoutParameters.mIsFirstCharacterOfWord = false;
- } // end group of character
- } // end words
- } // end group of words
- } // end lines
+ relayoutParameters.mIsFirstCharacterOfWord = false;
+ } // end character
+ } // end words
+ } // 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.
// Retrieves the first index and the last index of the line.
ellipsizeParameters.mFirstIndex = lineInfo.mCharacterGlobalIndex;
- ellipsizeParameters.mLastIndex = 0;
- if( ( lineInfoIt + 1 ) != endLineInfoIt )
+ ellipsizeParameters.mLastIndex = 0u;
+ if( ( lineInfoIt + 1u ) != endLineInfoIt )
{
- const Toolkit::TextView::LineLayoutInfo& nextLineInfo( *( lineInfoIt + 1 ) );
- ellipsizeParameters.mLastIndex = nextLineInfo.mCharacterGlobalIndex - 1;
+ const Toolkit::TextView::LineLayoutInfo& nextLineInfo( *( lineInfoIt + 1u ) );
+ ellipsizeParameters.mLastIndex = nextLineInfo.mCharacterGlobalIndex - 1u;
}
else
{
- ellipsizeParameters.mLastIndex = relayoutData.mCharacterLayoutInfoTable.size() - 1;
+ ellipsizeParameters.mLastIndex = relayoutData.mCharacterLayoutInfoTable.size() - 1u;
}
// Retrieves the first character of the line and build the position of the line with the bearing.
{
// Current line is not ellipsized.
// Need to check if there is a next line and if it's not visible. If there is, current line needs to be ellipsized.
- Toolkit::TextView::LineLayoutInfoContainer::const_iterator nextLineInfoIt = lineInfoIt + 1;
+ Toolkit::TextView::LineLayoutInfoContainer::const_iterator nextLineInfoIt = lineInfoIt + 1u;
if( nextLineInfoIt != endLineInfoIt )
{
// Retrives the position of the first character of the line and remove
}
}
-void UpdateTextActorInfo( const TextView::VisualParameters& visualParameters,
- TextView::RelayoutData& relayoutData )
+/**
+ * Creates an image actor for the emoticon.
+ *
+ * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending).
+ * @param[in,out] characterLayout Layout info for the character.
+ * @param[in] character The character.
+ */
+void CreateEmoticon( const TextView::VisualParameters& visualParameters,
+ TextViewProcessor::CharacterLayoutInfo& characterLayout,
+ const Character& character )
{
- CurrentTextActorInfo currentTextActorInfo;
+ // The character is an emoticon.
+ ImageActor imageActor = ImageActor::DownCast( characterLayout.mGlyphActor );
+ if( !imageActor )
+ {
+ imageActor = ImageActor::New();
+
+ GlyphImage image = GlyphImage::New( character );
+
+ if( image )
+ {
+ imageActor.SetImage( image );
+ }
+ }
- // Traverses the text-actor and layout info data structures.
- for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
- endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
- lineLayoutIt != endLineLayoutIt;
- ++lineLayoutIt )
+ imageActor.SetPosition( Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x,
+ characterLayout.mPosition.y + characterLayout.mOffset.y,
+ characterLayout.mPosition.z ) );
+ imageActor.SetSize( characterLayout.mSize );
+
+ // Sets the sort modifier value.
+ imageActor.SetSortModifier( visualParameters.mSortModifier );
+
+ characterLayout.mGlyphActor = imageActor;
+}
+
+/**
+ * Creates text-actors for the given text.
+ *
+ * @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] paragraph Layout info for the paragraph.
+ * @param[in,out] wordLayout Layout info for the word.
+ * @param[in,out] characterLayout Layout info for the character.
+ * @param[in] character The character.
+ * @param[in] style The character's style.
+ * @param[in,out] currentTextActorInfo Temporary stores the text-actor's info to be set.
+ * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles.
+ * @param[in,out] textActorCreated Whether a text-actor
+ */
+void CreateTextActor( const TextView::VisualParameters& visualParameters,
+ TextView::RelayoutData& relayoutData,
+ const TextViewProcessor::ParagraphLayoutInfo& paragraph,
+ TextViewProcessor::WordLayoutInfo& wordLayout,
+ TextViewProcessor::CharacterLayoutInfo& characterLayout,
+ const Character& character,
+ const TextStyle& style,
+ CurrentTextActorInfo& currentTextActorInfo,
+ bool createGlyphActors,
+ bool& textActorCreated )
+{
+ textActorCreated = false;
+
+ // Set the text-actor for the current traversed text.
+ if( currentTextActorInfo.textActor )
{
- TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
+ 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,
+ paragraph.mSize.height );
+ }
- for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(),
- endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end();
- groupLayoutIt != endGroupLayoutIt;
- ++groupLayoutIt )
+ 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;
+ }
+
+ // Whether this word is not a white space or if it is, it is underlined.
+ // Don't want to create text-actors for white spaces unless they are underlined.
+ bool isNotWhiteSpace = ( TextViewProcessor::NoSeparator == wordLayout.mType ) || ( ( TextViewProcessor::WordSeparator == wordLayout.mType ) && style.IsUnderlineEnabled() );
+
+ if( isNotWhiteSpace )
+ {
+ currentTextActorInfo.text = Text( character );
+ }
+ else
+ {
+ currentTextActorInfo.text = Text();
+ }
+ 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;
+
+ currentTextActorInfo.color = style.GetTextColor();
+ currentTextActorInfo.color.a = characterLayout.mColorAlpha;
+
+ TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor );
+
+ if( createGlyphActors && isNotWhiteSpace )
+ {
+ textActorCreated = true;
+ if( textActor )
{
- TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *groupLayoutIt );
+ // Try to reuse first the text-actor of this character.
+ textActor.SetTextStyle( style );
+ }
+ else
+ {
+ // If there is no text-actor, try to retrieve one from the cache.
+ textActor = relayoutData.mTextActorCache.RetrieveTextActor();
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.begin(),
- endWordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.end();
- wordLayoutIt != endWordLayoutIt;
- ++wordLayoutIt )
+ // If still there is no text-actor, create one.
+ if( !textActor )
{
- TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
+ TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_OFF );
+ textActor = TextActor::New( Text(), parameters );
+ }
+ else
+ {
+ textActor.SetTextStyle( style );
+ }
+ }
+ characterLayout.mSetText = true;
+ currentTextActorInfo.characterLayout = &characterLayout;
- for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
- endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
- characterLayoutIt != endCharacterLayoutIt;
- ++characterLayoutIt )
- {
- TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
+ characterLayout.mGlyphActor = textActor;
+ }
- if( characterLayoutInfo.mIsColorGlyph )
- {
- ImageActor imageActor = ImageActor::DownCast( characterLayoutInfo.mGlyphActor );
+ // Update the current text-actor.
+ currentTextActorInfo.textActor = textActor;
+}
- if( characterLayoutInfo.mSetText )
- {
- GlyphImage image = GlyphImage::New( characterLayoutInfo.mStyledText.mText[0] );
+/**
+ * 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] 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 lines.
+ * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles.
+ */
+void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualParameters,
+ TextView::RelayoutData& relayoutData,
+ TextViewProcessor::ParagraphLayoutInfo& paragraphLayout,
+ std::size_t& characterGlobalIndex,
+ std::size_t& lineLayoutInfoIndex,
+ bool createGlyphActors )
+{
+ CurrentTextActorInfo currentTextActorInfo;
+ currentTextActorInfo.characterLayout = NULL;
- if( image )
- {
- imageActor.SetImage( image );
- }
- characterLayoutInfo.mSetText = false;
- }
+ const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines.
+ bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last line.
+ bool textActorCreated = false; // Whether a text actor has been created for this the current group of characters traversed.
- imageActor.SetPosition( Vector3( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x,
- characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y,
- characterLayoutInfo.mPosition.z ) );
- imageActor.SetSize( characterLayoutInfo.mSize );
+ TextStyle currentStyle; // style for the current text-actor.
- // Sets the sort modifier value.
- imageActor.SetSortModifier( visualParameters.mSortModifier );
- }
- else
- {
- TextActor textActor = TextActor::DownCast( characterLayoutInfo.mGlyphActor );
- if( textActor )
- {
- // There is a new text-actor. Set text and everything to the previous one.
- if( currentTextActorInfo.textActor )
- {
- currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
- currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
- currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
+ 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.
- SetVisualParameters( currentTextActorInfo,
- visualParameters,
- relayoutData,
- lineLayoutInfo.mSize.height );
- }
+ bool currentIsColorGlyph = false; // Whether current glyph is an emoticon.
- currentTextActorInfo.text = characterLayoutInfo.mStyledText.mText;
- currentTextActorInfo.position = Vector3( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x,
- characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y,
- characterLayoutInfo.mPosition.z );
- currentTextActorInfo.size = characterLayoutInfo.mSize * relayoutData.mShrinkFactor;
+ std::vector<TextActor> textActorsToRemove; // Keep a vector of text-actors to be included into the cache.
- currentTextActorInfo.color = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
- currentTextActorInfo.color.a = characterLayoutInfo.mColorAlpha;
+ // 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;
- currentTextActorInfo.gradientColor = characterLayoutInfo.mGradientColor;
- currentTextActorInfo.startPoint = characterLayoutInfo.mStartPoint;
- currentTextActorInfo.endPoint = characterLayoutInfo.mEndPoint;
+ 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;
- // Update the current text-actor.
- currentTextActorInfo.textActor = textActor;
- }
- else
- {
- // If this character layout has no text-actor is because this character has the same style than previous one.
- // Add the character to the current text-actor and update the size.
- if( characterLayoutInfo.mIsVisible && ( TextViewProcessor::LineSeparator != wordLayoutInfo.mType ) )
- {
- currentTextActorInfo.text.Append( characterLayoutInfo.mStyledText.mText );
+ // 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.
+ createGlyphActors = createGlyphActors || ( ( isRightToLeftLayout ) ? paragraphLayout.mRightToLeftLayout->mPreviousLayoutCleared : false );
- currentTextActorInfo.position.y = std::min( currentTextActorInfo.position.y, ( characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y ) );
- currentTextActorInfo.size.width += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor;
- currentTextActorInfo.size.height = std::max( currentTextActorInfo.size.height, characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor );
- }
- }
+ 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& wordLayout( *wordIt );
+
+ for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = wordLayout.mCharactersLayoutInfo.begin(), characterEndIt = wordLayout.mCharactersLayoutInfo.end();
+ characterIt != characterEndIt;
+ ++characterIt )
+ {
+ TextViewProcessor::CharacterLayoutInfo& characterLayout( *characterIt );
+
+ // 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.
+ }
+ textActorCreated = false;
+ }
+
+ // Do not create a glyph-actor if there is no text.
+ const Character character = text[characterParagraphIndex];
+ const TextStyle& style = *( *( textStyles.Begin() + characterParagraphIndex ) );
+
+ // 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;
+ }
+
+ if( ( createGlyphActors && !textActorCreated ) ||
+ characterLayout.mIsColorGlyph ||
+ differentGradientInfo ||
+ ( characterLayout.mIsColorGlyph != currentIsColorGlyph ) ||
+ ( style != currentStyle ) )
+ {
+ characterLayout.mSetText = false;
+ characterLayout.mSetStyle = false;
+
+ if( characterLayout.mIsColorGlyph )
+ {
+ CreateEmoticon( visualParameters,
+ characterLayout,
+ character );
+
+ characterLayout.mGlyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ characterLayout.mGlyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT );
+ }
+ else
+ {
+ // There is a new style or a new line.
+
+ CreateTextActor( visualParameters,
+ relayoutData,
+ paragraphLayout,
+ wordLayout,
+ characterLayout,
+ character,
+ style,
+ currentTextActorInfo,
+ createGlyphActors,
+ textActorCreated );
+
+ if( textActorCreated )
+ {
+ characterLayout.mGlyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ characterLayout.mGlyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT );
}
- } // end characters
- } // end words
+ }
- if( !currentTextActorInfo.text.IsEmpty() )
+ // Update style to be checked with next characters.
+ currentStyle = style;
+ currentGradientInfo = characterLayout.mGradientInfo;
+ currentIsColorGlyph = characterLayout.mIsColorGlyph;
+ }
+ else
{
- if( currentTextActorInfo.textActor )
+ DALI_ASSERT_DEBUG( !characterLayout.mIsColorGlyph && "TextViewProcessor::InitializeTextActorInfo. An image-actor doesn't store more than one emoticon." );
+
+ // Same style than previous one.
+
+ // Add the character to the current text-actor and update the size.
+ if( characterLayout.mIsVisible && ( TextViewProcessor::ParagraphSeparator != wordLayout.mType ) )
{
- currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
- currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
- currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
+ currentTextActorInfo.text.Append( character );
- SetVisualParameters( currentTextActorInfo,
- visualParameters,
- relayoutData,
- lineLayoutInfo.mSize.height );
+ currentTextActorInfo.position.y = std::min( currentTextActorInfo.position.y, ( characterLayout.mPosition.y + characterLayout.mOffset.y ) );
+ currentTextActorInfo.size.width += characterLayout.mSize.width * relayoutData.mShrinkFactor;
+ currentTextActorInfo.size.height = std::max( currentTextActorInfo.size.height, characterLayout.mSize.height * relayoutData.mShrinkFactor );
}
}
- } //end groups of words
- } // end lines
+ if( ( createGlyphActors ) &&
+ !characterLayout.mIsColorGlyph &&
+ !textActorCreated )
+ {
+ TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor );
+ if( textActor )
+ {
+ // There is a previously created text-actor for this character.
+ // If this character has another one put it into the cache.
+ textActor.SetText( "" );
+ textActorsToRemove.push_back( textActor );
+ }
+
+ if( characterLayout.mGlyphActor )
+ {
+ characterLayout.mGlyphActor.Reset();
+ }
+ }
+ ++characterGlobalIndex;
+ ++characterParagraphIndex;
+ } // characters
+ } // words
+
+ if( !currentTextActorInfo.text.IsEmpty() )
+ {
+ if( currentTextActorInfo.textActor )
+ {
+ 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,
+ paragraphLayout.mSize.height );
+ }
+ }
+
+ // Insert the spare text-actors into the cache.
+ relayoutData.mTextActorCache.InsertTextActors( textActorsToRemove );
+}
+
+void UpdateTextActorInfo( const TextView::VisualParameters& visualParameters,
+ TextView::RelayoutData& relayoutData,
+ bool createGlyphActors )
+{
+ if( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() )
+ {
+ // 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 line info.
+
+ for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end();
+ paragraphIt != paragraphEndIt;
+ ++paragraphIt )
+ {
+ TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt );
+
+ UpdateTextActorInfoForParagraph( visualParameters,
+ relayoutData,
+ paragraph,
+ characterGlobalIndex,
+ lineLayoutInfoIndex,
+ createGlyphActors );
+ } // paragraphs
+
+ // Set visual parameters for ellipsis renderable actors.
for( std::vector<RenderableActor>::iterator it = relayoutData.mEllipsizedGlyphActors.begin(),
endIt = relayoutData.mEllipsizedGlyphActors.end();
it != endIt;
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 );
- for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupIt = line.mWordGroupsLayoutInfo.begin(), groupEndIt = line.mWordGroupsLayoutInfo.end();
- groupIt != groupEndIt;
- ++groupIt )
+ 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 )
{
- TextViewProcessor::WordGroupLayoutInfo& group( *groupIt );
+ TextViewProcessor::WordLayoutInfo& word( *wordIt );
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = group.mWordsLayoutInfo.begin(), wordEndIt = group.mWordsLayoutInfo.end();
- wordIt != wordEndIt;
- ++wordIt )
+ for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
+ characterIt != characterEndIt;
+ ++characterIt, ++characterIndex )
{
- TextViewProcessor::WordLayoutInfo& word( *wordIt );
+ TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
+ const TextStyle& style = *( *( paragraph.mTextStyles.Begin() + characterIndex ) );
- for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
- characterIt != characterEndIt;
- ++characterIt )
+ // 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 )
{
- TextViewProcessor::CharacterLayoutInfo& characterGroup( *characterIt );
+ ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
+ }
- // Check if current character is the first of a new laid-out line
- const bool isNewLine = ( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() ) &&
- ( textUnderlineStatus.mCharacterGlobalIndex == ( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) ).mCharacterGlobalIndex );
- if( isNewLine )
+ 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.
{
- ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
- }
+ // Create a new underline info for the current underlined characters.
+ UnderlineInfo underlineInfo;
+ underlineInfo.mMaxHeight = character.mSize.height;
+ underlineInfo.mMaxThickness = character.mUnderlineThickness;
+ underlineInfo.mPosition = character.mUnderlinePosition;
+
+ textUnderlineStatus.mUnderlineInfo.push_back( underlineInfo );
- if( characterGroup.mStyledText.mStyle.IsUnderlineEnabled() )
+ textUnderlineStatus.mCurrentUnderlineStatus = true; // Set the current text is underlined.
+ }
+ else
{
- 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.
- {
- // Create a new underline info for the current underlined characters.
- UnderlineInfo underlineInfo;
- underlineInfo.mMaxHeight = characterGroup.mSize.height;
- underlineInfo.mMaxThickness = characterGroup.mUnderlineThickness;
- underlineInfo.mPosition = characterGroup.mUnderlinePosition;
+ // Retrieve last underline info and update it if current underline thickness is bigger.
+ UnderlineInfo& underlineInfo( *( textUnderlineStatus.mUnderlineInfo.end() - 1u ) );
- textUnderlineStatus.mUnderlineInfo.push_back( underlineInfo );
+ underlineInfo.mMaxHeight = std::max( underlineInfo.mMaxHeight, character.mSize.height );
- textUnderlineStatus.mCurrentUnderlineStatus = true; // Set the current text is underlined.
- }
- else
+ if( character.mUnderlineThickness > underlineInfo.mMaxThickness )
{
- // Retrieve last underline info and update it if current underline thickness is bigger.
- UnderlineInfo& underlineInfo( *( textUnderlineStatus.mUnderlineInfo.end() - 1 ) );
-
- underlineInfo.mMaxHeight = std::max( underlineInfo.mMaxHeight, characterGroup.mSize.height );
-
- if( characterGroup.mUnderlineThickness > underlineInfo.mMaxThickness )
- {
- underlineInfo.mMaxThickness = characterGroup.mUnderlineThickness;
- underlineInfo.mPosition = characterGroup.mUnderlinePosition;
- }
+ underlineInfo.mMaxThickness = character.mUnderlineThickness;
+ underlineInfo.mPosition = character.mUnderlinePosition;
}
}
- else
- {
- textUnderlineStatus.mCurrentUnderlineStatus = false;
- }
+ }
+ else
+ {
+ textUnderlineStatus.mCurrentUnderlineStatus = false;
+ }
- ++textUnderlineStatus.mCharacterGlobalIndex;
- } // end group of characters.
- } // end words.
- } // end group of words.
- } // end lines.
+ ++textUnderlineStatus.mCharacterGlobalIndex;
+ } // end characters.
+ } // end words.
+ } // end paragraphs.
}
void SetUnderlineInfo( TextView::RelayoutData& relayoutData )
{
- // Stores for each group of consecutive underlined text 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() )
// Whether current text is underlined.
textUnderlineStatus.mCurrentUnderlineStatus = false;
- textUnderlineStatus.mCharacterGlobalIndex = 0;
- textUnderlineStatus.mLineGlobalIndex = 0;
+ textUnderlineStatus.mCharacterGlobalIndex = 0u;
+ textUnderlineStatus.mLineGlobalIndex = 0u;
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::WordGroupLayoutInfoContainer::iterator groupIt = line.mWordGroupsLayoutInfo.begin(), groupEndIt = line.mWordGroupsLayoutInfo.end();
- groupIt != groupEndIt;
- ++groupIt )
+ for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end();
+ wordIt != wordEndIt;
+ ++wordIt )
{
- TextViewProcessor::WordGroupLayoutInfo& group( *groupIt );
+ TextViewProcessor::WordLayoutInfo& word( *wordIt );
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = group.mWordsLayoutInfo.begin(), wordEndIt = group.mWordsLayoutInfo.end();
- wordIt != wordEndIt;
- ++wordIt )
+ for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
+ characterIt != characterEndIt;
+ ++characterIt, ++characterIndex )
{
- TextViewProcessor::WordLayoutInfo& word( *wordIt );
+ TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
+ TextStyle& style = *( *( paragraph.mTextStyles.Begin() + characterIndex ) );
- for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
- characterIt != characterEndIt;
- ++characterIt )
- {
- TextViewProcessor::CharacterLayoutInfo& characterGroup( *characterIt );
+ // Check if current character is the first of a new line
- // Check if current character is the first of a new laid-out line
+ bool isNewLine = false;
- bool isNewLine = false;
+ if( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() )
+ {
+ const Toolkit::TextView::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) );
+ isNewLine = ( textUnderlineStatus.mCharacterGlobalIndex == lineLayoutInfo.mCharacterGlobalIndex );
- if( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() )
+ if( isNewLine )
{
- const Toolkit::TextView::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) );
- isNewLine = ( textUnderlineStatus.mCharacterGlobalIndex == lineLayoutInfo.mCharacterGlobalIndex );
-
- if( isNewLine )
- {
- currentLineHeight = lineLayoutInfo.mSize.height;
- currentLineAscender = lineLayoutInfo.mAscender;
- ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
- }
+ currentLineHeight = lineLayoutInfo.mSize.height;
+ currentLineAscender = lineLayoutInfo.mAscender;
+ ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
}
+ }
- if( characterGroup.mStyledText.mStyle.IsUnderlineEnabled() )
+ if( style.IsUnderlineEnabled() )
+ {
+ if( textUnderlineStatus.mCurrentUnderlineStatus )
{
- if( textUnderlineStatus.mCurrentUnderlineStatus )
+ if( isNewLine )
{
- if( isNewLine )
+ // Retrieves the thickness and position for the next piece of underlined text.
+ if( underlineInfoIt < underlineInfoEndIt )
{
- // Retrieves the thickness and position for the next piece of underlined text.
+ ++underlineInfoIt;
if( underlineInfoIt < underlineInfoEndIt )
{
- ++underlineInfoIt;
- if( underlineInfoIt < underlineInfoEndIt )
- {
- underlineInfo = *underlineInfoIt;
- }
+ underlineInfo = *underlineInfoIt;
}
}
}
+ }
- textUnderlineStatus.mCurrentUnderlineStatus = true;
+ textUnderlineStatus.mCurrentUnderlineStatus = true;
- // Before setting the position it needs to be adjusted to match the base line.
- const float bearingOffset = ( currentLineHeight - currentLineAscender ) - ( characterGroup.mSize.height - characterGroup.mAscender );
- const float positionOffset = ( underlineInfo.mMaxHeight - characterGroup.mSize.height ) - bearingOffset;
+ // Before setting the position it needs to be adjusted to match the base line.
+ const float bearingOffset = ( currentLineHeight - currentLineAscender ) - ( character.mSize.height - character.mAscender );
+ const float positionOffset = ( underlineInfo.mMaxHeight - character.mSize.height ) - bearingOffset;
- // Sets the underline's parameters.
- characterGroup.mStyledText.mStyle.SetUnderline( true, underlineInfo.mMaxThickness, underlineInfo.mPosition - positionOffset );
+ // Sets the underline's parameters.
+ style.SetUnderline( true, underlineInfo.mMaxThickness, underlineInfo.mPosition - positionOffset );
- // Mark the group of characters to be set the new style into the text-actor.
- characterGroup.mSetStyle = true;
- }
- else
+ // Mark the character to be set the new style into the text-actor.
+ character.mSetStyle = true;
+ }
+ else
+ {
+ if( textUnderlineStatus.mCurrentUnderlineStatus )
{
- if( textUnderlineStatus.mCurrentUnderlineStatus )
- {
- textUnderlineStatus.mCurrentUnderlineStatus = false;
+ textUnderlineStatus.mCurrentUnderlineStatus = false;
- // Retrieves the thickness and position for the next piece of underlined text.
+ // Retrieves the thickness and position for the next piece of underlined text.
+ if( underlineInfoIt < underlineInfoEndIt )
+ {
+ ++underlineInfoIt;
if( underlineInfoIt < underlineInfoEndIt )
{
- ++underlineInfoIt;
- if( underlineInfoIt < underlineInfoEndIt )
- {
- underlineInfo = *underlineInfoIt;
- }
+ underlineInfo = *underlineInfoIt;
}
}
}
+ }
- ++textUnderlineStatus.mCharacterGlobalIndex;
- } // end of group of characters.
- } // end of word.
- } // end of group of words.
- } // end of lines.
+ ++textUnderlineStatus.mCharacterGlobalIndex;
+ } // end of characters.
+ } // end of word.
+ } // end of paragraphs.
}
void RemoveGlyphActors( Actor textView,
}
}
-void InsertToTextView( const TextView::RelayoutOperationMask relayoutOperationMask,
- Actor textView,
+void InsertToTextView( Actor textView,
TextView::RelayoutData& relayoutData )
{
- const bool insertToTextView = relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW;
- const bool insertToTextActorList = relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST;
-
// 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 );
- for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(),
- endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end();
- groupLayoutIt != endGroupLayoutIt;
- ++groupLayoutIt )
+ // 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 )
{
- TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *groupLayoutIt );
+ TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
- for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.begin(),
- endWordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.end();
- wordLayoutIt != endWordLayoutIt;
- ++wordLayoutIt )
+ for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
+ endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
+ characterLayoutIt != endCharacterLayoutIt;
+ ++characterLayoutIt )
{
- TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
+ TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
- for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
- endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
- characterLayoutIt != endCharacterLayoutIt;
- ++characterLayoutIt )
+ if( characterLayoutInfo.mIsVisible && characterLayoutInfo.mGlyphActor ) // White spaces and '\n' characters doesn't have a text-actor.
{
- TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
-
- if( characterLayoutInfo.mIsVisible && characterLayoutInfo.mGlyphActor ) // White spaces and '\n' characters doesn't have a text-actor.
- {
- //Add to the text-view.
- if( insertToTextView )
- {
- textView.Add( characterLayoutInfo.mGlyphActor );
- }
- if( insertToTextActorList )
- {
- relayoutData.mGlyphActors.push_back( characterLayoutInfo.mGlyphActor );
- }
- }
- } // end group of character
- } // end words
- } // end group of words
- } // end lines
+ //Add to the text-view.
+ textView.Add( characterLayoutInfo.mGlyphActor );
+ relayoutData.mGlyphActors.push_back( characterLayoutInfo.mGlyphActor );
+ }
+ } // end character
+ } // end words
+ } // end paragraphs
for( std::vector<RenderableActor>::iterator it = relayoutData.mEllipsizedGlyphActors.begin(),
endIt = relayoutData.mEllipsizedGlyphActors.end();
RenderableActor glyphActor = ( *it );
//Add to the text-view.
- if( insertToTextView )
- {
- textView.Add( glyphActor );
- }
- if( insertToTextActorList )
- {
- relayoutData.mGlyphActors.push_back( glyphActor );
- }
+ textView.Add( glyphActor );
+ relayoutData.mGlyphActors.push_back( glyphActor );
}
relayoutData.mEllipsizedGlyphActors.clear();
}