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 mIsNewLineCharacter( 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 SubLineLayoutInfo::SubLineLayoutInfo()
135 : mLineLength( 0.f ),
136 mMaxCharHeight( 0.f ),
141 SubLineLayoutInfo::~SubLineLayoutInfo()
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( const bool isWhiteSpace, const float width, const 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 Vector4 gradientColor;
221 void SetVisualParameters( CurrentTextActorInfo& currentTextActorInfo,
222 const TextView::VisualParameters& visualParameters,
223 TextView::RelayoutData& relayoutData,
224 const float lineHeight )
226 currentTextActorInfo.textActor.SetTextColor( currentTextActorInfo.color );
227 currentTextActorInfo.textActor.SetGradientColor( currentTextActorInfo.gradientColor );
228 currentTextActorInfo.textActor.SetGradientStartPoint( currentTextActorInfo.startPoint );
229 currentTextActorInfo.textActor.SetGradientEndPoint( currentTextActorInfo.endPoint );
231 // The italics offset is used in the offscreen rendering. When text is in italics, it may exceed the text-view's boundary
232 // due to the trick used to implement it.
233 const Radian& italicsAngle = currentTextActorInfo.textActor.GetItalicsAngle();
234 const float italicsOffset = lineHeight * std::tan( italicsAngle );
235 relayoutData.mTextLayoutInfo.mMaxItalicsOffset = std::max( relayoutData.mTextLayoutInfo.mMaxItalicsOffset, italicsOffset );
237 // Sets the sort modifier value.
238 currentTextActorInfo.textActor.SetSortModifier( visualParameters.mSortModifier );
240 // Enables or disables the blending.
241 currentTextActorInfo.textActor.SetBlendMode( !visualParameters.mSnapshotModeEnabled ? BlendingMode::ON : BlendingMode::OFF );
244 void CalculateSubLineLayout( const float parentWidth,
245 const TextViewProcessor::TextInfoIndices& indices,
246 const TextViewProcessor::LineLayoutInfo& lineLayoutInfo,
247 const HorizontalWrapType splitPolicy,
248 const float shrinkFactor,
249 SubLineLayoutInfo& subLineInfo )
251 subLineInfo.mLineLength = 0.f;
252 subLineInfo.mMaxCharHeight = 0.f;
253 subLineInfo.mMaxAscender = 0.f;
255 float endWhiteSpaceLength = 0.f;
257 std::size_t characterIndex = indices.mCharacterIndex;
258 float lineOffset = 0.f;
260 bool isFirstCharacter = true;
261 for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = lineLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex,
262 wordEndIt = lineLayoutInfo.mWordsLayoutInfo.end();
263 ( wordIt != wordEndIt ) && !found;
266 const TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordIt );
268 const float shrunkWordWidth = wordLayoutInfo.mSize.width * shrinkFactor;
269 const bool isWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType;
271 bool splitByCharacter = false;
273 switch( splitPolicy )
275 case WrapByCharacter:
277 splitByCharacter = true;
281 case WrapByLine: // Fall through
283 splitByCharacter = false;
286 case WrapByWordAndSplit:
288 splitByCharacter = ( shrunkWordWidth > parentWidth );
291 case WrapByLineAndSplit:
293 if( ( 0u != characterIndex ) ||
294 ( ( 0u == characterIndex ) && ( lineOffset + shrunkWordWidth > parentWidth ) ) )
296 splitByCharacter = true;
300 lineOffset += shrunkWordWidth;
301 splitByCharacter = false;
306 if( splitByCharacter )
308 for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator charIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + characterIndex,
309 charEndIt = wordLayoutInfo.mCharactersLayoutInfo.end();
310 ( charIt != charEndIt ) && !found;
313 const TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *charIt );
314 CalculateLineLength( isWhiteSpace, characterLayoutInfo.mSize.width * shrinkFactor, parentWidth, found, subLineInfo.mLineLength, endWhiteSpaceLength );
315 if( !found || isFirstCharacter )
317 subLineInfo.mMaxCharHeight = std::max( subLineInfo.mMaxCharHeight, characterLayoutInfo.mSize.height );
318 subLineInfo.mMaxAscender = std::max( subLineInfo.mMaxAscender, characterLayoutInfo.mAscender );
321 // All characters for word 'wordIndex' have been processed.
322 // Next word need to process all characters, so the characterIndex is reset to 0.
324 isFirstCharacter = false;
327 lineOffset += subLineInfo.mLineLength;
331 CalculateLineLength( isWhiteSpace, shrunkWordWidth, parentWidth, found, subLineInfo.mLineLength, endWhiteSpaceLength );
332 if( !found || isFirstCharacter )
334 subLineInfo.mMaxCharHeight = std::max( subLineInfo.mMaxCharHeight, wordLayoutInfo.mSize.height );
335 subLineInfo.mMaxAscender = std::max( subLineInfo.mMaxAscender, wordLayoutInfo.mAscender );
337 isFirstCharacter = false;
341 subLineInfo.mMaxCharHeight *= shrinkFactor;
342 subLineInfo.mMaxAscender *= shrinkFactor;
345 float CalculateXoffset( const Toolkit::Alignment::Type horizontalTextAlignment, const float parentWidth, const float wholeTextWidth )
347 float xOffset( 0.f );
348 switch( horizontalTextAlignment )
350 case Toolkit::Alignment::HorizontalLeft:
355 case Toolkit::Alignment::HorizontalCenter:
357 xOffset = 0.5f * ( parentWidth - wholeTextWidth );
360 case Toolkit::Alignment::HorizontalRight:
362 xOffset = parentWidth - wholeTextWidth;
367 DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateXoffset: Wrong horizontal text alignment. Did you set a vertical one?" );
374 float CalculateYoffset( const Toolkit::Alignment::Type verticalTextAlignment, const float parentHeight, const float wholeTextHeight )
376 float yOffset( 0.f );
377 switch( verticalTextAlignment )
379 case Toolkit::Alignment::VerticalTop:
384 case Toolkit::Alignment::VerticalCenter:
386 yOffset = 0.5f * ( parentHeight - wholeTextHeight );
389 case Toolkit::Alignment::VerticalBottom:
391 yOffset = parentHeight - wholeTextHeight;
396 DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateXoffset: Wrong vertical text alignment. Did you set an horizontal one?" );
403 float CalculateJustificationOffset( const Toolkit::TextView::LineJustification justification, const float wholeTextWidth, const float lineLength )
406 switch( justification )
408 case Toolkit::TextView::Left:
413 case Toolkit::TextView::Center:
415 offset = 0.5f * ( wholeTextWidth - lineLength );
418 case Toolkit::TextView::Right:
420 offset = wholeTextWidth - lineLength;
423 case Toolkit::TextView::Justified:
433 bool IsVisible( const Vector3& position, const Size& size, const Size& parentSize, const VisibilityTestType type )
435 bool visible = false;
441 // Whether the text-actor is fully inside the boundaries of the text-view.
442 visible = ( ( position.x >= 0.f ) && ( position.x + size.width <= parentSize.width ) &&
443 ( position.y >= size.height ) && ( position.y <= parentSize.height ) );
446 case FULLY_VISIBLE_WIDTH:
448 // Whether the text-actor is between the left and right boundaries of the text-view.
449 visible = ( ( position.x >= 0.f ) && ( position.x + size.width <= parentSize.width ) );
452 case FULLY_VISIBLE_HEIGHT:
454 // Whether the text-actor is between the top and bottom boundaries of the text-view.
455 visible = ( ( position.y >= size.height ) && ( position.y <= parentSize.height ) );
458 case PARTIALLY_VISIBLE:
460 // Whether the text-actor is partially inside the boundaries of the text-view.
461 visible = ( ( position.x < parentSize.width ) &&
462 ( position.x + size.width > 0.f ) &&
463 ( position.y > 0.f ) &&
464 ( position.y - size.height < parentSize.height ) );
467 case PARTIALLY_VISIBLE_WIDTH:
469 // Whether the text-actor is partially inside the area defined by the left and the right boundaries of the text-view.
470 // It may not be partially inside the text-view.
471 visible = ( ( position.x < parentSize.width ) &&
472 ( position.x + size.width > 0.f ) );
475 case PARTIALLY_VISIBLE_HEIGHT:
477 // Whether the text-actor is partially inside the area defined by the top and the bottom boundaries of the text-view.
478 // It may not be partially inside the text-view.
479 visible = ( ( position.y > 0.f ) &&
480 ( position.y - size.height < parentSize.height ) );
488 Vector2 CalculateRectParameters( const Vector2& p0, const Vector2& p1 )
490 const float gradient = ( p1.y - p0.y ) / ( p1.x - p0.x );
492 return Vector2( gradient, p0.y - gradient * p0.x );
495 void UpdateAlignment( const TextView::LayoutParameters& layoutParameters,
496 TextView::RelayoutData& relayoutData )
498 // Calculates an offset to align the whole text within the text-view's boundary accordingly with the set alignment and justification options.
499 // The offset could be negative if the whole text is bigger than the boundary of the text-view.
501 // If the exceed policy is ellipsize at the end, negative offsets are not wanted.
502 // In that case, it will align the line to the left and/or top, and ellipsize the end.
503 const bool ellipsizeAlignToLeft = ( layoutParameters.mExceedPolicy == TextView::EllipsizeEndOriginal ) ||
504 ( layoutParameters.mExceedPolicy == TextView::EllipsizeEnd ) ||
505 ( layoutParameters.mExceedPolicy == TextView::SplitEllipsizeEnd );
506 const bool ellipsizeAlignToTop = ( layoutParameters.mExceedPolicy == TextView::EllipsizeEnd ) ||
507 ( layoutParameters.mExceedPolicy == TextView::SplitEllipsizeEnd );
509 RelayoutParameters relayoutParameters;
511 // Calculates the vertical and horizontal offsets.
512 const float textHorizontalOffset = CalculateXoffset( layoutParameters.mHorizontalAlignment, relayoutData.mTextViewSize.width, relayoutData.mTextSizeForRelayoutOption.width );
513 const float textVerticalOffset = CalculateYoffset( layoutParameters.mVerticalAlignment, relayoutData.mTextViewSize.height, relayoutData.mTextSizeForRelayoutOption.height );
515 std::size_t lineJustificationIndex = 0; // Index to the first position of the vector which stores all line justification info.
516 std::size_t infoTableCharacterIndex = 0;
518 relayoutParameters.mIndices.mLineIndex = 0;
520 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
521 endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
522 lineLayoutIt != endLineLayoutIt;
523 ++lineLayoutIt, ++relayoutParameters.mIndices.mLineIndex )
525 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
527 float justificationOffset = 0.f;
529 relayoutParameters.mIndices.mWordIndex = 0;
531 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(),
532 endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.end();
533 wordLayoutIt != endWordLayoutIt;
534 ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
536 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
538 relayoutParameters.mIndices.mCharacterIndex = 0;
540 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
541 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
542 characterLayoutIt != endCharacterLayoutIt;
543 ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex )
545 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
547 // Calculate line justification offset.
548 if( lineJustificationIndex < relayoutData.mLineJustificationInfo.size() )
550 const TextView::LineJustificationInfo lineJustificationInfo( *( relayoutData.mLineJustificationInfo.begin() + lineJustificationIndex ) );
552 if( relayoutParameters.mIndices == lineJustificationInfo.mIndices )
554 justificationOffset = CalculateJustificationOffset( layoutParameters.mLineJustification, relayoutData.mTextSizeForRelayoutOption.width, lineJustificationInfo.mLineLength );
555 ++lineJustificationIndex; // increase the index to point the next position in the vector.
559 // Deletes the offsets if the exceed policies are EllipsizeEnd.
560 const float horizontalOffset = textHorizontalOffset + justificationOffset;
561 characterLayoutInfo.mOffset.x = ( ellipsizeAlignToLeft && ( horizontalOffset < 0.f ) ) ? 0.f : horizontalOffset;
562 characterLayoutInfo.mOffset.y = ( ellipsizeAlignToTop && ( textVerticalOffset < 0.f ) ) ? 0.f : textVerticalOffset;
564 // Updates the size and position table for text-input with the alignment offset.
565 Vector3 positionOffset( characterLayoutInfo.mPosition );
567 std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex;
568 Toolkit::TextView::CharacterLayoutInfo& characterTableInfo( *infoTableIt );
570 characterTableInfo.mPosition.x = positionOffset.x + characterLayoutInfo.mOffset.x;
571 characterTableInfo.mPosition.y = positionOffset.y + characterLayoutInfo.mOffset.y;
573 positionOffset.x += characterLayoutInfo.mAdvance * relayoutData.mShrinkFactor;
579 void CalculateBearing( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
580 TextView::RelayoutData& relayoutData )
592 // ggggg gggggggggg bb ggggg
593 // gg gg gggggggggg bb gg gg
594 // gg gg gggg bb gg gg
595 // gg gg gggg bb gg gg
596 // ggggg gg gggg bbbbbbb ggggg
597 // gg gg gggg bb bb gg
598 // g gg gggggggggg bb bb g gg
599 // ggggg gggggggggg bbbbbbb ggggg
608 // ggggg gggg gggg bb ggggg
609 // gg gg gggg gggg bbbbbbb gg gg
610 // gg gg gggg gggg bb bb gg gg
611 // gg gg gggggggggg bb bb gg gg
612 // ggggg gggggggggg bbbbbbb ggggg
615 // ggggg gg gggg ggggg
620 const Toolkit::TextView::LineLayoutInfo& lineInfo( *( relayoutData.mLines.end() - 1 ) );
621 const float bearingOffset = ( lineInfo.mSize.height - lineInfo.mAscender ) - ( characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender );
623 characterLayoutInfo.mPosition.y -= bearingOffset * relayoutData.mShrinkFactor;
626 void UpdateLayoutInfoTable( Vector4& minMaxXY,
627 TextViewProcessor::WordLayoutInfo& wordLayoutInfo,
628 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
629 RelayoutParameters& relayoutParameters,
630 TextView::RelayoutData& relayoutData )
632 // updates min and max position to calculate the text size for multiline policies.
633 minMaxXY.x = std::min( minMaxXY.x, characterLayoutInfo.mPosition.x );
634 minMaxXY.z = std::max( minMaxXY.z, characterLayoutInfo.mPosition.x + characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor );
636 minMaxXY.y = std::min( minMaxXY.y, characterLayoutInfo.mPosition.y - characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor );
637 minMaxXY.w = std::max( minMaxXY.w, characterLayoutInfo.mPosition.y );
639 // Adds layout info to be retrieved by external controls or applications.
640 Vector3 positionOffset( characterLayoutInfo.mPosition );
642 const float descender = characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender;
644 const Toolkit::TextView::CharacterLayoutInfo characterLayoutTableInfo( Size( characterLayoutInfo.mAdvance * relayoutData.mShrinkFactor,
645 characterLayoutInfo.mHeight * relayoutData.mShrinkFactor ),
647 ( TextViewProcessor::LineSeparator == wordLayoutInfo.mType ),
648 false, // VCC set the correct direction if needed.
652 relayoutData.mCharacterLayoutInfoTable.push_back( characterLayoutTableInfo );
654 positionOffset.x += characterLayoutInfo.mAdvance * relayoutData.mShrinkFactor;
657 void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters,
658 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
659 RelayoutParameters& relayoutParameters,
660 FadeParameters& fadeParameters,
661 TextView::RelayoutData& relayoutData )
663 if( ( TextView::Fade != layoutParameters.mExceedPolicy ) &&
664 ( TextView::SplitFade != layoutParameters.mExceedPolicy ) &&
665 ( TextView::FadeOriginal != layoutParameters.mExceedPolicy ) &&
666 ( TextView::OriginalFade != layoutParameters.mExceedPolicy ) )
672 // Calculates visibility of a text-actor according the exceed policies.
674 // position + alignment offset.
675 const Vector3 position( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x,
676 characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y,
677 characterLayoutInfo.mPosition.z );
679 // Whether the text actor is fully, partially or non visible (according exceed policies).
680 switch( layoutParameters.mExceedPolicy )
684 // All text-actors which are not completely inside the text-view's boundaries are set as non visible.
685 // All text-actors which are partially inside the text-view's boundaries are set as partially visible.
686 if( !IsVisible( position,
687 characterLayoutInfo.mSize,
688 relayoutData.mTextViewSize,
691 relayoutParameters.mIsVisible = false;
692 if( IsVisible( position,
693 characterLayoutInfo.mSize,
694 relayoutData.mTextViewSize,
695 PARTIALLY_VISIBLE ) )
697 fadeParameters.mIsPartiallyVisible = true;
699 // Checks if a text-actor is exceeding more than one boundary as this case is not supported.
700 if( IsExceedingWidth( position,
701 characterLayoutInfo.mSize,
702 relayoutData.mTextViewSize ) &&
703 IsExceedingHeight( position,
704 characterLayoutInfo.mSize,
705 relayoutData.mTextViewSize ) )
707 // Combination not fully supported by text-view.
708 // Need to check if text-actor really supports this combination.
709 fadeParameters.mIsPartiallyVisible = false;
715 case TextView::FadeOriginal:
717 // All text-actors which are not completely between the left and right text-view's boundaries are set as non visible.
718 // All text-actors which are partially inside the text-view's boundaries are set as partially visible.
719 if( !IsVisible( position,
720 characterLayoutInfo.mSize,
721 relayoutData.mTextViewSize,
722 FULLY_VISIBLE_WIDTH ) )
724 relayoutParameters.mIsVisible = false;
725 if( IsVisible( position,
726 characterLayoutInfo.mSize,
727 relayoutData.mTextViewSize,
728 PARTIALLY_VISIBLE_WIDTH ) )
730 fadeParameters.mIsPartiallyVisible = true;
735 case TextView::OriginalFade:
736 case TextView::SplitFade: // Fallthrough
738 // All text-actors which are not completely between the top and bottom text-view's boundaries are set as non visible.
739 // All text-actors which are partially inside the text-view's boundaries are set as partially visible.
740 if( !IsVisible( position,
741 characterLayoutInfo.mSize,
742 relayoutData.mTextViewSize,
743 FULLY_VISIBLE_HEIGHT ) )
745 relayoutParameters.mIsVisible = false;
746 if( IsVisible( position,
747 characterLayoutInfo.mSize,
748 relayoutData.mTextViewSize,
749 PARTIALLY_VISIBLE_HEIGHT ) )
751 fadeParameters.mIsPartiallyVisible = true;
758 DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateVisibilityForFade. Wrong exceed policies." )
763 if( relayoutParameters.mIsVisible || fadeParameters.mIsPartiallyVisible )
765 characterLayoutInfo.mIsVisible = true;
767 const Size size = characterLayoutInfo.mSize * relayoutData.mShrinkFactor;
768 const float characterPositionPlusWidth = position.x + size.width;
769 const float characterPositionMinusHeight = position.y - size.height;
771 // Calculates which edges need to be faded-out.
772 bool rightFadeOut = false;
773 bool leftFadeOut = false;
774 bool bottomFadeOut = false;
775 bool topFadeOut = false;
777 switch( layoutParameters.mExceedPolicy )
781 // All text-actors exceeding any of the boundaries will be faded-out.
782 rightFadeOut = ( characterPositionPlusWidth > fadeParameters.mRightFadeThreshold );
783 leftFadeOut = ( position.x < fadeParameters.mLeftFadeThreshold );
784 bottomFadeOut = ( position.y > fadeParameters.mBottomFadeThreshold );
785 topFadeOut = ( characterPositionMinusHeight < fadeParameters.mTopFadeThreshold );
788 case TextView::FadeOriginal:
790 // Only text-actors exceeding the left or the right boundaries will be faded-out.
791 rightFadeOut = ( characterPositionPlusWidth > fadeParameters.mRightFadeThreshold );
792 leftFadeOut = ( position.x < fadeParameters.mLeftFadeThreshold );
795 case TextView::SplitFade:
796 case TextView::OriginalFade: //Fallthrough
798 // Only text-actors exceeding the top or the bottom boundaries will be faded-out.
799 bottomFadeOut = ( position.y > fadeParameters.mBottomFadeThreshold );
800 topFadeOut = ( characterPositionMinusHeight < fadeParameters.mTopFadeThreshold );
805 DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateVisibilityForFade. Wrong exceed policies." );
810 // Calculates gradient parameters for a text-actor.
811 Vector4 gradientColor = Vector4::ZERO;
812 Vector2 startPoint = Vector2::ZERO;
813 Vector2 endPoint = Vector2::ZERO;
815 if( !( rightFadeOut && leftFadeOut ) )
817 // Current implementation can't set gradient parameters for a text-actor exceeding at the same time the left and the right boundaries.
820 gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
822 // Calculates gradient coeficients.
823 characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mRightAlphaCoeficients.x * position.x + fadeParameters.mRightAlphaCoeficients.y );
824 gradientColor.a *= std::max( 0.f, fadeParameters.mRightAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mRightAlphaCoeficients.y );
826 startPoint = Vector2( std::max( 0.f, ( fadeParameters.mRightFadeThresholdOffset - position.x ) / size.width ), 0.5f );
827 endPoint = Vector2( std::min( 1.f, ( relayoutData.mTextViewSize.width - position.x ) / size.width ), 0.5f );
829 else if( leftFadeOut )
831 gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
833 // Calculates gradient coeficients.
834 characterLayoutInfo.mColorAlpha = std::min( 1.f, fadeParameters.mLeftAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mLeftAlphaCoeficients.y );
835 gradientColor.a *= gradientColor.a * std::max( 0.f, fadeParameters.mLeftAlphaCoeficients.x * position.x + fadeParameters.mLeftAlphaCoeficients.y );
837 startPoint = Vector2( std::max( 0.f, ( fadeParameters.mLeftFadeThresholdOffset - position.x ) / size.width ), 0.5f );
838 endPoint = Vector2( std::min( 1.f, -position.x / size.width ), 0.5f );
842 if( !( bottomFadeOut && topFadeOut ) )
844 // Current implementation can't set gradient parameters for a text-actor exceeding at the same time the top and the bottom boundaries.
847 gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
849 // Calculates gradient coeficients.
850 characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mBottomAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mBottomAlphaCoeficients.y );
851 gradientColor.a *= std::max( 0.f, fadeParameters.mBottomAlphaCoeficients.x * position.y + fadeParameters.mBottomAlphaCoeficients.y );
853 startPoint = Vector2( 0.5f, std::max( 0.f, ( fadeParameters.mBottomFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) );
854 endPoint = Vector2( 0.5f, std::min( 1.f, ( relayoutData.mTextViewSize.height - characterPositionMinusHeight ) / size.height ) );
856 else if( topFadeOut )
858 gradientColor = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
860 // Calculates gradient coeficients.
861 characterLayoutInfo.mColorAlpha *= gradientColor.a * std::min( 1.f, fadeParameters.mTopAlphaCoeficients.x * position.y + fadeParameters.mTopAlphaCoeficients.y );
862 gradientColor.a *= std::max( 0.f, fadeParameters.mTopAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mTopAlphaCoeficients.y );
864 startPoint = Vector2( 0.5f, std::max( 0.f, ( fadeParameters.mTopFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) );
865 endPoint = Vector2( 0.5f, std::min( 1.f, -characterPositionMinusHeight / size.height ) );
869 characterLayoutInfo.mGradientColor = gradientColor;
870 characterLayoutInfo.mStartPoint = startPoint;
871 characterLayoutInfo.mEndPoint = endPoint;
875 characterLayoutInfo.mIsVisible = false;
879 bool CalculateVisibilityForEllipsizeEndOriginal( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
880 const EllipsizeParameters& ellipsizeParameters )
882 bool isPartiallyVisible = false;
884 if( !IsVisible( ellipsizeParameters.mPosition,
885 characterLayoutInfo.mSize,
886 ellipsizeParameters.mEllipsizeBoundary,
887 FULLY_VISIBLE_WIDTH ) )
889 // The character doesn't fit in the text-view's width.
890 characterLayoutInfo.mIsVisible = false;
892 // Checks if the character is partially visible (it's cut by the boundary)
893 isPartiallyVisible = IsVisible( ellipsizeParameters.mPosition,
894 characterLayoutInfo.mSize,
895 ellipsizeParameters.mEllipsizeBoundary,
896 PARTIALLY_VISIBLE_WIDTH );
900 // The character fits in the text-view's width. Set it to visible.
901 characterLayoutInfo.mIsVisible = true;
904 return isPartiallyVisible;
907 bool CalculateVisibilityForEllipsizeEnd( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
908 const EllipsizeParameters& ellipsizeParameters )
910 bool isPartiallyVisible = false;
912 if( !IsVisible( ellipsizeParameters.mPosition,
913 characterLayoutInfo.mSize,
914 ellipsizeParameters.mEllipsizeBoundary,
917 // The character is not fully visible. Needs to check if it's partially visible.
918 characterLayoutInfo.mIsVisible = false;
920 // Checks if the character doesn't cut the bottom edge of the text-view.
921 const bool fullyVisibleHeight = IsVisible( ellipsizeParameters.mPosition,
922 characterLayoutInfo.mSize,
923 ellipsizeParameters.mEllipsizeBoundary,
924 FULLY_VISIBLE_HEIGHT );
926 // Checks if the character cuts the right edge of the text-view.
927 const bool partiallyVisibleWidth = IsVisible( ellipsizeParameters.mPosition,
928 characterLayoutInfo.mSize,
929 ellipsizeParameters.mEllipsizeBoundary,
930 PARTIALLY_VISIBLE_WIDTH );
932 // Character will be ellipsized if it cuts the right edge of the text-view but fits completely in the text-view's height.
933 isPartiallyVisible = ( fullyVisibleHeight && partiallyVisibleWidth );
937 // The character fits in the boundary of the text-view. Set it to visible.
938 characterLayoutInfo.mIsVisible = true;
941 return isPartiallyVisible;
944 void CalculateVisibilityForEllipsize( const Internal::TextView::LayoutParameters& layoutParameters,
945 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo,
946 EllipsizeParameters& ellipsizeParameters,
947 TextView::RelayoutData& relayoutData )
949 // Calculates visibility for EllipsizeEnd exceed policies.
951 // 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.
952 // If a character is cut by this boundary and the whole line (if the multi-line policy is split-by-new-line-char)
953 // 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.
955 // Position of the character used to do the visibility test.
956 ellipsizeParameters.mPosition = Vector3( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x,
957 characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y,
958 characterLayoutInfo.mPosition.z );
960 // 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).
961 bool isPartiallyVisible = false;
963 // Checks if the whole line or the whole word fits in the text-view's width accordingly with the multiline policy.
964 const bool fitsInWidth = ( Toolkit::TextView::SplitByNewLineChar == layoutParameters.mMultilinePolicy ) ? ellipsizeParameters.mLineFits: ellipsizeParameters.mWordFits;
966 // Will only ellipsize the text if it cuts the right vertical edge and it doesn't fit in the text-view's width.
969 // The line or word fits completely inside the text-view's width. Nothing else to do.
970 characterLayoutInfo.mIsVisible = true;
974 // The line or word doesn't fit in the text-view's width.
976 // Calculates visibility for each type of ellipsize policies.
977 switch( layoutParameters.mExceedPolicy )
979 case TextView::EllipsizeEndOriginal:
981 // 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.
983 isPartiallyVisible = CalculateVisibilityForEllipsizeEndOriginal( characterLayoutInfo,
984 ellipsizeParameters );
988 case TextView::SplitEllipsizeEnd:
989 case TextView::EllipsizeEnd:
991 // Ellipsizes the text if it doesn't fit in the width and fully fits in the text-view's height.
993 isPartiallyVisible = CalculateVisibilityForEllipsizeEnd( characterLayoutInfo,
994 ellipsizeParameters );
1000 DALI_ASSERT_DEBUG( !"TextViewRelayout::CalculateVisibilityForEllipsize. Wrong exceed value." );
1006 // If the current character is not fully visible but is partially visible, it is cut by the boundary of the text-view.
1007 // In that case, the charater needs to be replaced by the ellipsize text.
1008 ellipsizeParameters.mCreateEllipsizedTextActors = ( !characterLayoutInfo.mIsVisible && isPartiallyVisible );
1011 void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters,
1012 TextView::RelayoutData& relayoutData )
1014 // 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.
1015 // The code bellow creates the text-actors needed for the ellipsize text.
1017 // Set ellipsize's position by the end of visible text.
1018 Vector3 ellipsizePosition = ellipsizeParameters.mPosition;
1019 // Stores current ellipsize text.
1021 // Stores current ellipsize style.
1022 TextStyle ellipsizeStyle;
1023 // Stores the current size.
1025 //Whether current glyph is an emoticon.
1026 bool isColorGlyph = false;
1028 float bearingOffset = 0.f;
1030 // Create ellipsize text-actor.
1031 for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator ellipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.begin(),
1032 endEllipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.end();
1033 ellipsizeCharacterLayoutIt != endEllipsizeCharacterLayoutIt;
1034 ++ellipsizeCharacterLayoutIt )
1036 const TextViewProcessor::CharacterLayoutInfo& ellipsizeCharacterLayoutInfo( *ellipsizeCharacterLayoutIt );
1039 ( isColorGlyph != ellipsizeCharacterLayoutInfo.mIsColorGlyph ) ||
1040 ( ellipsizeStyle != ellipsizeCharacterLayoutInfo.mStyledText.mStyle ) )
1042 // The style is different, so a new text-actor is needed.
1043 if( !ellipsizeText.IsEmpty() )
1045 // It only creates a text-actor if there is any text.
1046 RenderableActor ellipsizeGlyphActor = CreateGlyphActor( ellipsizeText, ellipsizeStyle, relayoutData.mTextActorCache );
1047 ellipsizeGlyphActor.SetSize( ellipsizeSize );
1048 ellipsizeGlyphActor.SetPosition( Vector3( ellipsizePosition.x, ellipsizePosition.y - bearingOffset, ellipsizePosition.z ) );
1050 // Updates the position for the next text-actor.
1051 ellipsizePosition.x += ellipsizeSize.width;
1053 // Adds the text-actor to the list.
1054 relayoutData.mEllipsizedGlyphActors.push_back( ellipsizeGlyphActor );
1057 // Resets the current ellipsize info.
1058 ellipsizeText = ellipsizeCharacterLayoutInfo.mStyledText.mText;
1059 ellipsizeStyle = ellipsizeCharacterLayoutInfo.mStyledText.mStyle;
1060 ellipsizeSize = ellipsizeCharacterLayoutInfo.mSize;
1061 isColorGlyph = ellipsizeCharacterLayoutInfo.mIsColorGlyph;
1063 bearingOffset = ( ellipsizeParameters.mLineDescender - ( ellipsizeCharacterLayoutInfo.mSize.height - ellipsizeCharacterLayoutInfo.mAscender ) ) * relayoutData.mShrinkFactor;
1067 // Updates text and size with the new character.
1068 ellipsizeText.Append( ellipsizeCharacterLayoutInfo.mStyledText.mText );
1069 TextViewProcessor::UpdateSize( ellipsizeSize, ellipsizeCharacterLayoutInfo.mSize );
1074 if( !ellipsizeText.IsEmpty() )
1076 // Creates the last glyph-actor.
1077 RenderableActor ellipsizeGlyphActor = CreateGlyphActor( ellipsizeText, ellipsizeStyle, relayoutData.mTextActorCache );
1078 ellipsizeGlyphActor.SetSize( ellipsizeSize );
1079 ellipsizeGlyphActor.SetPosition( Vector3( ellipsizePosition.x, ellipsizePosition.y - bearingOffset, ellipsizePosition.z ) );
1081 // Adds the glyph-actor to the list.
1082 relayoutData.mEllipsizedGlyphActors.push_back( ellipsizeGlyphActor );
1086 void EllipsizeLine( const TextView::LayoutParameters& layoutParameters,
1087 EllipsizeParameters& ellipsizeParameters,
1088 TextView::RelayoutData& relayoutData )
1090 // Traverses the text layout info from the first character of the laid out line
1091 // to the last one setting to each character its visibility. If needed, it adds the ellipsize text (...).
1093 // Indices to the first character of the laid out line.
1094 TextViewProcessor::TextInfoIndices firstIndices;
1095 TextViewProcessor::GetIndicesFromGlobalCharacterIndex( ellipsizeParameters.mFirstIndex,
1096 relayoutData.mTextLayoutInfo,
1099 // Indices to the last character of the laid out line.
1100 TextViewProcessor::TextInfoIndices lastIndices;
1101 TextViewProcessor::GetIndicesFromGlobalCharacterIndex( ellipsizeParameters.mLastIndex,
1102 relayoutData.mTextLayoutInfo,
1105 // Defines a boundary by substracting the ellipsize-text's width to the text-view's width.
1106 // This is the boundary used to check if a character have to be ellipsized.
1107 ellipsizeParameters.mEllipsizeBoundary = relayoutData.mTextViewSize;
1108 ellipsizeParameters.mEllipsizeBoundary.width -= relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mSize.width;
1110 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin() + firstIndices.mLineIndex,
1111 endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin() + lastIndices.mLineIndex + 1u;
1112 lineLayoutIt != endLineLayoutIt;
1115 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
1117 ellipsizeParameters.mLineFits = ellipsizeParameters.mIsLineWidthFullyVisible && ellipsizeParameters.mIsLineHeightFullyVisible && ellipsizeParameters.mIsNextLineFullyVisibleHeight;
1119 if( !ellipsizeParameters.mIsNextLineFullyVisibleHeight )
1121 ellipsizeParameters.mEllipsizeBoundary.width = ellipsizeParameters.mLineWidth;
1124 bool firstWord = true;
1125 bool lastWord = false;
1127 std::size_t wordCount = 0u;
1129 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin() + firstIndices.mWordIndex,
1130 endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin() + lastIndices.mWordIndex + 1u;
1131 wordLayoutIt != endWordLayoutIt;
1132 ++wordLayoutIt, ++wordCount )
1134 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
1136 if( wordCount == lastIndices.mWordIndex - firstIndices.mWordIndex )
1141 const std::size_t firstCharacterIndex = firstWord ? firstIndices.mCharacterIndex : 0u;
1142 const std::size_t lastCharacterIndex = lastWord ? lastIndices.mCharacterIndex : wordLayoutInfo.mCharactersLayoutInfo.size() - 1u;
1143 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + firstCharacterIndex,
1144 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + lastCharacterIndex + 1u;
1145 characterLayoutIt != endCharacterLayoutIt;
1146 ++characterLayoutIt )
1148 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
1150 if( ellipsizeParameters.mEllipsizeLine )
1152 // Calculates the character visibility and whether it needs to be replace by ellipsized text.
1153 CalculateVisibilityForEllipsize( layoutParameters,
1154 characterLayoutInfo,
1155 ellipsizeParameters,
1158 if( ellipsizeParameters.mCreateEllipsizedTextActors )
1160 // Create ellipsize text-actors if the character needs to be replaced.
1161 CreateEllipsizeTextActor( ellipsizeParameters,
1167 if( ( TextView::EllipsizeEnd == layoutParameters.mExceedPolicy ) ||
1168 ( TextView::SplitEllipsizeEnd == layoutParameters.mExceedPolicy ))
1170 if( !ellipsizeParameters.mIsLineHeightFullyVisible )
1172 // Make characters invisible.
1173 characterLayoutInfo.mIsVisible = false;
1183 void SetTextVisible( TextView::RelayoutData& relayoutData )
1185 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
1186 endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
1187 lineLayoutIt != endLineLayoutIt;
1190 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
1192 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(),
1193 endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.end();
1194 wordLayoutIt != endWordLayoutIt;
1197 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
1199 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
1200 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
1201 characterLayoutIt != endCharacterLayoutIt;
1202 ++characterLayoutIt )
1204 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
1206 characterLayoutInfo.mIsVisible = true;
1207 characterLayoutInfo.mGradientColor = Vector4::ZERO;
1208 characterLayoutInfo.mStartPoint = Vector2::ZERO;
1209 characterLayoutInfo.mEndPoint = Vector2::ZERO;
1210 characterLayoutInfo.mColorAlpha = characterLayoutInfo.mStyledText.mStyle.GetTextColor().a;
1215 // Updates the visibility for text-input..
1216 for( std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator it = relayoutData.mCharacterLayoutInfoTable.begin(),
1217 endIt = relayoutData.mCharacterLayoutInfoTable.end();
1221 Toolkit::TextView::CharacterLayoutInfo& characterLayoutInfo( *it );
1223 characterLayoutInfo.mIsVisible = true;
1227 void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters,
1228 const TextView::VisualParameters& visualParameters,
1229 TextView::RelayoutData& relayoutData )
1231 RelayoutParameters relayoutParameters;
1232 FadeParameters fadeParameters;
1234 // 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.
1235 fadeParameters.mRightFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mRight );
1236 fadeParameters.mRightFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mRight > 0 ? fadeParameters.mRightFadeBoundary : MINIMUM_FADE_BOUNDARY );
1237 fadeParameters.mRightFadeThreshold = relayoutData.mTextViewSize.width - fadeParameters.mRightFadeBoundary;
1238 fadeParameters.mRightFadeThresholdOffset = relayoutData.mTextViewSize.width - fadeParameters.mRightFadeBoundaryOffset;
1239 fadeParameters.mLeftFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mLeft );
1240 fadeParameters.mLeftFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mLeft > 0 ? fadeParameters.mLeftFadeBoundary : MINIMUM_FADE_BOUNDARY );
1241 fadeParameters.mLeftFadeThreshold = fadeParameters.mLeftFadeBoundary;
1242 fadeParameters.mLeftFadeThresholdOffset = fadeParameters.mLeftFadeBoundaryOffset;
1243 fadeParameters.mTopFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mTop );
1244 fadeParameters.mTopFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mTop > 0 ? fadeParameters.mTopFadeBoundary : MINIMUM_FADE_BOUNDARY );
1245 fadeParameters.mTopFadeThreshold = fadeParameters.mTopFadeBoundary;
1246 fadeParameters.mTopFadeThresholdOffset = fadeParameters.mTopFadeBoundaryOffset;
1247 fadeParameters.mBottomFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mBottom );
1248 fadeParameters.mBottomFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mBottom > 0 ? fadeParameters.mBottomFadeBoundary : MINIMUM_FADE_BOUNDARY );
1249 fadeParameters.mBottomFadeThreshold = relayoutData.mTextViewSize.height - fadeParameters.mBottomFadeBoundary;
1250 fadeParameters.mBottomFadeThresholdOffset = relayoutData.mTextViewSize.height - fadeParameters.mBottomFadeBoundaryOffset;
1252 // Calculates the fade out rect coeficients for the right, left, top and bottom sides of the text-view.
1253 fadeParameters.mRightAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mRightFadeThresholdOffset, 1.f ), Vector2( relayoutData.mTextViewSize.width, 0.f ) );
1254 fadeParameters.mLeftAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mLeftFadeThresholdOffset, 1.f ), Vector2( 0.f, 0.f ) );
1255 fadeParameters.mTopAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mTopFadeThresholdOffset, 1.f ), Vector2( 0.f, 0.f ) );
1256 fadeParameters.mBottomAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mBottomFadeThresholdOffset, 1.f ), Vector2( relayoutData.mTextViewSize.height, 0.f ) );
1258 // Traverses all characters and calculates the visibility.
1260 std::size_t infoTableCharacterIndex = 0;
1262 relayoutParameters.mIndices.mLineIndex = 0;
1264 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
1265 endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
1266 lineLayoutIt != endLineLayoutIt;
1267 ++lineLayoutIt, ++relayoutParameters.mIndices.mLineIndex )
1269 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
1271 relayoutParameters.mIndices.mWordIndex = 0;
1273 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(),
1274 endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.end();
1275 wordLayoutIt != endWordLayoutIt;
1276 ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
1278 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
1280 relayoutParameters.mIsFirstCharacterOfWord = true;
1281 relayoutParameters.mWordSize = wordLayoutInfo.mSize;
1282 relayoutParameters.mIndices.mCharacterIndex = 0;
1284 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
1285 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
1286 characterLayoutIt != endCharacterLayoutIt;
1287 ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex )
1289 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
1291 relayoutParameters.mIsVisible = true;
1292 fadeParameters.mIsPartiallyVisible = false;
1294 // Calculates the visibility for the current character.
1295 CalculateVisibilityForFade( layoutParameters,
1296 characterLayoutInfo,
1301 // Updates the visibility for text-input..
1302 std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex;
1304 Toolkit::TextView::CharacterLayoutInfo& characterLayoutTableInfo( *it );
1306 characterLayoutTableInfo.mIsVisible = relayoutParameters.mIsVisible;
1308 relayoutParameters.mIsFirstCharacterOfWord = false;
1314 void UpdateVisibilityForEllipsize( const TextView::LayoutParameters& layoutParameters,
1315 const TextView::VisualParameters& visualParameters,
1316 TextView::RelayoutData& relayoutData )
1318 // Traverses the laid-out lines and checks which ones doesn't fit in the text-view's boundary.
1319 for( Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineInfoIt = relayoutData.mLines.begin(), endLineInfoIt = relayoutData.mLines.end();
1320 lineInfoIt != endLineInfoIt;
1323 const Toolkit::TextView::LineLayoutInfo& lineInfo( *lineInfoIt );
1325 // To check if a laid-out line fits in the text-view's boundary,
1326 // get the position of the first character is needed and do the test
1327 // with the laid-out line size.
1329 // An bearing offset may have been applied to the first character so it's needed to
1330 // get the start position of the line.
1332 // Some parameters used in the CalculateVisibilityForEllipsize() function.
1333 EllipsizeParameters ellipsizeParameters;
1335 // Retrieves the first index and the last index of the line.
1336 ellipsizeParameters.mFirstIndex = lineInfo.mCharacterGlobalIndex;
1337 ellipsizeParameters.mLastIndex = 0;
1338 if( ( lineInfoIt + 1 ) != endLineInfoIt )
1340 const Toolkit::TextView::LineLayoutInfo& nextLineInfo( *( lineInfoIt + 1 ) );
1341 ellipsizeParameters.mLastIndex = nextLineInfo.mCharacterGlobalIndex - 1;
1345 ellipsizeParameters.mLastIndex = relayoutData.mCharacterLayoutInfoTable.size() - 1;
1348 // Retrieves the first character of the line and build the position of the line with the bearing.
1349 const Toolkit::TextView::CharacterLayoutInfo& characterInfo = *( relayoutData.mCharacterLayoutInfoTable.begin() + ellipsizeParameters.mFirstIndex );
1351 // Calculates the bearing offset applied to the first character.
1352 const float bearingOffset = ( lineInfo.mSize.height - lineInfo.mAscender ) - characterInfo.mDescender;
1354 // Build the position of the line by removing the bearing offset from the first character's position.
1355 const Vector3 position( characterInfo.mPosition.x,
1356 characterInfo.mPosition.y + bearingOffset,
1357 characterInfo.mPosition.z );
1359 // Checks if the line needs to be ellipsized,
1360 ellipsizeParameters.mIsLineWidthFullyVisible = IsVisible( position,
1362 relayoutData.mTextViewSize,
1363 FULLY_VISIBLE_WIDTH );
1365 // If the exceed policy is EllipsizeEndOriginal it's enough to check
1366 // if the line fits in the width.
1367 ellipsizeParameters.mEllipsizeLine = !ellipsizeParameters.mIsLineWidthFullyVisible;
1369 // If the exceed policy is EllipsizeEnd, it's needed to check if the next line exceeds the text-view's height.
1370 // If the next line exceeds the text-view height then it's going to be invisible and current line needs to be ellipsized.
1371 ellipsizeParameters.mIsLineHeightFullyVisible = true;
1372 ellipsizeParameters.mIsNextLineFullyVisibleHeight = true;
1373 if( ( TextView::EllipsizeEnd == layoutParameters.mExceedPolicy ) ||
1374 ( TextView::SplitEllipsizeEnd == layoutParameters.mExceedPolicy ) )
1376 // Need to check if there is lines which doesn't fit in the height.
1378 ellipsizeParameters.mIsLineHeightFullyVisible = IsVisible( position,
1380 relayoutData.mTextViewSize,
1381 FULLY_VISIBLE_HEIGHT );
1383 ellipsizeParameters.mEllipsizeLine = ellipsizeParameters.mEllipsizeLine && ellipsizeParameters.mIsLineHeightFullyVisible;
1385 if( ellipsizeParameters.mIsLineHeightFullyVisible && !ellipsizeParameters.mEllipsizeLine )
1387 // Current line is not ellipsized.
1388 // Need to check if there is a next line and if it's not visible. If there is, current line needs to be ellipsized.
1389 Toolkit::TextView::LineLayoutInfoContainer::const_iterator nextLineInfoIt = lineInfoIt + 1;
1390 if( nextLineInfoIt != endLineInfoIt )
1392 // Retrives the position of the first character of the line and remove
1393 // the bearing offset to build to build the position of the line.
1394 const Toolkit::TextView::LineLayoutInfo& nextLineInfo( *nextLineInfoIt );
1395 const Toolkit::TextView::CharacterLayoutInfo& characterInfo = *( relayoutData.mCharacterLayoutInfoTable.begin() + nextLineInfo.mCharacterGlobalIndex );
1397 const float bearingOffset = ( ( lineInfo.mSize.height - lineInfo.mAscender ) - characterInfo.mDescender ) * relayoutData.mShrinkFactor;
1399 const Vector3 position( characterInfo.mPosition.x,
1400 characterInfo.mPosition.y + bearingOffset,
1401 characterInfo.mPosition.z );
1403 ellipsizeParameters.mIsNextLineFullyVisibleHeight = IsVisible( position,
1405 relayoutData.mTextViewSize,
1406 FULLY_VISIBLE_HEIGHT );
1408 // If the next line is not visible, current line have to be ellipsized.
1409 ellipsizeParameters.mEllipsizeLine = !ellipsizeParameters.mIsNextLineFullyVisibleHeight;
1414 if( !ellipsizeParameters.mIsNextLineFullyVisibleHeight )
1416 ellipsizeParameters.mLineWidth = position.x + lineInfo.mSize.width - relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mSize.width;
1419 // Sets the line descender.
1420 ellipsizeParameters.mLineDescender = lineInfo.mSize.height - lineInfo.mAscender;
1422 // At this point, ellipsizeLine distinguish if a piece of line have to be ellipsized or not.
1423 EllipsizeLine( layoutParameters, ellipsizeParameters, relayoutData );
1427 void UpdateVisibility( const TextView::LayoutParameters& layoutParameters,
1428 const TextView::VisualParameters& visualParameters,
1429 TextView::RelayoutData& relayoutData )
1431 switch( layoutParameters.mExceedPolicy )
1433 case TextView::FadeOriginal:
1434 case TextView::OriginalFade:
1435 case TextView::Fade:
1436 case TextView::SplitFade: // Fall through
1438 UpdateVisibilityForFade( layoutParameters,
1443 case TextView::EllipsizeEndOriginal:
1444 case TextView::SplitEllipsizeEnd:
1445 case TextView::EllipsizeEnd: // Fall through
1447 // Set first all characters to visible as UpdateVisibilityForEllipsize() doesn't traverse all of them.
1448 SetTextVisible( relayoutData );
1450 UpdateVisibilityForEllipsize( layoutParameters,
1457 SetTextVisible( relayoutData );
1463 void UpdateTextActorInfo( const TextView::VisualParameters& visualParameters,
1464 TextView::RelayoutData& relayoutData )
1466 CurrentTextActorInfo currentTextActorInfo;
1468 // Traverses the text-actor and layout info data structures.
1469 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
1470 endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
1471 lineLayoutIt != endLineLayoutIt;
1474 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
1476 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(),
1477 endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.end();
1478 wordLayoutIt != endWordLayoutIt;
1481 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
1483 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
1484 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
1485 characterLayoutIt != endCharacterLayoutIt;
1486 ++characterLayoutIt )
1488 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
1490 if( characterLayoutInfo.mIsColorGlyph )
1492 ImageActor imageActor = ImageActor::DownCast( characterLayoutInfo.mGlyphActor );
1494 if( characterLayoutInfo.mSetText )
1496 GlyphImage image = GlyphImage::New( characterLayoutInfo.mStyledText.mText[0] );
1500 imageActor.SetImage( image );
1502 characterLayoutInfo.mSetText = false;
1505 imageActor.SetPosition( Vector3( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x,
1506 characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y,
1507 characterLayoutInfo.mPosition.z ) );
1508 imageActor.SetSize( characterLayoutInfo.mSize );
1510 // Sets the sort modifier value.
1511 imageActor.SetSortModifier( visualParameters.mSortModifier );
1515 TextActor textActor = TextActor::DownCast( characterLayoutInfo.mGlyphActor );
1518 // There is a new text-actor. Set text and everything to the previous one.
1519 if( currentTextActorInfo.textActor )
1521 currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
1522 currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
1523 currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
1525 SetVisualParameters( currentTextActorInfo,
1528 lineLayoutInfo.mSize.height );
1531 currentTextActorInfo.text = characterLayoutInfo.mStyledText.mText;
1532 currentTextActorInfo.position = Vector3( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x,
1533 characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y,
1534 characterLayoutInfo.mPosition.z );
1535 currentTextActorInfo.size = characterLayoutInfo.mSize * relayoutData.mShrinkFactor;
1537 currentTextActorInfo.color = characterLayoutInfo.mStyledText.mStyle.GetTextColor();
1538 currentTextActorInfo.color.a = characterLayoutInfo.mColorAlpha;
1540 currentTextActorInfo.gradientColor = characterLayoutInfo.mGradientColor;
1541 currentTextActorInfo.startPoint = characterLayoutInfo.mStartPoint;
1542 currentTextActorInfo.endPoint = characterLayoutInfo.mEndPoint;
1544 // Update the current text-actor.
1545 currentTextActorInfo.textActor = textActor;
1549 // If this character layout has no text-actor is because this character has the same style than previous one.
1550 // Add the character to the current text-actor and update the size.
1551 if( characterLayoutInfo.mIsVisible && ( TextViewProcessor::LineSeparator != wordLayoutInfo.mType ) )
1553 currentTextActorInfo.text.Append( characterLayoutInfo.mStyledText.mText );
1555 currentTextActorInfo.position.y = std::min( currentTextActorInfo.position.y, ( characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y ) );
1556 currentTextActorInfo.size.width += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor;
1557 currentTextActorInfo.size.height = std::max( currentTextActorInfo.size.height, characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor );
1564 if( !currentTextActorInfo.text.IsEmpty() )
1566 if( currentTextActorInfo.textActor )
1568 currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
1569 currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
1570 currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
1572 SetVisualParameters( currentTextActorInfo,
1575 lineLayoutInfo.mSize.height );
1580 for( std::vector<RenderableActor>::iterator it = relayoutData.mEllipsizedGlyphActors.begin(),
1581 endIt = relayoutData.mEllipsizedGlyphActors.end();
1585 RenderableActor glyphActor = ( *it );
1587 glyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT );
1588 glyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT );
1590 // Sets the sort modifier value.
1591 glyphActor.SetSortModifier( visualParameters.mSortModifier );
1593 // Enables or disables the blending.
1594 glyphActor.SetBlendMode( !visualParameters.mSnapshotModeEnabled ? BlendingMode::ON : BlendingMode::OFF );
1598 void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelayout::TextUnderlineStatus& textUnderlineStatus )
1600 // Traverse the whole text to find all groups of consecutive underlined characters in the same laid-out line.
1602 // Note that relayoutData.mTextLayoutInfo contains layout info per line but these lines are the result of split the whole text every time a '\n' is found.
1603 // According with the layout option, one of this lines could be laid-out in more than one.
1605 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), lineEndIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
1606 lineIt != lineEndIt;
1609 TextViewProcessor::LineLayoutInfo& line( *lineIt );
1611 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = line.mWordsLayoutInfo.begin(), wordEndIt = line.mWordsLayoutInfo.end();
1612 wordIt != wordEndIt;
1615 TextViewProcessor::WordLayoutInfo& word( *wordIt );
1617 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
1618 characterIt != characterEndIt;
1621 TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
1623 // Check if current character is the first of a new laid-out line
1624 const bool isNewLine = ( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() ) &&
1625 ( textUnderlineStatus.mCharacterGlobalIndex == ( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) ).mCharacterGlobalIndex );
1628 ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
1631 if( character.mStyledText.mStyle.IsUnderlineEnabled() )
1633 if( !textUnderlineStatus.mCurrentUnderlineStatus || // Current character is underlined but previous one it wasn't.
1634 isNewLine ) // Current character is underlined and is the first of current laid-out line.
1636 // Create a new underline info for the current underlined characters.
1637 UnderlineInfo underlineInfo;
1638 underlineInfo.mMaxHeight = character.mSize.height;
1639 underlineInfo.mMaxThickness = character.mUnderlineThickness;
1640 underlineInfo.mPosition = character.mUnderlinePosition;
1642 textUnderlineStatus.mUnderlineInfo.push_back( underlineInfo );
1644 textUnderlineStatus.mCurrentUnderlineStatus = true; // Set the current text is underlined.
1648 // Retrieve last underline info and update it if current underline thickness is bigger.
1649 UnderlineInfo& underlineInfo( *( textUnderlineStatus.mUnderlineInfo.end() - 1 ) );
1651 underlineInfo.mMaxHeight = std::max( underlineInfo.mMaxHeight, character.mSize.height );
1653 if( character.mUnderlineThickness > underlineInfo.mMaxThickness )
1655 underlineInfo.mMaxThickness = character.mUnderlineThickness;
1656 underlineInfo.mPosition = character.mUnderlinePosition;
1662 textUnderlineStatus.mCurrentUnderlineStatus = false;
1665 ++textUnderlineStatus.mCharacterGlobalIndex;
1666 } // end characters.
1671 void SetUnderlineInfo( TextView::RelayoutData& relayoutData )
1673 // 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.
1674 TextViewRelayout::TextUnderlineStatus textUnderlineStatus;
1676 // Traverse the whole text to find all groups of consecutive underlined characters in the same laid-out line.
1677 CalculateUnderlineInfo( relayoutData, textUnderlineStatus );
1679 if( textUnderlineStatus.mUnderlineInfo.empty() )
1681 // There is no underlined text. Just exit.
1685 // At this point textUnderlineStatus.mUnderlineInfo has for each group of consecutive underlined characters their maximum thickness, position and maximum height.
1686 // Traverse the whole text and set the previously stored underline info in the text style.
1688 std::vector<UnderlineInfo>::const_iterator underlineInfoIt = textUnderlineStatus.mUnderlineInfo.begin();
1689 std::vector<UnderlineInfo>::const_iterator underlineInfoEndIt = textUnderlineStatus.mUnderlineInfo.end();
1691 UnderlineInfo underlineInfo;
1693 if( underlineInfoIt < underlineInfoEndIt )
1695 underlineInfo = ( *underlineInfoIt );
1698 // Whether current text is underlined.
1699 textUnderlineStatus.mCurrentUnderlineStatus = false;
1700 textUnderlineStatus.mCharacterGlobalIndex = 0;
1701 textUnderlineStatus.mLineGlobalIndex = 0;
1703 float currentLineHeight = 0.f;
1704 float currentLineAscender = 0.f;
1706 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), lineEndIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
1707 lineIt != lineEndIt;
1710 TextViewProcessor::LineLayoutInfo& line( *lineIt );
1712 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = line.mWordsLayoutInfo.begin(), wordEndIt = line.mWordsLayoutInfo.end();
1713 wordIt != wordEndIt;
1716 TextViewProcessor::WordLayoutInfo& word( *wordIt );
1718 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
1719 characterIt != characterEndIt;
1722 TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
1724 // Check if current character is the first of a new laid-out line
1726 bool isNewLine = false;
1728 if( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() )
1730 const Toolkit::TextView::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) );
1731 isNewLine = ( textUnderlineStatus.mCharacterGlobalIndex == lineLayoutInfo.mCharacterGlobalIndex );
1735 currentLineHeight = lineLayoutInfo.mSize.height;
1736 currentLineAscender = lineLayoutInfo.mAscender;
1737 ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
1741 if( character.mStyledText.mStyle.IsUnderlineEnabled() )
1743 if( textUnderlineStatus.mCurrentUnderlineStatus )
1747 // Retrieves the thickness and position for the next piece of underlined text.
1748 if( underlineInfoIt < underlineInfoEndIt )
1751 if( underlineInfoIt < underlineInfoEndIt )
1753 underlineInfo = *underlineInfoIt;
1759 textUnderlineStatus.mCurrentUnderlineStatus = true;
1761 // Before setting the position it needs to be adjusted to match the base line.
1762 const float bearingOffset = ( currentLineHeight - currentLineAscender ) - ( character.mSize.height - character.mAscender );
1763 const float positionOffset = ( underlineInfo.mMaxHeight - character.mSize.height ) - bearingOffset;
1765 // Sets the underline's parameters.
1766 character.mStyledText.mStyle.SetUnderline( true, underlineInfo.mMaxThickness, underlineInfo.mPosition - positionOffset );
1768 // Mark the character to be set the new style into the text-actor.
1769 character.mSetStyle = true;
1773 if( textUnderlineStatus.mCurrentUnderlineStatus )
1775 textUnderlineStatus.mCurrentUnderlineStatus = false;
1777 // Retrieves the thickness and position for the next piece of underlined text.
1778 if( underlineInfoIt < underlineInfoEndIt )
1781 if( underlineInfoIt < underlineInfoEndIt )
1783 underlineInfo = *underlineInfoIt;
1789 ++textUnderlineStatus.mCharacterGlobalIndex;
1790 } // end of characters.
1795 void RemoveGlyphActors( Actor textView,
1796 const std::vector<RenderableActor>& glyphActors )
1798 // Removes previously inserted renderable-actors.
1799 // The SplitByNewLineChar::Relayout(), SplitByWord::Relayout() and SplitByChar::Relayout() functions add
1800 // renderable-actors to the text-view. A handle to these renderable-actors are stored and passed to this function
1801 // in order to remove 'only' renderable-actors added by these functions.
1802 // Any other actor added by a programmer or application won't be removed.
1804 for( std::vector<RenderableActor>::const_reverse_iterator it = glyphActors.rbegin(), endIt = glyphActors.rend(); it != endIt; ++it )
1806 textView.Remove( *it );
1810 void InsertToTextView( const TextView::RelayoutOperationMask relayoutOperationMask,
1812 TextView::RelayoutData& relayoutData )
1814 const bool insertToTextView = relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW;
1815 const bool insertToTextActorList = relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST;
1817 // Add text-actors to the text-view.
1819 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
1820 endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
1821 lineLayoutIt != endLineLayoutIt;
1824 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
1826 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(),
1827 endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.end();
1828 wordLayoutIt != endWordLayoutIt;
1831 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
1833 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
1834 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
1835 characterLayoutIt != endCharacterLayoutIt;
1836 ++characterLayoutIt )
1838 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
1840 if( characterLayoutInfo.mIsVisible && characterLayoutInfo.mGlyphActor ) // White spaces and '\n' characters doesn't have a text-actor.
1842 //Add to the text-view.
1843 if( insertToTextView )
1845 textView.Add( characterLayoutInfo.mGlyphActor );
1847 if( insertToTextActorList )
1849 relayoutData.mGlyphActors.push_back( characterLayoutInfo.mGlyphActor );
1856 for( std::vector<RenderableActor>::iterator it = relayoutData.mEllipsizedGlyphActors.begin(),
1857 endIt = relayoutData.mEllipsizedGlyphActors.end();
1861 RenderableActor glyphActor = ( *it );
1863 //Add to the text-view.
1864 if( insertToTextView )
1866 textView.Add( glyphActor );
1868 if( insertToTextActorList )
1870 relayoutData.mGlyphActors.push_back( glyphActor );
1873 relayoutData.mEllipsizedGlyphActors.clear();
1876 RenderableActor CreateGlyphActor( const Text& text, const TextStyle& style, TextActorCache& cache )
1878 TextActor textActor = cache.RetrieveTextActor();
1882 // Update the text-actor.
1883 textActor.SetText( text );
1884 textActor.SetTextStyle( style );
1888 // The text-actor cache is empty. Create a new one.
1889 TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_OFF );
1890 textActor = TextActor::New( text, parameters );
1896 } // namespace TextViewRelayout
1898 } // namespace Internal
1900 } // namespace Toolkit