X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=base%2Fdali-toolkit%2Finternal%2Fcontrols%2Ftext-view%2Frelayout-utilities.cpp;h=84fd94323ca5178641fbafd70a0d3ccfb87a64a4;hb=refs%2Fchanges%2F61%2F27361%2F4;hp=87f098401f09c562877b0b3f8e7a7e02a47c2954;hpb=542f7db49eb2cf604ad0a0baf15348a18b5bd0b4;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp b/base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp index 87f0984..84fd943 100644 --- a/base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp +++ b/base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp @@ -16,19 +16,14 @@ */ // FILE HEADER -#include "relayout-utilities.h" +#include + +// INTERNAL INCLUDES +#include // EXTERNAL INCLUDES #include -// INTERNAL INCLUDES -#include -#include -#include "text-view-line-processor.h" -#include "text-view-word-processor.h" -#include "text-view-processor-helper-functions.h" -#include "text-view-processor-dbg.h" - namespace Dali { @@ -259,101 +254,88 @@ void CalculateSubLineLayout( const float parentWidth, 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 = lineLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex, + wordEndIt = lineLayoutInfo.mWordsLayoutInfo.end(); + ( wordIt != wordEndIt ) && !found; + ++wordIt ) { - const TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *wordGroupIt ); + const TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordIt ); - for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = wordGroupLayoutInfo.mWordsLayoutInfo.begin() + wordIndex, - wordEndIt = wordGroupLayoutInfo.mWordsLayoutInfo.end(); - ( wordIt != wordEndIt ) && !found; - ++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 WrapByLine: // Fall through + { + splitByCharacter = false; + break; + } + case WrapByWordAndSplit: + { + splitByCharacter = ( shrunkWordWidth > parentWidth ); + break; + } + case WrapByLineAndSplit: { - 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; @@ -530,10 +512,10 @@ void UpdateAlignment( const TextView::LayoutParameters& layoutParameters, const float textHorizontalOffset = CalculateXoffset( layoutParameters.mHorizontalAlignment, relayoutData.mTextViewSize.width, relayoutData.mTextSizeForRelayoutOption.width ); const float textVerticalOffset = CalculateYoffset( layoutParameters.mVerticalAlignment, relayoutData.mTextViewSize.height, relayoutData.mTextSizeForRelayoutOption.height ); - std::size_t lineJustificationIndex = 0; // Index to the first position of the vector which stores all line justification info. - std::size_t infoTableCharacterIndex = 0; + std::size_t lineJustificationIndex = 0u; // Index to the first position of the vector which stores all line justification info. + std::size_t infoTableCharacterIndex = 0u; - relayoutParameters.mIndices.mLineIndex = 0; + relayoutParameters.mIndices.mLineIndex = 0u; for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end(); @@ -542,64 +524,55 @@ void UpdateAlignment( const TextView::LayoutParameters& layoutParameters, { TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt ); - 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 ) + relayoutParameters.mIndices.mWordIndex = 0u; + + for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(), + endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.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, ++infoTableCharacterIndex ) { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); + TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - relayoutParameters.mIndices.mCharacterIndex = 0; - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex ) + // Calculate line justification offset. + if( lineJustificationIndex < relayoutData.mLineJustificationInfo.size() ) { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); + const TextView::LineJustificationInfo lineJustificationInfo( *( relayoutData.mLineJustificationInfo.begin() + lineJustificationIndex ) ); - // Calculate line justification offset. - if( lineJustificationIndex < relayoutData.mLineJustificationInfo.size() ) + if( relayoutParameters.mIndices == lineJustificationInfo.mIndices ) { - const TextView::LineJustificationInfo lineJustificationInfo( *( relayoutData.mLineJustificationInfo.begin() + lineJustificationIndex ) ); - - 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. - } + justificationOffset = CalculateJustificationOffset( layoutParameters.mLineJustification, relayoutData.mTextSizeForRelayoutOption.width, lineJustificationInfo.mLineLength ); + ++lineJustificationIndex; // increase the index to point the next position in the 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::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex; - Toolkit::TextView::CharacterLayoutInfo& characterTableInfo( *infoTableIt ); + std::vector::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex; + 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 + positionOffset.x += characterLayoutInfo.mAdvance * relayoutData.mShrinkFactor; + } // end characters + } // end words } // end lines } @@ -644,14 +617,13 @@ void CalculateBearing( TextViewProcessor::CharacterLayoutInfo& characterLayoutIn // 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, @@ -673,7 +645,7 @@ void UpdateLayoutInfoTable( Vector4& minMaxXY, characterLayoutInfo.mHeight * relayoutData.mShrinkFactor ), positionOffset, ( TextViewProcessor::LineSeparator == wordLayoutInfo.mType ), - ( TextViewProcessor::RTL == wordGroupLayoutInfo.mDirection ), + false, // VCC set the correct direction if needed. true, descender ); @@ -1096,7 +1068,6 @@ void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters, ellipsizeText.Append( ellipsizeCharacterLayoutInfo.mStyledText.mText ); TextViewProcessor::UpdateSize( ellipsizeSize, ellipsizeCharacterLayoutInfo.mSize ); } - } if( !ellipsizeText.IsEmpty() ) @@ -1136,7 +1107,7 @@ void EllipsizeLine( const TextView::LayoutParameters& layoutParameters, 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; + endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin() + lastIndices.mLineIndex + 1u; lineLayoutIt != endLineLayoutIt; ++lineLayoutIt ) { @@ -1149,82 +1120,62 @@ void EllipsizeLine( const TextView::LayoutParameters& layoutParameters, 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; + + for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin() + firstIndices.mWordIndex, + endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.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 ); - - if( lastGroup && ( wordCount == lastIndices.mWordIndex - firstWordIndex ) ) - { - lastWord = true; - } + TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - 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 ) + if( ellipsizeParameters.mEllipsizeLine ) { - 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 characters + firstWord = false; + } // end words } // end lines } @@ -1237,35 +1188,27 @@ void SetTextVisible( TextView::RelayoutData& relayoutData ) { TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt ); - for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(), - endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end(); - groupLayoutIt != endGroupLayoutIt; - ++groupLayoutIt ) + for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(), + endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.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 ); - - 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 + 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 lines // Updates the visibility for text-input.. @@ -1289,19 +1232,19 @@ void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters // 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( 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( 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( 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( 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; @@ -1311,11 +1254,11 @@ void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters 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.mLineIndex = 0u; for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end(); @@ -1324,56 +1267,46 @@ void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters { TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt ); - relayoutParameters.mIndices.mGroupIndex = 0; + relayoutParameters.mIndices.mWordIndex = 0u; - for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(), - endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end(); - groupLayoutIt != endGroupLayoutIt; - ++groupLayoutIt, ++relayoutParameters.mIndices.mGroupIndex ) + for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(), + endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.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 ) { - 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, + relayoutParameters, + fadeParameters, + relayoutData ); - // Updates the visibility for text-input.. - std::vector::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex; + // Updates the visibility for text-input.. + std::vector::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + 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 + relayoutParameters.mIsFirstCharacterOfWord = false; + } // end character + } // end words } // end lines } @@ -1400,15 +1333,15 @@ void UpdateVisibilityForEllipsize( const TextView::LayoutParameters& layoutParam // 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. @@ -1452,7 +1385,7 @@ void UpdateVisibilityForEllipsize( const TextView::LayoutParameters& layoutParam { // 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 @@ -1526,130 +1459,330 @@ void UpdateVisibility( const TextView::LayoutParameters& layoutParameters, } } -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(); - // 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 ) + GlyphImage image = GlyphImage::New( character ); + + if( image ) + { + imageActor.SetImage( image ); + } + } + + 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] line Layout info for the line. + * @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. + */ +void CreateTextActor( const TextView::VisualParameters& visualParameters, + TextView::RelayoutData& relayoutData, + const TextViewProcessor::LineLayoutInfo& line, + TextViewProcessor::CharacterLayoutInfo& characterLayout, + const Character& character, + const TextStyle& style, + CurrentTextActorInfo& currentTextActorInfo, + bool createGlyphActors ) +{ + // Set the text-actor for the current traversed text. + if( currentTextActorInfo.textActor ) { - TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt ); + currentTextActorInfo.textActor.SetText( currentTextActorInfo.text ); + currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position ); + currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size ); + + SetVisualParameters( currentTextActorInfo, + visualParameters, + relayoutData, + line.mSize.height ); + } + + currentTextActorInfo.text = Text( character ); + currentTextActorInfo.position = Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x, + characterLayout.mPosition.y + characterLayout.mOffset.y, + characterLayout.mPosition.z ); + currentTextActorInfo.size = characterLayout.mSize * relayoutData.mShrinkFactor; - for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(), - endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end(); - groupLayoutIt != endGroupLayoutIt; - ++groupLayoutIt ) + currentTextActorInfo.color = style.GetTextColor(); + currentTextActorInfo.color.a = characterLayout.mColorAlpha; + + currentTextActorInfo.gradientColor = characterLayout.mGradientColor; + currentTextActorInfo.startPoint = characterLayout.mStartPoint; + currentTextActorInfo.endPoint = characterLayout.mEndPoint; + + TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); + + if( createGlyphActors ) + { + 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 ) + { + TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_OFF ); + textActor = TextActor::New( Text(), parameters ); + } + else { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); + textActor.SetTextStyle( style ); + } + } + characterLayout.mGlyphActor = textActor; + } + + // Update the current text-actor. + currentTextActorInfo.textActor = textActor; +} + +/** + * Traverses the whole line initializating renderable-actor handles and updating them with the new size and position. + * + * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). + * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. + * @param[in,out] line Layout info for the line. + * @param[in,out] characterGlobalIndex Index to the character within the whole text. + * @param[in,out] lineLayoutInfoIndex Index to the table of laid out lines. + * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles. + */ +void UpdateTextActorInfoForLine( const TextView::VisualParameters& visualParameters, + TextView::RelayoutData& relayoutData, + TextViewProcessor::LineLayoutInfo& line, + std::size_t& characterGlobalIndex, + std::size_t& lineLayoutInfoIndex, + bool createGlyphActors ) +{ + CurrentTextActorInfo currentTextActorInfo; + + const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of laid out lines. + bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last laid out line. + bool glyphActorCreatedForLine = false; // Whether a renderable actor has been created for this line. + + TextStyle currentStyle; // style for the current text-actor. + + Vector4 currentGradientColor; // gradient color for the current text-actor. + Vector2 currentStartPoint; // start point for the current text-actor. + Vector2 currentEndPoint; // end point for the current text-actor. + + bool currentIsColorGlyph = false; // Whether current glyph is an emoticon. + + std::vector textActorsToRemove; // Keep a vector of text-actors to be included into the cache. + + std::size_t characterLineIndex = 0u; // Index to the character (within the line). + for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = line.mWordsLayoutInfo.begin(), wordEndIt = line.mWordsLayoutInfo.end(); + wordIt != wordEndIt; + ++wordIt ) + { + TextViewProcessor::WordLayoutInfo& word( *wordIt ); + + for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.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 ); - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt ) + if( newLine ) + { + // Point to the next line. + ++lineLayoutInfoIndex; + if( lineLayoutInfoIndex >= lineLayoutInfoSize ) { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); + // Arrived at last line. + lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector. + } + glyphActorCreatedForLine = false; + } - if( characterLayoutInfo.mIsColorGlyph ) - { - ImageActor imageActor = ImageActor::DownCast( characterLayoutInfo.mGlyphActor ); + // Do not create a glyph-actor if there is no text. + const Character character = characterLayout.mStyledText.mText[0u]; // there are only one character per character layout. + const TextStyle& style = characterLayout.mStyledText.mStyle; - if( characterLayoutInfo.mSetText ) - { - GlyphImage image = GlyphImage::New( characterLayoutInfo.mStyledText.mText[0] ); + bool appendCharacter = false; - if( image ) - { - imageActor.SetImage( image ); - } - characterLayoutInfo.mSetText = false; - } + if( characterLayout.mIsColorGlyph || + !character.IsWhiteSpace() || // A new line character is also a white space. + ( character.IsWhiteSpace() && style.IsUnderlineEnabled() ) ) + { + // Do not create a glyph-actor if it's a white space (without underline) or a new line character. + + // Creates one glyph-actor for each counsecutive group of characters, with the same style, per line, or if it's an emoticon. + + if( !glyphActorCreatedForLine || + characterLayout.mIsColorGlyph || + ( characterLayout.mIsColorGlyph != currentIsColorGlyph ) || + ( style != currentStyle ) || + ( characterLayout.mGradientColor != currentGradientColor ) || + ( characterLayout.mStartPoint != currentStartPoint ) || + ( characterLayout.mEndPoint != currentEndPoint ) ) + { + characterLayout.mSetText = false; + characterLayout.mSetStyle = false; - imageActor.SetPosition( Vector3( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x, - characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y, - characterLayoutInfo.mPosition.z ) ); - imageActor.SetSize( characterLayoutInfo.mSize ); + // There is a new style or a new line. + glyphActorCreatedForLine = true; - // Sets the sort modifier value. - imageActor.SetSortModifier( visualParameters.mSortModifier ); + if( characterLayout.mIsColorGlyph ) + { + CreateEmoticon( visualParameters, + characterLayout, + character ); } 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 ); - - SetVisualParameters( currentTextActorInfo, - visualParameters, - relayoutData, - lineLayoutInfo.mSize.height ); - } + CreateTextActor( visualParameters, + relayoutData, + line, + characterLayout, + character, + style, + currentTextActorInfo, + createGlyphActors ); + } - 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; + // Update style to be checked with next characters. + currentStyle = style; + currentGradientColor = characterLayout.mGradientColor; + currentStartPoint = characterLayout.mStartPoint; + currentEndPoint = characterLayout.mEndPoint; + currentIsColorGlyph = characterLayout.mIsColorGlyph; - currentTextActorInfo.color = characterLayoutInfo.mStyledText.mStyle.GetTextColor(); - currentTextActorInfo.color.a = characterLayoutInfo.mColorAlpha; + characterLayout.mGlyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + characterLayout.mGlyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT ); + } + else + { + DALI_ASSERT_DEBUG( !characterLayout.mIsColorGlyph && "TextViewProcessor::InitializeTextActorInfo. An image-actor doesn't store more than one emoticon." ); - currentTextActorInfo.gradientColor = characterLayoutInfo.mGradientColor; - currentTextActorInfo.startPoint = characterLayoutInfo.mStartPoint; - currentTextActorInfo.endPoint = characterLayoutInfo.mEndPoint; + // Same style than previous one. - // 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 ); + // Add the character to the current text-actor and update the size. + appendCharacter = true; - 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 ); - } - } + 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(); } - } // end characters - } // end words + } + } // no white space / new line char + else + { + appendCharacter = true; + } - if( !currentTextActorInfo.text.IsEmpty() ) + if( appendCharacter ) { - if( currentTextActorInfo.textActor ) + // Add the character to the current text-actor and update the size. + if( characterLayout.mIsVisible && ( TextViewProcessor::LineSeparator != word.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 + + ++characterGlobalIndex; + ++characterLineIndex; + } // characters + } // words + + if( !currentTextActorInfo.text.IsEmpty() ) + { + if( currentTextActorInfo.textActor ) + { + currentTextActorInfo.textActor.SetText( currentTextActorInfo.text ); + currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position ); + currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size ); + + SetVisualParameters( currentTextActorInfo, + visualParameters, + relayoutData, + line.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.mLinesLayoutInfo.empty() ) + { + // nothing to do if there is no lines. + return; + } + + std::size_t characterGlobalIndex = 0u; // Index to the global character (within the whole text). + std::size_t lineLayoutInfoIndex = 0u; // Index to the laid out line info. + + for( TextViewProcessor::LineLayoutInfoContainer::iterator lineIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), lineEndIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end(); + lineIt != lineEndIt; + ++lineIt ) + { + TextViewProcessor::LineLayoutInfo& line( *lineIt ); + + UpdateTextActorInfoForLine( visualParameters, + relayoutData, + line, + characterGlobalIndex, + lineLayoutInfoIndex, + createGlyphActors ); + } // lines for( std::vector::iterator it = relayoutData.mEllipsizedGlyphActors.begin(), endIt = relayoutData.mEllipsizedGlyphActors.end(); @@ -1682,76 +1815,69 @@ void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelay { TextViewProcessor::LineLayoutInfo& line( *lineIt ); - for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupIt = line.mWordGroupsLayoutInfo.begin(), groupEndIt = line.mWordGroupsLayoutInfo.end(); - groupIt != groupEndIt; - ++groupIt ) + for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = line.mWordsLayoutInfo.begin(), wordEndIt = line.mWordsLayoutInfo.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 ) { - TextViewProcessor::WordLayoutInfo& word( *wordIt ); + TextViewProcessor::CharacterLayoutInfo& character( *characterIt ); - 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 laid-out 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( character.mStyledText.mStyle.IsUnderlineEnabled() ) + { + if( !textUnderlineStatus.mCurrentUnderlineStatus || // Current character is underlined but previous one it wasn't. + isNewLine ) // Current character is underlined and is the first of current laid-out line. { - ++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. + ++textUnderlineStatus.mCharacterGlobalIndex; + } // end characters. + } // end words. } // end lines. } 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 laid-out 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. @@ -1778,8 +1904,8 @@ void SetUnderlineInfo( TextView::RelayoutData& relayoutData ) // 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; @@ -1790,93 +1916,86 @@ void SetUnderlineInfo( TextView::RelayoutData& relayoutData ) { TextViewProcessor::LineLayoutInfo& line( *lineIt ); - for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupIt = line.mWordGroupsLayoutInfo.begin(), groupEndIt = line.mWordGroupsLayoutInfo.end(); - groupIt != groupEndIt; - ++groupIt ) + for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = line.mWordsLayoutInfo.begin(), wordEndIt = line.mWordsLayoutInfo.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 ) { - TextViewProcessor::WordLayoutInfo& word( *wordIt ); + TextViewProcessor::CharacterLayoutInfo& character( *characterIt ); - 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 laid-out 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( character.mStyledText.mStyle.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. + character.mStyledText.mStyle.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. + ++textUnderlineStatus.mCharacterGlobalIndex; + } // end of characters. + } // end of word. } // end of lines. } @@ -1895,13 +2014,9 @@ 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(), @@ -1911,42 +2026,28 @@ void InsertToTextView( const TextView::RelayoutOperationMask relayoutOperationMa { TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt ); - for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(), - endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end(); - groupLayoutIt != endGroupLayoutIt; - ++groupLayoutIt ) + for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(), + endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.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 + //Add to the text-view. + textView.Add( characterLayoutInfo.mGlyphActor ); + relayoutData.mGlyphActors.push_back( characterLayoutInfo.mGlyphActor ); + } + } // end character + } // end words } // end lines for( std::vector::iterator it = relayoutData.mEllipsizedGlyphActors.begin(), @@ -1957,14 +2058,8 @@ void InsertToTextView( const TextView::RelayoutOperationMask relayoutOperationMa 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(); } @@ -1982,7 +2077,8 @@ RenderableActor CreateGlyphActor( const Text& text, const TextStyle& style, Text else { // The text-actor cache is empty. Create a new one. - textActor = TextActor::New( text, style, false, true ); + TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_OFF ); + textActor = TextActor::New( text, parameters ); } return textActor;