2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
22 #include <dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h>
36 namespace TextViewRelayout
39 const float MINIMUM_FADE_BOUNDARY = 0.05f; // When the fade boundary is the same as the text-view boundary, this constant reduces it in order to avoid a zero division.
41 RelayoutParameters::RelayoutParameters()
47 mCharacterGlobalIndex( 0u ),
48 mIsFirstCharacter( false ),
49 mIsFirstCharacterOfWord( false ),
51 mIsNewParagraphCharacter( false ),
52 mIsWhiteSpace( false ),
57 RelayoutParameters::~RelayoutParameters()
61 FadeParameters::FadeParameters()
62 : mRightFadeBoundary( 0.f ),
63 mRightFadeThreshold( 0.f ),
64 mRightFadeBoundaryOffset( 0.f ),
65 mRightFadeThresholdOffset( 0.f ),
66 mRightAlphaCoeficients(),
67 mLeftFadeBoundary( 0.f ),
68 mLeftFadeThreshold( 0.f ),
69 mLeftFadeBoundaryOffset( 0.f ),
70 mLeftFadeThresholdOffset( 0.f ),
71 mLeftAlphaCoeficients(),
72 mTopFadeBoundary( 0.f ),
73 mTopFadeThreshold( 0.f ),
74 mTopFadeBoundaryOffset( 0.f ),
75 mTopFadeThresholdOffset( 0.f ),
76 mTopAlphaCoeficients(),
77 mBottomFadeBoundary( 0.f ),
78 mBottomFadeThreshold( 0.f ),
79 mBottomFadeBoundaryOffset( 0.f ),
80 mBottomFadeThresholdOffset( 0.f ),
81 mBottomAlphaCoeficients(),
82 mIsPartiallyVisible( false )
86 FadeParameters::~FadeParameters()
90 EllipsizeParameters::EllipsizeParameters()
92 mLineDescender( 0.f ),
97 mEllipsizeLine( false ),
98 mIsLineWidthFullyVisible( false ),
99 mIsLineHeightFullyVisible( false ),
100 mIsNextLineFullyVisibleHeight( false ),
101 mCreateEllipsizedTextActors( false ),
107 EllipsizeParameters::~EllipsizeParameters()
111 UnderlineInfo::UnderlineInfo()
113 mMaxThickness( 0.f ),
118 UnderlineInfo::~UnderlineInfo()
122 TextUnderlineStatus::TextUnderlineStatus()
124 mCharacterGlobalIndex( 0u ),
125 mLineGlobalIndex( 0u ),
126 mCurrentUnderlineStatus( false )
130 TextUnderlineStatus::~TextUnderlineStatus()
134 LineLayoutInfo::LineLayoutInfo()
135 : mLineLength( 0.f ),
136 mMaxCharHeight( 0.f ),
141 LineLayoutInfo::~LineLayoutInfo()
146 * Whether the given text-actor exceeds the left or the right boundary of the text-view.
148 * @param[in] position The position of the text-actor.
149 * @param[in] size The size of the text-actor.
150 * @param[in] parantSize The size of the text-view.
152 * @return \e true if the text-actor exceeds the left or the right boundary of the text-view.
154 bool IsExceedingWidth( const Vector3& position, const Size& size, const Size& parentSize )
156 return ( ( position.x < 0.f ) ||
157 ( position.x + size.width > parentSize.width ) );
161 * Whether the given text-actor exceeds the top or the bottom boundary of the text-view.
163 * @param[in] position The position of the text-actor.
164 * @param[in] size The size of the text-actor.
165 * @param[in] parantSize The size of the text-view.
167 * @return \e true if the text-actor exceeds the top or the bottom boundary of the text-view.
169 bool IsExceedingHeight( const Vector3& position, const Size& size, const Size& parentSize )
171 return ( ( position.y > parentSize.height ) ||
172 ( position.y < size.height ) );
176 * Calculates the line length adding the new word or character width.
178 * It also returns the length of white spaces if they are at the end of the line.
180 * @param[in] isWhiteSpace Whether the word is a white space.
181 * @param[in] width The width of the character or word.
182 * @param[in] parentWidth The parent width.
183 * @param[out] found Whether the sum of the new character or word is exceding the parent's width.
184 * @param[out] lineLength The length of the portion of line which doesn't exceed the parant's width
185 * @param[out] endWhiteSpaceLength The length of white spaces which are at the end of the line.
187 void CalculateLineLength( bool isWhiteSpace, float width, float parentWidth, bool& found, float& lineLength, float& endWhiteSpaceLength )
189 if( lineLength + width > parentWidth )
192 lineLength -= endWhiteSpaceLength;
200 endWhiteSpaceLength += width;
204 endWhiteSpaceLength = 0.f;
209 struct CurrentTextActorInfo
216 TextViewProcessor::GradientInfo* gradientInfo;
219 void SetVisualParameters( CurrentTextActorInfo& currentTextActorInfo,
220 const TextView::VisualParameters& visualParameters,
221 TextView::RelayoutData& relayoutData,
222 const float lineHeight )
224 currentTextActorInfo.textActor.SetTextColor( currentTextActorInfo.color );
225 if( NULL != currentTextActorInfo.gradientInfo )
227 currentTextActorInfo.textActor.SetGradientColor( currentTextActorInfo.gradientInfo->mGradientColor );
228 currentTextActorInfo.textActor.SetGradientStartPoint( currentTextActorInfo.gradientInfo->mStartPoint );
229 currentTextActorInfo.textActor.SetGradientEndPoint( currentTextActorInfo.gradientInfo->mEndPoint );
232 // The italics offset is used in the offscreen rendering. When text is in italics, it may exceed the text-view's boundary
233 // due to the trick used to implement it.
234 const Radian& italicsAngle = currentTextActorInfo.textActor.GetItalicsAngle();
235 const float italicsOffset = lineHeight * std::tan( italicsAngle );
236 relayoutData.mTextLayoutInfo.mMaxItalicsOffset = std::max( relayoutData.mTextLayoutInfo.mMaxItalicsOffset, italicsOffset );
238 // Sets the sort modifier value.
239 currentTextActorInfo.textActor.SetSortModifier( visualParameters.mSortModifier );
241 // Enables or disables the blending.
242 currentTextActorInfo.textActor.SetBlendMode( !visualParameters.mSnapshotModeEnabled ? BlendingMode::ON : BlendingMode::OFF );
245 void CalculateLineLayout( float parentWidth,
246 const TextViewProcessor::TextInfoIndices& indices,
247 const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo,
248 HorizontalWrapType splitPolicy,
250 LineLayoutInfo& subLineInfo )
252 subLineInfo.mLineLength = 0.f;
253 subLineInfo.mMaxCharHeight = 0.f;
254 subLineInfo.mMaxAscender = 0.f;
256 float endWhiteSpaceLength = 0.f;
258 std::size_t characterIndex = indices.mCharacterIndex;
259 float lineOffset = 0.f;
261 bool isFirstCharacter = true;
262 for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = paragraphLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex,
263 wordEndIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
264 ( wordIt != wordEndIt ) && !found;
267 const TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordIt );
269 const float shrunkWordWidth = wordLayoutInfo.mSize.width * shrinkFactor;
270 const bool isWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType;
272 bool splitByCharacter = false;
274 switch( splitPolicy )
276 case WrapByCharacter:
278 splitByCharacter = true;
282 case WrapByParagraphCharacter: // Fall through
284 splitByCharacter = false;
287 case WrapByWordAndSplit:
289 splitByCharacter = ( shrunkWordWidth > parentWidth );
292 case WrapByParagraphCharacterAndSplit:
294 if( ( 0u != characterIndex ) ||
295 ( ( 0u == characterIndex ) && ( lineOffset + shrunkWordWidth > parentWidth ) ) )
297 splitByCharacter = true;
301 lineOffset += shrunkWordWidth;
302 splitByCharacter = false;
307 if( splitByCharacter )
309 for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator charIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + characterIndex,
310 charEndIt = wordLayoutInfo.mCharactersLayoutInfo.end();
311 ( charIt != charEndIt ) && !found;
314 const TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *charIt );
315 CalculateLineLength( isWhiteSpace, characterLayoutInfo.mSize.width * shrinkFactor, parentWidth, found, subLineInfo.mLineLength, endWhiteSpaceLength );
316 if( !found || isFirstCharacter )
318 subLineInfo.mMaxCharHeight = std::max( subLineInfo.mMaxCharHeight, characterLayoutInfo.mSize.height );
319 subLineInfo.mMaxAscender = std::max( subLineInfo.mMaxAscender, characterLayoutInfo.mAscender );
322 // All characters for word 'wordIndex' have been processed.
323 // Next word need to process all characters, so the characterIndex is reset to 0.
325 isFirstCharacter = false;
328 lineOffset += subLineInfo.mLineLength;
332 CalculateLineLength( isWhiteSpace, shrunkWordWidth, parentWidth, found, subLineInfo.mLineLength, endWhiteSpaceLength );
333 if( !found || isFirstCharacter )
335 subLineInfo.mMaxCharHeight = std::max( subLineInfo.mMaxCharHeight, wordLayoutInfo.mSize.height );
336 subLineInfo.mMaxAscender = std::max( subLineInfo.mMaxAscender, wordLayoutInfo.mAscender );
338 isFirstCharacter = false;
342 subLineInfo.mMaxCharHeight *= shrinkFactor;
343 subLineInfo.mMaxAscender *= shrinkFactor;
346 float CalculateXoffset( Toolkit::Alignment::Type horizontalTextAlignment, float parentWidth, float wholeTextWidth )
348 float xOffset( 0.f );
349 switch( horizontalTextAlignment )
351 case Toolkit::Alignment::HorizontalLeft:
356 case Toolkit::Alignment::HorizontalCenter:
358 xOffset = 0.5f * ( parentWidth - wholeTextWidth );
361 case Toolkit::Alignment::HorizontalRight:
363 xOffset = parentWidth - wholeTextWidth;
368 DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateXoffset: Wrong horizontal text alignment. Did you set a vertical one?" );
375 float CalculateYoffset( Toolkit::Alignment::Type verticalTextAlignment, float parentHeight, float wholeTextHeight )
377 float yOffset( 0.f );
378 switch( verticalTextAlignment )
380 case Toolkit::Alignment::VerticalTop:
385 case Toolkit::Alignment::VerticalCenter:
387 yOffset = 0.5f * ( parentHeight - wholeTextHeight );
390 case Toolkit::Alignment::VerticalBottom:
392 yOffset = parentHeight - wholeTextHeight;
397 DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateXoffset: Wrong vertical text alignment. Did you set an horizontal one?" );
404 float CalculateJustificationOffset( Toolkit::TextView::LineJustification justification, float wholeTextWidth, float lineLength )
407 switch( justification )
409 case Toolkit::TextView::Left:
414 case Toolkit::TextView::Center:
416 offset = 0.5f * ( wholeTextWidth - lineLength );
419 case Toolkit::TextView::Right:
421 offset = wholeTextWidth - lineLength;
424 case Toolkit::TextView::Justified:
434 bool IsVisible( const Vector3& position, const Size& size, const Size& parentSize, VisibilityTestType type )
436 bool visible = false;
442 // Whether the text-actor is fully inside the boundaries of the text-view.
443 visible = ( ( position.x >= 0.f ) && ( position.x + size.width <= parentSize.width ) &&
444 ( position.y >= size.height ) && ( position.y <= parentSize.height ) );
447 case FULLY_VISIBLE_WIDTH:
449 // Whether the text-actor is between the left and right boundaries of the text-view.
450 visible = ( ( position.x >= 0.f ) && ( position.x + size.width <= parentSize.width ) );
453 case FULLY_VISIBLE_HEIGHT:
455 // Whether the text-actor is between the top and bottom boundaries of the text-view.
456 visible = ( ( position.y >= size.height ) && ( position.y <= parentSize.height ) );
459 case PARTIALLY_VISIBLE:
461 // Whether the text-actor is partially inside the boundaries of the text-view.
462 visible = ( ( position.x < parentSize.width ) &&
463 ( position.x + size.width > 0.f ) &&
464 ( position.y > 0.f ) &&
465 ( position.y - size.height < parentSize.height ) );
468 case PARTIALLY_VISIBLE_WIDTH:
470 // Whether the text-actor is partially inside the area defined by the left and the right boundaries of the text-view.
471 // It may not be partially inside the text-view.
472 visible = ( ( position.x < parentSize.width ) &&
473 ( position.x + size.width > 0.f ) );
476 case PARTIALLY_VISIBLE_HEIGHT:
478 // Whether the text-actor is partially inside the area defined by the top and the bottom boundaries of the text-view.
479 // It may not be partially inside the text-view.
480 visible = ( ( position.y > 0.f ) &&
481 ( position.y - size.height < parentSize.height ) );
489 Vector2 CalculateRectParameters( const Vector2& p0, const Vector2& p1 )
491 const float gradient = ( p1.y - p0.y ) / ( p1.x - p0.x );
493 return Vector2( gradient, p0.y - gradient * p0.x );
496 void UpdateAlignment( const TextView::LayoutParameters& layoutParameters,
497 TextView::RelayoutData& relayoutData )
499 // Calculates an offset to align the whole text within the text-view's boundary accordingly with the set alignment and justification options.
500 // The offset could be negative if the whole text is bigger than the boundary of the text-view.
502 // If the exceed policy is ellipsize at the end, negative offsets are not wanted.
503 // In that case, it will align the line to the left and/or top, and ellipsize the end.
504 const bool ellipsizeAlignToLeft = ( layoutParameters.mExceedPolicy == TextView::EllipsizeEndOriginal ) ||
505 ( layoutParameters.mExceedPolicy == TextView::EllipsizeEnd ) ||
506 ( layoutParameters.mExceedPolicy == TextView::SplitEllipsizeEnd );
507 const bool ellipsizeAlignToTop = ( layoutParameters.mExceedPolicy == TextView::EllipsizeEnd ) ||
508 ( layoutParameters.mExceedPolicy == TextView::SplitEllipsizeEnd );
510 RelayoutParameters relayoutParameters;
512 // Calculates the vertical and horizontal offsets.
513 const float textHorizontalOffset = CalculateXoffset( layoutParameters.mHorizontalAlignment, relayoutData.mTextViewSize.width, relayoutData.mTextSizeForRelayoutOption.width );
514 const float textVerticalOffset = CalculateYoffset( layoutParameters.mVerticalAlignment, relayoutData.mTextViewSize.height, relayoutData.mTextSizeForRelayoutOption.height );
516 std::size_t lineJustificationIndex = 0u; // Index to the first position of the vector which stores all line justification info.
517 std::size_t infoTableCharacterIndex = 0u;
519 relayoutParameters.mIndices.mParagraphIndex = 0u;
521 for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(),
522 endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end();
523 paragraphLayoutIt != endParagraphLayoutIt;
524 ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex )
526 TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
528 float justificationOffset = 0.f;
530 relayoutParameters.mIndices.mWordIndex = 0u;
532 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
533 endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
534 wordLayoutIt != endWordLayoutIt;
535 ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
537 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
539 relayoutParameters.mIndices.mCharacterIndex = 0u;
541 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
542 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
543 characterLayoutIt != endCharacterLayoutIt;
544 ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex )
546 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
548 // Calculate line justification offset.
549 if( lineJustificationIndex < relayoutData.mLineJustificationInfo.size() )
551 const TextView::LineJustificationInfo lineJustificationInfo( *( relayoutData.mLineJustificationInfo.begin() + lineJustificationIndex ) );
553 if( relayoutParameters.mIndices == lineJustificationInfo.mIndices )
555 justificationOffset = CalculateJustificationOffset( layoutParameters.mLineJustification, relayoutData.mTextSizeForRelayoutOption.width, lineJustificationInfo.mLineLength );
556 ++lineJustificationIndex; // increase the index to point the next position in the vector.
560 // Deletes the offsets if the exceed policies are EllipsizeEnd.
561 const float horizontalOffset = textHorizontalOffset + justificationOffset;
562 characterLayoutInfo.mOffset.x = ( ellipsizeAlignToLeft && ( horizontalOffset < 0.f ) ) ? 0.f : horizontalOffset;
563 characterLayoutInfo.mOffset.y = ( ellipsizeAlignToTop && ( textVerticalOffset < 0.f ) ) ? 0.f : textVerticalOffset;
565 // Updates the size and position table for text-input with the alignment offset.
566 Vector3 positionOffset( characterLayoutInfo.mPosition );
568 std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex;
569 Toolkit::TextView::CharacterLayoutInfo& characterTableInfo( *infoTableIt );
571 characterTableInfo.mPosition.x = positionOffset.x + characterLayoutInfo.mOffset.x;
572 characterTableInfo.mPosition.y = positionOffset.y + characterLayoutInfo.mOffset.y;
574 positionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor;
580 void CalculateBearing( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
581 TextView::RelayoutData& relayoutData )
593 // ggggg gggggggggg bb ggggg
594 // gg gg gggggggggg bb gg gg
595 // gg gg gggg bb gg gg
596 // gg gg gggg bb gg gg
597 // ggggg gg gggg bbbbbbb ggggg
598 // gg gg gggg bb bb gg
599 // g gg gggggggggg bb bb g gg
600 // ggggg gggggggggg bbbbbbb ggggg
609 // ggggg gggg gggg bb ggggg
610 // gg gg gggg gggg bbbbbbb gg gg
611 // gg gg gggg gggg bb bb gg gg
612 // gg gg gggggggggg bb bb gg gg
613 // ggggg gggggggggg bbbbbbb ggggg
616 // ggggg gg gggg ggggg
621 const Toolkit::TextView::LineLayoutInfo& lineInfo( *( relayoutData.mLines.end() - 1u ) );
622 const float bearingOffset = ( lineInfo.mSize.height - lineInfo.mAscender ) - ( characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender );
624 characterLayoutInfo.mPosition.y -= bearingOffset * relayoutData.mShrinkFactor;
627 void UpdateLayoutInfoTable( Vector4& minMaxXY,
628 TextViewProcessor::WordLayoutInfo& wordLayoutInfo,
629 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
630 RelayoutParameters& relayoutParameters,
631 TextView::RelayoutData& relayoutData )
633 // updates min and max position to calculate the text size for multiline policies.
634 minMaxXY.x = std::min( minMaxXY.x, characterLayoutInfo.mPosition.x );
635 minMaxXY.z = std::max( minMaxXY.z, characterLayoutInfo.mPosition.x + characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor );
637 minMaxXY.y = std::min( minMaxXY.y, characterLayoutInfo.mPosition.y - characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor );
638 minMaxXY.w = std::max( minMaxXY.w, characterLayoutInfo.mPosition.y );
640 // Adds layout info to be retrieved by external controls or applications.
641 Vector3 positionOffset( characterLayoutInfo.mPosition );
643 const float descender = characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender;
645 const Toolkit::TextView::CharacterLayoutInfo characterLayoutTableInfo( Size( characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor,
646 characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor ),
648 ( TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType ),
649 false, // VCC set the correct direction if needed.
653 relayoutData.mCharacterLayoutInfoTable.push_back( characterLayoutTableInfo );
655 positionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor;
658 void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters,
659 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
660 RelayoutParameters& relayoutParameters,
661 FadeParameters& fadeParameters,
662 TextView::RelayoutData& relayoutData )
664 if( ( TextView::Fade != layoutParameters.mExceedPolicy ) &&
665 ( TextView::SplitFade != layoutParameters.mExceedPolicy ) &&
666 ( TextView::FadeOriginal != layoutParameters.mExceedPolicy ) &&
667 ( TextView::OriginalFade != layoutParameters.mExceedPolicy ) )
673 // Calculates visibility of a text-actor according the exceed policies.
675 // position + alignment offset.
676 const Vector3 position( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x,
677 characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y,
678 characterLayoutInfo.mPosition.z );
680 // Whether the text actor is fully, partially or non visible (according exceed policies).
681 switch( layoutParameters.mExceedPolicy )
685 // All text-actors which are not completely inside the text-view's boundaries are set as non visible.
686 // All text-actors which are partially inside the text-view's boundaries are set as partially visible.
687 if( !IsVisible( position,
688 characterLayoutInfo.mSize,
689 relayoutData.mTextViewSize,
692 relayoutParameters.mIsVisible = false;
693 if( IsVisible( position,
694 characterLayoutInfo.mSize,
695 relayoutData.mTextViewSize,
696 PARTIALLY_VISIBLE ) )
698 fadeParameters.mIsPartiallyVisible = true;
700 // Checks if a text-actor is exceeding more than one boundary as this case is not supported.
701 if( IsExceedingWidth( position,
702 characterLayoutInfo.mSize,
703 relayoutData.mTextViewSize ) &&
704 IsExceedingHeight( position,
705 characterLayoutInfo.mSize,
706 relayoutData.mTextViewSize ) )
708 // Combination not fully supported by text-view.
709 // Need to check if text-actor really supports this combination.
710 fadeParameters.mIsPartiallyVisible = false;
716 case TextView::FadeOriginal:
718 // All text-actors which are not completely between the left and right text-view's boundaries are set as non visible.
719 // All text-actors which are partially inside the text-view's boundaries are set as partially visible.
720 if( !IsVisible( position,
721 characterLayoutInfo.mSize,
722 relayoutData.mTextViewSize,
723 FULLY_VISIBLE_WIDTH ) )
725 relayoutParameters.mIsVisible = false;
726 if( IsVisible( position,
727 characterLayoutInfo.mSize,
728 relayoutData.mTextViewSize,
729 PARTIALLY_VISIBLE_WIDTH ) )
731 fadeParameters.mIsPartiallyVisible = true;
736 case TextView::OriginalFade:
737 case TextView::SplitFade: // Fallthrough
739 // All text-actors which are not completely between the top and bottom text-view's boundaries are set as non visible.
740 // All text-actors which are partially inside the text-view's boundaries are set as partially visible.
741 if( !IsVisible( position,
742 characterLayoutInfo.mSize,
743 relayoutData.mTextViewSize,
744 FULLY_VISIBLE_HEIGHT ) )
746 relayoutParameters.mIsVisible = false;
747 if( IsVisible( position,
748 characterLayoutInfo.mSize,
749 relayoutData.mTextViewSize,
750 PARTIALLY_VISIBLE_HEIGHT ) )
752 fadeParameters.mIsPartiallyVisible = true;
759 DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateVisibilityForFade. Wrong exceed policies." )
764 if( relayoutParameters.mIsVisible || fadeParameters.mIsPartiallyVisible )
766 characterLayoutInfo.mIsVisible = true;
768 const Size size = characterLayoutInfo.mSize * relayoutData.mShrinkFactor;
769 const float characterPositionPlusWidth = position.x + size.width;
770 const float characterPositionMinusHeight = position.y - size.height;
772 // Calculates which edges need to be faded-out.
773 bool rightFadeOut = false;
774 bool leftFadeOut = false;
775 bool bottomFadeOut = false;
776 bool topFadeOut = false;
778 switch( layoutParameters.mExceedPolicy )
782 // All text-actors exceeding any of the boundaries will be faded-out.
783 rightFadeOut = ( characterPositionPlusWidth > fadeParameters.mRightFadeThreshold );
784 leftFadeOut = ( position.x < fadeParameters.mLeftFadeThreshold );
785 bottomFadeOut = ( position.y > fadeParameters.mBottomFadeThreshold );
786 topFadeOut = ( characterPositionMinusHeight < fadeParameters.mTopFadeThreshold );
789 case TextView::FadeOriginal:
791 // Only text-actors exceeding the left or the right boundaries will be faded-out.
792 rightFadeOut = ( characterPositionPlusWidth > fadeParameters.mRightFadeThreshold );
793 leftFadeOut = ( position.x < fadeParameters.mLeftFadeThreshold );
796 case TextView::SplitFade:
797 case TextView::OriginalFade: //Fallthrough
799 // Only text-actors exceeding the top or the bottom boundaries will be faded-out.
800 bottomFadeOut = ( position.y > fadeParameters.mBottomFadeThreshold );
801 topFadeOut = ( characterPositionMinusHeight < fadeParameters.mTopFadeThreshold );
806 DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateVisibilityForFade. Wrong exceed policies." );
811 // Calculates gradient parameters for a text-actor.
812 Vector4 gradientColor = Vector4::ZERO;
813 Vector2 startPoint = Vector2::ZERO;
814 Vector2 endPoint = Vector2::ZERO;
816 if( NULL == characterLayoutInfo.mGradientInfo )
818 characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo();
821 if( !( rightFadeOut && leftFadeOut ) )
823 // Current implementation can't set gradient parameters for a text-actor exceeding at the same time the left and the right boundaries.
826 gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
828 // Calculates gradient coeficients.
829 characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mRightAlphaCoeficients.x * position.x + fadeParameters.mRightAlphaCoeficients.y );
830 gradientColor.a *= std::max( 0.f, fadeParameters.mRightAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mRightAlphaCoeficients.y );
832 startPoint = Vector2( std::max( 0.f, ( fadeParameters.mRightFadeThresholdOffset - position.x ) / size.width ), 0.5f );
833 endPoint = Vector2( std::min( 1.f, ( relayoutData.mTextViewSize.width - position.x ) / size.width ), 0.5f );
835 else if( leftFadeOut )
837 gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
839 // Calculates gradient coeficients.
840 characterLayoutInfo.mColorAlpha = std::min( 1.f, fadeParameters.mLeftAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mLeftAlphaCoeficients.y );
841 gradientColor.a *= gradientColor.a * std::max( 0.f, fadeParameters.mLeftAlphaCoeficients.x * position.x + fadeParameters.mLeftAlphaCoeficients.y );
843 startPoint = Vector2( std::max( 0.f, ( fadeParameters.mLeftFadeThresholdOffset - position.x ) / size.width ), 0.5f );
844 endPoint = Vector2( std::min( 1.f, -position.x / size.width ), 0.5f );
848 if( !( bottomFadeOut && topFadeOut ) )
850 // Current implementation can't set gradient parameters for a text-actor exceeding at the same time the top and the bottom boundaries.
853 gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
855 // Calculates gradient coeficients.
856 characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mBottomAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mBottomAlphaCoeficients.y );
857 gradientColor.a *= std::max( 0.f, fadeParameters.mBottomAlphaCoeficients.x * position.y + fadeParameters.mBottomAlphaCoeficients.y );
859 startPoint = Vector2( 0.5f, std::max( 0.f, ( fadeParameters.mBottomFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) );
860 endPoint = Vector2( 0.5f, std::min( 1.f, ( relayoutData.mTextViewSize.height - characterPositionMinusHeight ) / size.height ) );
862 else if( topFadeOut )
864 gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
866 // Calculates gradient coeficients.
867 characterLayoutInfo.mColorAlpha *= gradientColor.a * std::min( 1.f, fadeParameters.mTopAlphaCoeficients.x * position.y + fadeParameters.mTopAlphaCoeficients.y );
868 gradientColor.a *= std::max( 0.f, fadeParameters.mTopAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mTopAlphaCoeficients.y );
870 startPoint = Vector2( 0.5f, std::max( 0.f, ( fadeParameters.mTopFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) );
871 endPoint = Vector2( 0.5f, std::min( 1.f, -characterPositionMinusHeight / size.height ) );
875 characterLayoutInfo.mGradientInfo->mGradientColor = gradientColor;
876 characterLayoutInfo.mGradientInfo->mStartPoint = startPoint;
877 characterLayoutInfo.mGradientInfo->mEndPoint = endPoint;
881 characterLayoutInfo.mIsVisible = false;
885 bool CalculateVisibilityForEllipsizeEndOriginal( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
886 const EllipsizeParameters& ellipsizeParameters )
888 bool isPartiallyVisible = false;
890 if( !IsVisible( ellipsizeParameters.mPosition,
891 characterLayoutInfo.mSize,
892 ellipsizeParameters.mEllipsizeBoundary,
893 FULLY_VISIBLE_WIDTH ) )
895 // The character doesn't fit in the text-view's width.
896 characterLayoutInfo.mIsVisible = false;
898 // Checks if the character is partially visible (it's cut by the boundary)
899 isPartiallyVisible = IsVisible( ellipsizeParameters.mPosition,
900 characterLayoutInfo.mSize,
901 ellipsizeParameters.mEllipsizeBoundary,
902 PARTIALLY_VISIBLE_WIDTH );
906 // The character fits in the text-view's width. Set it to visible.
907 characterLayoutInfo.mIsVisible = true;
910 return isPartiallyVisible;
913 bool CalculateVisibilityForEllipsizeEnd( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
914 const EllipsizeParameters& ellipsizeParameters )
916 bool isPartiallyVisible = false;
918 if( !IsVisible( ellipsizeParameters.mPosition,
919 characterLayoutInfo.mSize,
920 ellipsizeParameters.mEllipsizeBoundary,
923 // The character is not fully visible. Needs to check if it's partially visible.
924 characterLayoutInfo.mIsVisible = false;
926 // Checks if the character doesn't cut the bottom edge of the text-view.
927 const bool fullyVisibleHeight = IsVisible( ellipsizeParameters.mPosition,
928 characterLayoutInfo.mSize,
929 ellipsizeParameters.mEllipsizeBoundary,
930 FULLY_VISIBLE_HEIGHT );
932 // Checks if the character cuts the right edge of the text-view.
933 const bool partiallyVisibleWidth = IsVisible( ellipsizeParameters.mPosition,
934 characterLayoutInfo.mSize,
935 ellipsizeParameters.mEllipsizeBoundary,
936 PARTIALLY_VISIBLE_WIDTH );
938 // Character will be ellipsized if it cuts the right edge of the text-view but fits completely in the text-view's height.
939 isPartiallyVisible = ( fullyVisibleHeight && partiallyVisibleWidth );
943 // The character fits in the boundary of the text-view. Set it to visible.
944 characterLayoutInfo.mIsVisible = true;
947 return isPartiallyVisible;
950 void CalculateVisibilityForEllipsize( const Internal::TextView::LayoutParameters& layoutParameters,
951 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
952 EllipsizeParameters& ellipsizeParameters,
953 TextView::RelayoutData& relayoutData )
955 // Calculates visibility for EllipsizeEnd exceed policies.
957 // It defines a boundary on the right side of the text-view by substracting the ellipsize-text's size (...) to the text-view's size.
958 // If a character is cut by this boundary and the whole line (if the multi-line policy is split-by-new-line-char)
959 // or the whole word (if the multi-line policy is split-by-word) doesn't fit in the text-view's width, then it's replaced by the ellipsize-text.
961 // Position of the character used to do the visibility test.
962 ellipsizeParameters.mPosition = Vector3( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x,
963 characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y,
964 characterLayoutInfo.mPosition.z );
966 // Text will be ellipsized if a character is partially visible (it's cut by the boundary defined in the right side of the text-view).
967 bool isPartiallyVisible = false;
969 // Checks if the whole line or the whole word fits in the text-view's width accordingly with the multiline policy.
970 const bool fitsInWidth = ( Toolkit::TextView::SplitByNewLineChar == layoutParameters.mMultilinePolicy ) ? ellipsizeParameters.mLineFits: ellipsizeParameters.mWordFits;
972 // Will only ellipsize the text if it cuts the right vertical edge and it doesn't fit in the text-view's width.
975 // The line or word fits completely inside the text-view's width. Nothing else to do.
976 characterLayoutInfo.mIsVisible = true;
980 // The line or word doesn't fit in the text-view's width.
982 // Calculates visibility for each type of ellipsize policies.
983 switch( layoutParameters.mExceedPolicy )
985 case TextView::EllipsizeEndOriginal:
987 // Ellipsizes the text if it doesn't fit in the width but it doesn't ellipsize if the text doesn't fit in the height.
989 isPartiallyVisible = CalculateVisibilityForEllipsizeEndOriginal( characterLayoutInfo,
990 ellipsizeParameters );
994 case TextView::SplitEllipsizeEnd:
995 case TextView::EllipsizeEnd:
997 // Ellipsizes the text if it doesn't fit in the width and fully fits in the text-view's height.
999 isPartiallyVisible = CalculateVisibilityForEllipsizeEnd( characterLayoutInfo,
1000 ellipsizeParameters );
1006 DALI_ASSERT_DEBUG( !"TextViewRelayout::CalculateVisibilityForEllipsize. Wrong exceed value." );
1012 // If the current character is not fully visible but is partially visible, it is cut by the boundary of the text-view.
1013 // In that case, the charater needs to be replaced by the ellipsize text.
1014 ellipsizeParameters.mCreateEllipsizedTextActors = ( !characterLayoutInfo.mIsVisible && isPartiallyVisible );
1017 void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters,
1018 TextView::RelayoutData& relayoutData )
1020 // The default ellipsize text is '...' and all dots have the same style. However, a differernt ellipsize text could be set and it can have characters with differernt styles.
1021 // The code bellow creates the text-actors needed for the ellipsize text.
1023 // Set ellipsize's position by the end of visible text.
1024 Vector3 ellipsizePosition = ellipsizeParameters.mPosition;
1025 // Stores current ellipsize text.
1027 // Stores current ellipsize style.
1028 TextStyle ellipsizeStyle;
1029 // Stores the current size.
1031 //Whether current glyph is an emoticon.
1032 bool isColorGlyph = false;
1034 float bearingOffset = 0.f;
1036 // Create ellipsize text-actor.
1037 for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator ellipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.begin(),
1038 endEllipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.end();
1039 ellipsizeCharacterLayoutIt != endEllipsizeCharacterLayoutIt;
1040 ++ellipsizeCharacterLayoutIt )
1042 const TextViewProcessor::CharacterLayoutInfo& ellipsizeCharacterLayoutInfo( *ellipsizeCharacterLayoutIt );
1045 ( isColorGlyph != ellipsizeCharacterLayoutInfo.mIsColorGlyph ) ||
1046 ( ellipsizeStyle != ellipsizeCharacterLayoutInfo.mStyledText.mStyle ) )
1048 // The style is different, so a new text-actor is needed.
1049 if( !ellipsizeText.IsEmpty() )
1051 // It only creates a text-actor if there is any text.
1052 RenderableActor ellipsizeGlyphActor = CreateGlyphActor( ellipsizeText, ellipsizeStyle, relayoutData.mTextActorCache );
1053 ellipsizeGlyphActor.SetSize( ellipsizeSize );
1054 ellipsizeGlyphActor.SetPosition( Vector3( ellipsizePosition.x, ellipsizePosition.y - bearingOffset, ellipsizePosition.z ) );
1056 // Updates the position for the next text-actor.
1057 ellipsizePosition.x += ellipsizeSize.width;
1059 // Adds the text-actor to the list.
1060 relayoutData.mEllipsizedGlyphActors.push_back( ellipsizeGlyphActor );
1063 // Resets the current ellipsize info.
1064 ellipsizeText = ellipsizeCharacterLayoutInfo.mStyledText.mText;
1065 ellipsizeStyle = ellipsizeCharacterLayoutInfo.mStyledText.mStyle;
1066 ellipsizeSize = ellipsizeCharacterLayoutInfo.mSize;
1067 isColorGlyph = ellipsizeCharacterLayoutInfo.mIsColorGlyph;
1069 bearingOffset = ( ellipsizeParameters.mLineDescender - ( ellipsizeCharacterLayoutInfo.mSize.height - ellipsizeCharacterLayoutInfo.mAscender ) ) * relayoutData.mShrinkFactor;
1073 // Updates text and size with the new character.
1074 ellipsizeText.Append( ellipsizeCharacterLayoutInfo.mStyledText.mText );
1075 TextViewProcessor::UpdateSize( ellipsizeSize, ellipsizeCharacterLayoutInfo.mSize );
1079 if( !ellipsizeText.IsEmpty() )
1081 // Creates the last glyph-actor.
1082 RenderableActor ellipsizeGlyphActor = CreateGlyphActor( ellipsizeText, ellipsizeStyle, relayoutData.mTextActorCache );
1083 ellipsizeGlyphActor.SetSize( ellipsizeSize );
1084 ellipsizeGlyphActor.SetPosition( Vector3( ellipsizePosition.x, ellipsizePosition.y - bearingOffset, ellipsizePosition.z ) );
1086 // Adds the glyph-actor to the list.
1087 relayoutData.mEllipsizedGlyphActors.push_back( ellipsizeGlyphActor );
1091 void EllipsizeLine( const TextView::LayoutParameters& layoutParameters,
1092 EllipsizeParameters& ellipsizeParameters,
1093 TextView::RelayoutData& relayoutData )
1095 // Traverses the text layout info from the first character of the line
1096 // to the last one setting to each character its visibility. If needed, it adds the ellipsize text (...).
1098 // Indices to the first character of the line.
1099 TextViewProcessor::TextInfoIndices firstIndices;
1100 TextViewProcessor::GetIndicesFromGlobalCharacterIndex( ellipsizeParameters.mFirstIndex,
1101 relayoutData.mTextLayoutInfo,
1104 // Indices to the last character of the line.
1105 TextViewProcessor::TextInfoIndices lastIndices;
1106 TextViewProcessor::GetIndicesFromGlobalCharacterIndex( ellipsizeParameters.mLastIndex,
1107 relayoutData.mTextLayoutInfo,
1110 // Defines a boundary by substracting the ellipsize-text's width to the text-view's width.
1111 // This is the boundary used to check if a character have to be ellipsized.
1112 ellipsizeParameters.mEllipsizeBoundary = relayoutData.mTextViewSize;
1113 ellipsizeParameters.mEllipsizeBoundary.width -= relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mSize.width;
1115 for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + firstIndices.mParagraphIndex,
1116 endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + lastIndices.mParagraphIndex + 1u;
1117 paragraphLayoutIt != endParagraphLayoutIt;
1118 ++paragraphLayoutIt )
1120 TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
1122 ellipsizeParameters.mLineFits = ellipsizeParameters.mIsLineWidthFullyVisible && ellipsizeParameters.mIsLineHeightFullyVisible && ellipsizeParameters.mIsNextLineFullyVisibleHeight;
1124 if( !ellipsizeParameters.mIsNextLineFullyVisibleHeight )
1126 ellipsizeParameters.mEllipsizeBoundary.width = ellipsizeParameters.mLineWidth;
1129 bool firstWord = true;
1130 bool lastWord = false;
1132 std::size_t wordCount = 0u;
1134 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin() + firstIndices.mWordIndex,
1135 endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin() + lastIndices.mWordIndex + 1u;
1136 wordLayoutIt != endWordLayoutIt;
1137 ++wordLayoutIt, ++wordCount )
1139 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
1141 if( wordCount == lastIndices.mWordIndex - firstIndices.mWordIndex )
1146 const std::size_t firstCharacterIndex = firstWord ? firstIndices.mCharacterIndex : 0u;
1147 const std::size_t lastCharacterIndex = lastWord ? lastIndices.mCharacterIndex : wordLayoutInfo.mCharactersLayoutInfo.size() - 1u;
1148 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + firstCharacterIndex,
1149 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + lastCharacterIndex + 1u;
1150 characterLayoutIt != endCharacterLayoutIt;
1151 ++characterLayoutIt )
1153 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
1155 if( ellipsizeParameters.mEllipsizeLine )
1157 // Calculates the character visibility and whether it needs to be replace by ellipsized text.
1158 CalculateVisibilityForEllipsize( layoutParameters,
1159 characterLayoutInfo,
1160 ellipsizeParameters,
1163 if( ellipsizeParameters.mCreateEllipsizedTextActors )
1165 // Create ellipsize text-actors if the character needs to be replaced.
1166 CreateEllipsizeTextActor( ellipsizeParameters,
1172 if( ( TextView::EllipsizeEnd == layoutParameters.mExceedPolicy ) ||
1173 ( TextView::SplitEllipsizeEnd == layoutParameters.mExceedPolicy ))
1175 if( !ellipsizeParameters.mIsLineHeightFullyVisible )
1177 // Make characters invisible.
1178 characterLayoutInfo.mIsVisible = false;
1188 void SetTextVisible( TextView::RelayoutData& relayoutData )
1190 for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(),
1191 endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end();
1192 paragraphLayoutIt != endParagraphLayoutIt;
1193 ++paragraphLayoutIt )
1195 TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
1197 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
1198 endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
1199 wordLayoutIt != endWordLayoutIt;
1202 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
1204 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
1205 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
1206 characterLayoutIt != endCharacterLayoutIt;
1207 ++characterLayoutIt )
1209 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
1211 characterLayoutInfo.mIsVisible = true;
1212 delete characterLayoutInfo.mGradientInfo;
1213 characterLayoutInfo.mGradientInfo = NULL;
1214 characterLayoutInfo.mColorAlpha = characterLayoutInfo.mStyledText.mStyle.GetTextColor().a;
1219 // Updates the visibility for text-input..
1220 for( std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator it = relayoutData.mCharacterLayoutInfoTable.begin(),
1221 endIt = relayoutData.mCharacterLayoutInfoTable.end();
1225 Toolkit::TextView::CharacterLayoutInfo& characterLayoutInfo( *it );
1227 characterLayoutInfo.mIsVisible = true;
1231 void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters,
1232 const TextView::VisualParameters& visualParameters,
1233 TextView::RelayoutData& relayoutData )
1235 RelayoutParameters relayoutParameters;
1236 FadeParameters fadeParameters;
1238 // 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.
1239 fadeParameters.mRightFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mRight );
1240 fadeParameters.mRightFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mRight > 0u ? fadeParameters.mRightFadeBoundary : MINIMUM_FADE_BOUNDARY );
1241 fadeParameters.mRightFadeThreshold = relayoutData.mTextViewSize.width - fadeParameters.mRightFadeBoundary;
1242 fadeParameters.mRightFadeThresholdOffset = relayoutData.mTextViewSize.width - fadeParameters.mRightFadeBoundaryOffset;
1243 fadeParameters.mLeftFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mLeft );
1244 fadeParameters.mLeftFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mLeft > 0u ? fadeParameters.mLeftFadeBoundary : MINIMUM_FADE_BOUNDARY );
1245 fadeParameters.mLeftFadeThreshold = fadeParameters.mLeftFadeBoundary;
1246 fadeParameters.mLeftFadeThresholdOffset = fadeParameters.mLeftFadeBoundaryOffset;
1247 fadeParameters.mTopFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mTop );
1248 fadeParameters.mTopFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mTop > 0u ? fadeParameters.mTopFadeBoundary : MINIMUM_FADE_BOUNDARY );
1249 fadeParameters.mTopFadeThreshold = fadeParameters.mTopFadeBoundary;
1250 fadeParameters.mTopFadeThresholdOffset = fadeParameters.mTopFadeBoundaryOffset;
1251 fadeParameters.mBottomFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mBottom );
1252 fadeParameters.mBottomFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mBottom > 0u ? fadeParameters.mBottomFadeBoundary : MINIMUM_FADE_BOUNDARY );
1253 fadeParameters.mBottomFadeThreshold = relayoutData.mTextViewSize.height - fadeParameters.mBottomFadeBoundary;
1254 fadeParameters.mBottomFadeThresholdOffset = relayoutData.mTextViewSize.height - fadeParameters.mBottomFadeBoundaryOffset;
1256 // Calculates the fade out rect coeficients for the right, left, top and bottom sides of the text-view.
1257 fadeParameters.mRightAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mRightFadeThresholdOffset, 1.f ), Vector2( relayoutData.mTextViewSize.width, 0.f ) );
1258 fadeParameters.mLeftAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mLeftFadeThresholdOffset, 1.f ), Vector2( 0.f, 0.f ) );
1259 fadeParameters.mTopAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mTopFadeThresholdOffset, 1.f ), Vector2( 0.f, 0.f ) );
1260 fadeParameters.mBottomAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mBottomFadeThresholdOffset, 1.f ), Vector2( relayoutData.mTextViewSize.height, 0.f ) );
1262 // Traverses all characters and calculates the visibility.
1264 std::size_t infoTableCharacterIndex = 0u;
1266 relayoutParameters.mIndices.mParagraphIndex = 0u;
1268 for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(),
1269 endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end();
1270 paragraphLayoutIt != endParagraphLayoutIt;
1271 ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex )
1273 TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
1275 relayoutParameters.mIndices.mWordIndex = 0u;
1277 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
1278 endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
1279 wordLayoutIt != endWordLayoutIt;
1280 ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
1282 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
1284 relayoutParameters.mIsFirstCharacterOfWord = true;
1285 relayoutParameters.mWordSize = wordLayoutInfo.mSize;
1286 relayoutParameters.mIndices.mCharacterIndex = 0u;
1288 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
1289 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
1290 characterLayoutIt != endCharacterLayoutIt;
1291 ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex )
1293 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
1295 relayoutParameters.mIsVisible = true;
1296 fadeParameters.mIsPartiallyVisible = false;
1298 // Calculates the visibility for the current character.
1299 CalculateVisibilityForFade( layoutParameters,
1300 characterLayoutInfo,
1305 // Updates the visibility for text-input..
1306 std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex;
1308 Toolkit::TextView::CharacterLayoutInfo& characterLayoutTableInfo( *it );
1310 characterLayoutTableInfo.mIsVisible = relayoutParameters.mIsVisible;
1312 relayoutParameters.mIsFirstCharacterOfWord = false;
1318 void UpdateVisibilityForEllipsize( const TextView::LayoutParameters& layoutParameters,
1319 const TextView::VisualParameters& visualParameters,
1320 TextView::RelayoutData& relayoutData )
1322 // Traverses the lines and checks which ones doesn't fit in the text-view's boundary.
1323 for( Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineInfoIt = relayoutData.mLines.begin(), endLineInfoIt = relayoutData.mLines.end();
1324 lineInfoIt != endLineInfoIt;
1327 const Toolkit::TextView::LineLayoutInfo& lineInfo( *lineInfoIt );
1329 // To check if a line fits in the text-view's boundary,
1330 // get the position of the first character is needed and do the test
1331 // with the line size.
1333 // An bearing offset may have been applied to the first character so it's needed to
1334 // get the start position of the line.
1336 // Some parameters used in the CalculateVisibilityForEllipsize() function.
1337 EllipsizeParameters ellipsizeParameters;
1339 // Retrieves the first index and the last index of the line.
1340 ellipsizeParameters.mFirstIndex = lineInfo.mCharacterGlobalIndex;
1341 ellipsizeParameters.mLastIndex = 0u;
1342 if( ( lineInfoIt + 1u ) != endLineInfoIt )
1344 const Toolkit::TextView::LineLayoutInfo& nextLineInfo( *( lineInfoIt + 1u ) );
1345 ellipsizeParameters.mLastIndex = nextLineInfo.mCharacterGlobalIndex - 1u;
1349 ellipsizeParameters.mLastIndex = relayoutData.mCharacterLayoutInfoTable.size() - 1u;
1352 // Retrieves the first character of the line and build the position of the line with the bearing.
1353 const Toolkit::TextView::CharacterLayoutInfo& characterInfo = *( relayoutData.mCharacterLayoutInfoTable.begin() + ellipsizeParameters.mFirstIndex );
1355 // Calculates the bearing offset applied to the first character.
1356 const float bearingOffset = ( lineInfo.mSize.height - lineInfo.mAscender ) - characterInfo.mDescender;
1358 // Build the position of the line by removing the bearing offset from the first character's position.
1359 const Vector3 position( characterInfo.mPosition.x,
1360 characterInfo.mPosition.y + bearingOffset,
1361 characterInfo.mPosition.z );
1363 // Checks if the line needs to be ellipsized,
1364 ellipsizeParameters.mIsLineWidthFullyVisible = IsVisible( position,
1366 relayoutData.mTextViewSize,
1367 FULLY_VISIBLE_WIDTH );
1369 // If the exceed policy is EllipsizeEndOriginal it's enough to check
1370 // if the line fits in the width.
1371 ellipsizeParameters.mEllipsizeLine = !ellipsizeParameters.mIsLineWidthFullyVisible;
1373 // If the exceed policy is EllipsizeEnd, it's needed to check if the next line exceeds the text-view's height.
1374 // If the next line exceeds the text-view height then it's going to be invisible and current line needs to be ellipsized.
1375 ellipsizeParameters.mIsLineHeightFullyVisible = true;
1376 ellipsizeParameters.mIsNextLineFullyVisibleHeight = true;
1377 if( ( TextView::EllipsizeEnd == layoutParameters.mExceedPolicy ) ||
1378 ( TextView::SplitEllipsizeEnd == layoutParameters.mExceedPolicy ) )
1380 // Need to check if there is lines which doesn't fit in the height.
1382 ellipsizeParameters.mIsLineHeightFullyVisible = IsVisible( position,
1384 relayoutData.mTextViewSize,
1385 FULLY_VISIBLE_HEIGHT );
1387 ellipsizeParameters.mEllipsizeLine = ellipsizeParameters.mEllipsizeLine && ellipsizeParameters.mIsLineHeightFullyVisible;
1389 if( ellipsizeParameters.mIsLineHeightFullyVisible && !ellipsizeParameters.mEllipsizeLine )
1391 // Current line is not ellipsized.
1392 // Need to check if there is a next line and if it's not visible. If there is, current line needs to be ellipsized.
1393 Toolkit::TextView::LineLayoutInfoContainer::const_iterator nextLineInfoIt = lineInfoIt + 1u;
1394 if( nextLineInfoIt != endLineInfoIt )
1396 // Retrives the position of the first character of the line and remove
1397 // the bearing offset to build to build the position of the line.
1398 const Toolkit::TextView::LineLayoutInfo& nextLineInfo( *nextLineInfoIt );
1399 const Toolkit::TextView::CharacterLayoutInfo& characterInfo = *( relayoutData.mCharacterLayoutInfoTable.begin() + nextLineInfo.mCharacterGlobalIndex );
1401 const float bearingOffset = ( ( lineInfo.mSize.height - lineInfo.mAscender ) - characterInfo.mDescender ) * relayoutData.mShrinkFactor;
1403 const Vector3 position( characterInfo.mPosition.x,
1404 characterInfo.mPosition.y + bearingOffset,
1405 characterInfo.mPosition.z );
1407 ellipsizeParameters.mIsNextLineFullyVisibleHeight = IsVisible( position,
1409 relayoutData.mTextViewSize,
1410 FULLY_VISIBLE_HEIGHT );
1412 // If the next line is not visible, current line have to be ellipsized.
1413 ellipsizeParameters.mEllipsizeLine = !ellipsizeParameters.mIsNextLineFullyVisibleHeight;
1418 if( !ellipsizeParameters.mIsNextLineFullyVisibleHeight )
1420 ellipsizeParameters.mLineWidth = position.x + lineInfo.mSize.width - relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mSize.width;
1423 // Sets the line descender.
1424 ellipsizeParameters.mLineDescender = lineInfo.mSize.height - lineInfo.mAscender;
1426 // At this point, ellipsizeLine distinguish if a piece of line have to be ellipsized or not.
1427 EllipsizeLine( layoutParameters, ellipsizeParameters, relayoutData );
1431 void UpdateVisibility( const TextView::LayoutParameters& layoutParameters,
1432 const TextView::VisualParameters& visualParameters,
1433 TextView::RelayoutData& relayoutData )
1435 switch( layoutParameters.mExceedPolicy )
1437 case TextView::FadeOriginal:
1438 case TextView::OriginalFade:
1439 case TextView::Fade:
1440 case TextView::SplitFade: // Fall through
1442 UpdateVisibilityForFade( layoutParameters,
1447 case TextView::EllipsizeEndOriginal:
1448 case TextView::SplitEllipsizeEnd:
1449 case TextView::EllipsizeEnd: // Fall through
1451 // Set first all characters to visible as UpdateVisibilityForEllipsize() doesn't traverse all of them.
1452 SetTextVisible( relayoutData );
1454 UpdateVisibilityForEllipsize( layoutParameters,
1461 SetTextVisible( relayoutData );
1468 * Creates an image actor for the emoticon.
1470 * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending).
1471 * @param[in,out] characterLayout Layout info for the character.
1472 * @param[in] character The character.
1474 void CreateEmoticon( const TextView::VisualParameters& visualParameters,
1475 TextViewProcessor::CharacterLayoutInfo& characterLayout,
1476 const Character& character )
1478 // The character is an emoticon.
1479 ImageActor imageActor = ImageActor::DownCast( characterLayout.mGlyphActor );
1482 imageActor = ImageActor::New();
1484 GlyphImage image = GlyphImage::New( character );
1488 imageActor.SetImage( image );
1492 imageActor.SetPosition( Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x,
1493 characterLayout.mPosition.y + characterLayout.mOffset.y,
1494 characterLayout.mPosition.z ) );
1495 imageActor.SetSize( characterLayout.mSize );
1497 // Sets the sort modifier value.
1498 imageActor.SetSortModifier( visualParameters.mSortModifier );
1500 characterLayout.mGlyphActor = imageActor;
1504 * Creates text-actors for the given text.
1506 * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending).
1507 * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info.
1508 * @param[in,out] paragraph Layout info for the paragraph.
1509 * @param[in,out] characterLayout Layout info for the character.
1510 * @param[in] character The character.
1511 * @param[in] style The character's style.
1512 * @param[in,out] currentTextActorInfo Temporary stores the text-actor's info to be set.
1513 * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles.
1515 void CreateTextActor( const TextView::VisualParameters& visualParameters,
1516 TextView::RelayoutData& relayoutData,
1517 const TextViewProcessor::ParagraphLayoutInfo& paragraph,
1518 TextViewProcessor::CharacterLayoutInfo& characterLayout,
1519 const Character& character,
1520 const TextStyle& style,
1521 CurrentTextActorInfo& currentTextActorInfo,
1522 bool createGlyphActors )
1524 // Set the text-actor for the current traversed text.
1525 if( currentTextActorInfo.textActor )
1527 currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
1528 currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
1529 currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
1531 SetVisualParameters( currentTextActorInfo,
1534 paragraph.mSize.height );
1537 currentTextActorInfo.text = Text( character );
1538 currentTextActorInfo.position = Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x,
1539 characterLayout.mPosition.y + characterLayout.mOffset.y,
1540 characterLayout.mPosition.z );
1541 currentTextActorInfo.size = characterLayout.mSize * relayoutData.mShrinkFactor;
1543 currentTextActorInfo.color = style.GetTextColor();
1544 currentTextActorInfo.color.a = characterLayout.mColorAlpha;
1546 currentTextActorInfo.gradientInfo = characterLayout.mGradientInfo;
1548 TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor );
1550 if( createGlyphActors )
1554 // Try to reuse first the text-actor of this character.
1555 textActor.SetTextStyle( style );
1559 // If there is no text-actor, try to retrieve one from the cache.
1560 textActor = relayoutData.mTextActorCache.RetrieveTextActor();
1562 // If still there is no text-actor, create one.
1565 TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_OFF );
1566 textActor = TextActor::New( Text(), parameters );
1570 textActor.SetTextStyle( style );
1573 characterLayout.mGlyphActor = textActor;
1576 // Update the current text-actor.
1577 currentTextActorInfo.textActor = textActor;
1581 * Traverses the whole paragraph initializating renderable-actor handles and updating them with the new size and position.
1583 * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending).
1584 * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info.
1585 * @param[in,out] paragraph Layout info for the paragraph.
1586 * @param[in,out] characterGlobalIndex Index to the character within the whole text.
1587 * @param[in,out] lineLayoutInfoIndex Index to the table of lines.
1588 * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles.
1590 void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualParameters,
1591 TextView::RelayoutData& relayoutData,
1592 TextViewProcessor::ParagraphLayoutInfo& paragraph,
1593 std::size_t& characterGlobalIndex,
1594 std::size_t& lineLayoutInfoIndex,
1595 bool createGlyphActors )
1597 CurrentTextActorInfo currentTextActorInfo;
1599 const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines.
1600 bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last line.
1601 bool glyphActorCreatedForLine = false; // Whether a renderable actor has been created for this line.
1603 TextStyle currentStyle; // style for the current text-actor.
1605 TextViewProcessor::GradientInfo* currentGradientInfo = NULL; // gradient color for the current text-actor.
1606 // start point for the current text-actor.
1607 // end point for the current text-actor.
1609 bool currentIsColorGlyph = false; // Whether current glyph is an emoticon.
1611 std::vector<TextActor> textActorsToRemove; // Keep a vector of text-actors to be included into the cache.
1613 std::size_t characterParagraphIndex = 0u; // Index to the character (within the paragraph).
1614 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
1615 wordIt != wordEndIt;
1618 TextViewProcessor::WordLayoutInfo& word( *wordIt );
1620 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
1621 characterIt != characterEndIt;
1624 TextViewProcessor::CharacterLayoutInfo& characterLayout( *characterIt );
1626 // Check if there is a new line.
1627 const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex );
1631 // Point to the next line.
1632 ++lineLayoutInfoIndex;
1633 if( lineLayoutInfoIndex >= lineLayoutInfoSize )
1635 // Arrived at last line.
1636 lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector.
1638 glyphActorCreatedForLine = false;
1641 // Do not create a glyph-actor if there is no text.
1642 const Character character = characterLayout.mStyledText.mText[0u]; // there are only one character per character layout.
1643 const TextStyle& style = characterLayout.mStyledText.mStyle;
1645 bool appendCharacter = false;
1647 if( characterLayout.mIsColorGlyph ||
1648 !character.IsWhiteSpace() || // A new paragraph character is also a white space.
1649 ( character.IsWhiteSpace() && style.IsUnderlineEnabled() ) )
1651 // Do not create a glyph-actor if it's a white space (without underline) or a new paragraph character.
1653 // Check if the character has the same gradient info than the current one.
1654 bool differentGradientInfo = false;
1655 if( characterLayout.mGradientInfo && currentGradientInfo )
1657 differentGradientInfo = ( characterLayout.mGradientInfo->mGradientColor != currentGradientInfo->mGradientColor ) ||
1658 ( characterLayout.mGradientInfo->mStartPoint != currentGradientInfo->mStartPoint ) ||
1659 ( characterLayout.mGradientInfo->mEndPoint != currentGradientInfo->mEndPoint );
1661 else if( ( NULL != currentGradientInfo ) || ( NULL != characterLayout.mGradientInfo ) )
1663 differentGradientInfo = true;
1666 // Creates one glyph-actor for each counsecutive group of characters, with the same style, per line, or if it's an emoticon.
1667 if( !glyphActorCreatedForLine ||
1668 characterLayout.mIsColorGlyph ||
1669 differentGradientInfo ||
1670 ( characterLayout.mIsColorGlyph != currentIsColorGlyph ) ||
1671 ( style != currentStyle ) )
1673 characterLayout.mSetText = false;
1674 characterLayout.mSetStyle = false;
1676 // There is a new style or a new line.
1677 glyphActorCreatedForLine = true;
1679 if( characterLayout.mIsColorGlyph )
1681 CreateEmoticon( visualParameters,
1687 CreateTextActor( visualParameters,
1693 currentTextActorInfo,
1694 createGlyphActors );
1697 // Update style to be checked with next characters.
1698 currentStyle = style;
1699 currentGradientInfo = characterLayout.mGradientInfo;
1700 currentIsColorGlyph = characterLayout.mIsColorGlyph;
1702 characterLayout.mGlyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT );
1703 characterLayout.mGlyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT );
1707 DALI_ASSERT_DEBUG( !characterLayout.mIsColorGlyph && "TextViewProcessor::InitializeTextActorInfo. An image-actor doesn't store more than one emoticon." );
1709 // Same style than previous one.
1711 // Add the character to the current text-actor and update the size.
1712 appendCharacter = true;
1714 TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor );
1717 // There is a previously created text-actor for this character.
1718 // If this character has another one put it into the cache.
1719 textActor.SetText( "" );
1720 textActorsToRemove.push_back( textActor );
1723 if( characterLayout.mGlyphActor )
1725 characterLayout.mGlyphActor.Reset();
1728 } // no white space / new paragraph char
1731 appendCharacter = true;
1734 if( appendCharacter )
1736 // Add the character to the current text-actor and update the size.
1737 if( characterLayout.mIsVisible && ( TextViewProcessor::ParagraphSeparator != word.mType ) )
1739 currentTextActorInfo.text.Append( character );
1741 currentTextActorInfo.position.y = std::min( currentTextActorInfo.position.y, ( characterLayout.mPosition.y + characterLayout.mOffset.y ) );
1742 currentTextActorInfo.size.width += characterLayout.mSize.width * relayoutData.mShrinkFactor;
1743 currentTextActorInfo.size.height = std::max( currentTextActorInfo.size.height, characterLayout.mSize.height * relayoutData.mShrinkFactor );
1747 ++characterGlobalIndex;
1748 ++characterParagraphIndex;
1752 if( !currentTextActorInfo.text.IsEmpty() )
1754 if( currentTextActorInfo.textActor )
1756 currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
1757 currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
1758 currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
1760 SetVisualParameters( currentTextActorInfo,
1763 paragraph.mSize.height );
1767 // Insert the spare text-actors into the cache.
1768 relayoutData.mTextActorCache.InsertTextActors( textActorsToRemove );
1771 void UpdateTextActorInfo( const TextView::VisualParameters& visualParameters,
1772 TextView::RelayoutData& relayoutData,
1773 bool createGlyphActors )
1775 if( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() )
1777 // nothing to do if there is no paragraphs.
1781 std::size_t characterGlobalIndex = 0u; // Index to the global character (within the whole text).
1782 std::size_t lineLayoutInfoIndex = 0u; // Index to the line info.
1784 for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end();
1785 paragraphIt != paragraphEndIt;
1788 TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt );
1790 UpdateTextActorInfoForParagraph( visualParameters,
1793 characterGlobalIndex,
1794 lineLayoutInfoIndex,
1795 createGlyphActors );
1798 // Set visual parameters for ellipsis renderable actors.
1799 for( std::vector<RenderableActor>::iterator it = relayoutData.mEllipsizedGlyphActors.begin(),
1800 endIt = relayoutData.mEllipsizedGlyphActors.end();
1804 RenderableActor glyphActor = ( *it );
1806 glyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT );
1807 glyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT );
1809 // Sets the sort modifier value.
1810 glyphActor.SetSortModifier( visualParameters.mSortModifier );
1812 // Enables or disables the blending.
1813 glyphActor.SetBlendMode( !visualParameters.mSnapshotModeEnabled ? BlendingMode::ON : BlendingMode::OFF );
1817 void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelayout::TextUnderlineStatus& textUnderlineStatus )
1819 // Traverse the whole text to find all groups of consecutive underlined characters in the same line.
1821 // 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.
1822 // According with the layout option, one of this paragraphs could be laid-out in more than one line.
1824 for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end();
1825 paragraphIt != paragraphEndIt;
1828 TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt );
1830 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
1831 wordIt != wordEndIt;
1834 TextViewProcessor::WordLayoutInfo& word( *wordIt );
1836 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
1837 characterIt != characterEndIt;
1840 TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
1842 // Check if current character is the first of a new line
1843 const bool isNewLine = ( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() ) &&
1844 ( textUnderlineStatus.mCharacterGlobalIndex == ( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) ).mCharacterGlobalIndex );
1847 ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
1850 if( character.mStyledText.mStyle.IsUnderlineEnabled() )
1852 if( !textUnderlineStatus.mCurrentUnderlineStatus || // Current character is underlined but previous one it wasn't.
1853 isNewLine ) // Current character is underlined and is the first of current line.
1855 // Create a new underline info for the current underlined characters.
1856 UnderlineInfo underlineInfo;
1857 underlineInfo.mMaxHeight = character.mSize.height;
1858 underlineInfo.mMaxThickness = character.mUnderlineThickness;
1859 underlineInfo.mPosition = character.mUnderlinePosition;
1861 textUnderlineStatus.mUnderlineInfo.push_back( underlineInfo );
1863 textUnderlineStatus.mCurrentUnderlineStatus = true; // Set the current text is underlined.
1867 // Retrieve last underline info and update it if current underline thickness is bigger.
1868 UnderlineInfo& underlineInfo( *( textUnderlineStatus.mUnderlineInfo.end() - 1u ) );
1870 underlineInfo.mMaxHeight = std::max( underlineInfo.mMaxHeight, character.mSize.height );
1872 if( character.mUnderlineThickness > underlineInfo.mMaxThickness )
1874 underlineInfo.mMaxThickness = character.mUnderlineThickness;
1875 underlineInfo.mPosition = character.mUnderlinePosition;
1881 textUnderlineStatus.mCurrentUnderlineStatus = false;
1884 ++textUnderlineStatus.mCharacterGlobalIndex;
1885 } // end characters.
1887 } // end paragraphs.
1890 void SetUnderlineInfo( TextView::RelayoutData& relayoutData )
1892 // 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.
1893 TextViewRelayout::TextUnderlineStatus textUnderlineStatus;
1895 // Traverse the whole text to find all groups of consecutive underlined characters in the same line.
1896 CalculateUnderlineInfo( relayoutData, textUnderlineStatus );
1898 if( textUnderlineStatus.mUnderlineInfo.empty() )
1900 // There is no underlined text. Just exit.
1904 // At this point textUnderlineStatus.mUnderlineInfo has for each group of consecutive underlined characters their maximum thickness, position and maximum height.
1905 // Traverse the whole text and set the previously stored underline info in the text style.
1907 std::vector<UnderlineInfo>::const_iterator underlineInfoIt = textUnderlineStatus.mUnderlineInfo.begin();
1908 std::vector<UnderlineInfo>::const_iterator underlineInfoEndIt = textUnderlineStatus.mUnderlineInfo.end();
1910 UnderlineInfo underlineInfo;
1912 if( underlineInfoIt < underlineInfoEndIt )
1914 underlineInfo = ( *underlineInfoIt );
1917 // Whether current text is underlined.
1918 textUnderlineStatus.mCurrentUnderlineStatus = false;
1919 textUnderlineStatus.mCharacterGlobalIndex = 0u;
1920 textUnderlineStatus.mLineGlobalIndex = 0u;
1922 float currentLineHeight = 0.f;
1923 float currentLineAscender = 0.f;
1925 for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end();
1926 paragraphIt != paragraphEndIt;
1929 TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt );
1931 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end();
1932 wordIt != wordEndIt;
1935 TextViewProcessor::WordLayoutInfo& word( *wordIt );
1937 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
1938 characterIt != characterEndIt;
1941 TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
1943 // Check if current character is the first of a new line
1945 bool isNewLine = false;
1947 if( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() )
1949 const Toolkit::TextView::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) );
1950 isNewLine = ( textUnderlineStatus.mCharacterGlobalIndex == lineLayoutInfo.mCharacterGlobalIndex );
1954 currentLineHeight = lineLayoutInfo.mSize.height;
1955 currentLineAscender = lineLayoutInfo.mAscender;
1956 ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
1960 if( character.mStyledText.mStyle.IsUnderlineEnabled() )
1962 if( textUnderlineStatus.mCurrentUnderlineStatus )
1966 // Retrieves the thickness and position for the next piece of underlined text.
1967 if( underlineInfoIt < underlineInfoEndIt )
1970 if( underlineInfoIt < underlineInfoEndIt )
1972 underlineInfo = *underlineInfoIt;
1978 textUnderlineStatus.mCurrentUnderlineStatus = true;
1980 // Before setting the position it needs to be adjusted to match the base line.
1981 const float bearingOffset = ( currentLineHeight - currentLineAscender ) - ( character.mSize.height - character.mAscender );
1982 const float positionOffset = ( underlineInfo.mMaxHeight - character.mSize.height ) - bearingOffset;
1984 // Sets the underline's parameters.
1985 character.mStyledText.mStyle.SetUnderline( true, underlineInfo.mMaxThickness, underlineInfo.mPosition - positionOffset );
1987 // Mark the character to be set the new style into the text-actor.
1988 character.mSetStyle = true;
1992 if( textUnderlineStatus.mCurrentUnderlineStatus )
1994 textUnderlineStatus.mCurrentUnderlineStatus = false;
1996 // Retrieves the thickness and position for the next piece of underlined text.
1997 if( underlineInfoIt < underlineInfoEndIt )
2000 if( underlineInfoIt < underlineInfoEndIt )
2002 underlineInfo = *underlineInfoIt;
2008 ++textUnderlineStatus.mCharacterGlobalIndex;
2009 } // end of characters.
2011 } // end of paragraphs.
2014 void RemoveGlyphActors( Actor textView,
2015 const std::vector<RenderableActor>& glyphActors )
2017 // Removes previously inserted renderable-actors.
2018 // The SplitByNewLineChar::Relayout(), SplitByWord::Relayout() and SplitByChar::Relayout() functions add
2019 // renderable-actors to the text-view. A handle to these renderable-actors are stored and passed to this function
2020 // in order to remove 'only' renderable-actors added by these functions.
2021 // Any other actor added by a programmer or application won't be removed.
2023 for( std::vector<RenderableActor>::const_reverse_iterator it = glyphActors.rbegin(), endIt = glyphActors.rend(); it != endIt; ++it )
2025 textView.Remove( *it );
2029 void InsertToTextView( Actor textView,
2030 TextView::RelayoutData& relayoutData )
2032 // Add text-actors to the text-view.
2034 for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(),
2035 endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end();
2036 paragraphLayoutIt != endParagraphLayoutIt;
2037 ++paragraphLayoutIt )
2039 TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
2041 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
2042 endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
2043 wordLayoutIt != endWordLayoutIt;
2046 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
2048 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
2049 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
2050 characterLayoutIt != endCharacterLayoutIt;
2051 ++characterLayoutIt )
2053 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
2055 if( characterLayoutInfo.mIsVisible && characterLayoutInfo.mGlyphActor ) // White spaces and '\n' characters doesn't have a text-actor.
2057 //Add to the text-view.
2058 textView.Add( characterLayoutInfo.mGlyphActor );
2059 relayoutData.mGlyphActors.push_back( characterLayoutInfo.mGlyphActor );
2065 for( std::vector<RenderableActor>::iterator it = relayoutData.mEllipsizedGlyphActors.begin(),
2066 endIt = relayoutData.mEllipsizedGlyphActors.end();
2070 RenderableActor glyphActor = ( *it );
2072 //Add to the text-view.
2073 textView.Add( glyphActor );
2074 relayoutData.mGlyphActors.push_back( glyphActor );
2076 relayoutData.mEllipsizedGlyphActors.clear();
2079 RenderableActor CreateGlyphActor( const Text& text, const TextStyle& style, TextActorCache& cache )
2081 TextActor textActor = cache.RetrieveTextActor();
2085 // Update the text-actor.
2086 textActor.SetText( text );
2087 textActor.SetTextStyle( style );
2091 // The text-actor cache is empty. Create a new one.
2092 TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_OFF );
2093 textActor = TextActor::New( text, parameters );
2099 } // namespace TextViewRelayout
2101 } // namespace Internal
2103 } // namespace Toolkit