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 = 0u; // Index to the first position of the vector which stores all line justification info.
516 std::size_t infoTableCharacterIndex = 0u;
518 relayoutParameters.mIndices.mLineIndex = 0u;
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 = 0u;
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 = 0u;
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() - 1u ) );
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 );
1073 if( !ellipsizeText.IsEmpty() )
1075 // Creates the last glyph-actor.
1076 RenderableActor ellipsizeGlyphActor = CreateGlyphActor( ellipsizeText, ellipsizeStyle, relayoutData.mTextActorCache );
1077 ellipsizeGlyphActor.SetSize( ellipsizeSize );
1078 ellipsizeGlyphActor.SetPosition( Vector3( ellipsizePosition.x, ellipsizePosition.y - bearingOffset, ellipsizePosition.z ) );
1080 // Adds the glyph-actor to the list.
1081 relayoutData.mEllipsizedGlyphActors.push_back( ellipsizeGlyphActor );
1085 void EllipsizeLine( const TextView::LayoutParameters& layoutParameters,
1086 EllipsizeParameters& ellipsizeParameters,
1087 TextView::RelayoutData& relayoutData )
1089 // Traverses the text layout info from the first character of the laid out line
1090 // to the last one setting to each character its visibility. If needed, it adds the ellipsize text (...).
1092 // Indices to the first character of the laid out line.
1093 TextViewProcessor::TextInfoIndices firstIndices;
1094 TextViewProcessor::GetIndicesFromGlobalCharacterIndex( ellipsizeParameters.mFirstIndex,
1095 relayoutData.mTextLayoutInfo,
1098 // Indices to the last character of the laid out line.
1099 TextViewProcessor::TextInfoIndices lastIndices;
1100 TextViewProcessor::GetIndicesFromGlobalCharacterIndex( ellipsizeParameters.mLastIndex,
1101 relayoutData.mTextLayoutInfo,
1104 // Defines a boundary by substracting the ellipsize-text's width to the text-view's width.
1105 // This is the boundary used to check if a character have to be ellipsized.
1106 ellipsizeParameters.mEllipsizeBoundary = relayoutData.mTextViewSize;
1107 ellipsizeParameters.mEllipsizeBoundary.width -= relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mSize.width;
1109 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin() + firstIndices.mLineIndex,
1110 endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin() + lastIndices.mLineIndex + 1u;
1111 lineLayoutIt != endLineLayoutIt;
1114 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
1116 ellipsizeParameters.mLineFits = ellipsizeParameters.mIsLineWidthFullyVisible && ellipsizeParameters.mIsLineHeightFullyVisible && ellipsizeParameters.mIsNextLineFullyVisibleHeight;
1118 if( !ellipsizeParameters.mIsNextLineFullyVisibleHeight )
1120 ellipsizeParameters.mEllipsizeBoundary.width = ellipsizeParameters.mLineWidth;
1123 bool firstWord = true;
1124 bool lastWord = false;
1126 std::size_t wordCount = 0u;
1128 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin() + firstIndices.mWordIndex,
1129 endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin() + lastIndices.mWordIndex + 1u;
1130 wordLayoutIt != endWordLayoutIt;
1131 ++wordLayoutIt, ++wordCount )
1133 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
1135 if( wordCount == lastIndices.mWordIndex - firstIndices.mWordIndex )
1140 const std::size_t firstCharacterIndex = firstWord ? firstIndices.mCharacterIndex : 0u;
1141 const std::size_t lastCharacterIndex = lastWord ? lastIndices.mCharacterIndex : wordLayoutInfo.mCharactersLayoutInfo.size() - 1u;
1142 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + firstCharacterIndex,
1143 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + lastCharacterIndex + 1u;
1144 characterLayoutIt != endCharacterLayoutIt;
1145 ++characterLayoutIt )
1147 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
1149 if( ellipsizeParameters.mEllipsizeLine )
1151 // Calculates the character visibility and whether it needs to be replace by ellipsized text.
1152 CalculateVisibilityForEllipsize( layoutParameters,
1153 characterLayoutInfo,
1154 ellipsizeParameters,
1157 if( ellipsizeParameters.mCreateEllipsizedTextActors )
1159 // Create ellipsize text-actors if the character needs to be replaced.
1160 CreateEllipsizeTextActor( ellipsizeParameters,
1166 if( ( TextView::EllipsizeEnd == layoutParameters.mExceedPolicy ) ||
1167 ( TextView::SplitEllipsizeEnd == layoutParameters.mExceedPolicy ))
1169 if( !ellipsizeParameters.mIsLineHeightFullyVisible )
1171 // Make characters invisible.
1172 characterLayoutInfo.mIsVisible = false;
1182 void SetTextVisible( TextView::RelayoutData& relayoutData )
1184 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
1185 endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
1186 lineLayoutIt != endLineLayoutIt;
1189 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
1191 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(),
1192 endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.end();
1193 wordLayoutIt != endWordLayoutIt;
1196 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
1198 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
1199 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
1200 characterLayoutIt != endCharacterLayoutIt;
1201 ++characterLayoutIt )
1203 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
1205 characterLayoutInfo.mIsVisible = true;
1206 characterLayoutInfo.mGradientColor = Vector4::ZERO;
1207 characterLayoutInfo.mStartPoint = Vector2::ZERO;
1208 characterLayoutInfo.mEndPoint = Vector2::ZERO;
1209 characterLayoutInfo.mColorAlpha = characterLayoutInfo.mStyledText.mStyle.GetTextColor().a;
1214 // Updates the visibility for text-input..
1215 for( std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator it = relayoutData.mCharacterLayoutInfoTable.begin(),
1216 endIt = relayoutData.mCharacterLayoutInfoTable.end();
1220 Toolkit::TextView::CharacterLayoutInfo& characterLayoutInfo( *it );
1222 characterLayoutInfo.mIsVisible = true;
1226 void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters,
1227 const TextView::VisualParameters& visualParameters,
1228 TextView::RelayoutData& relayoutData )
1230 RelayoutParameters relayoutParameters;
1231 FadeParameters fadeParameters;
1233 // 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.
1234 fadeParameters.mRightFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mRight );
1235 fadeParameters.mRightFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mRight > 0u ? fadeParameters.mRightFadeBoundary : MINIMUM_FADE_BOUNDARY );
1236 fadeParameters.mRightFadeThreshold = relayoutData.mTextViewSize.width - fadeParameters.mRightFadeBoundary;
1237 fadeParameters.mRightFadeThresholdOffset = relayoutData.mTextViewSize.width - fadeParameters.mRightFadeBoundaryOffset;
1238 fadeParameters.mLeftFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mLeft );
1239 fadeParameters.mLeftFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mLeft > 0u ? fadeParameters.mLeftFadeBoundary : MINIMUM_FADE_BOUNDARY );
1240 fadeParameters.mLeftFadeThreshold = fadeParameters.mLeftFadeBoundary;
1241 fadeParameters.mLeftFadeThresholdOffset = fadeParameters.mLeftFadeBoundaryOffset;
1242 fadeParameters.mTopFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mTop );
1243 fadeParameters.mTopFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mTop > 0u ? fadeParameters.mTopFadeBoundary : MINIMUM_FADE_BOUNDARY );
1244 fadeParameters.mTopFadeThreshold = fadeParameters.mTopFadeBoundary;
1245 fadeParameters.mTopFadeThresholdOffset = fadeParameters.mTopFadeBoundaryOffset;
1246 fadeParameters.mBottomFadeBoundary = static_cast<float>( visualParameters.mFadeBoundary.mBottom );
1247 fadeParameters.mBottomFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mBottom > 0u ? fadeParameters.mBottomFadeBoundary : MINIMUM_FADE_BOUNDARY );
1248 fadeParameters.mBottomFadeThreshold = relayoutData.mTextViewSize.height - fadeParameters.mBottomFadeBoundary;
1249 fadeParameters.mBottomFadeThresholdOffset = relayoutData.mTextViewSize.height - fadeParameters.mBottomFadeBoundaryOffset;
1251 // Calculates the fade out rect coeficients for the right, left, top and bottom sides of the text-view.
1252 fadeParameters.mRightAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mRightFadeThresholdOffset, 1.f ), Vector2( relayoutData.mTextViewSize.width, 0.f ) );
1253 fadeParameters.mLeftAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mLeftFadeThresholdOffset, 1.f ), Vector2( 0.f, 0.f ) );
1254 fadeParameters.mTopAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mTopFadeThresholdOffset, 1.f ), Vector2( 0.f, 0.f ) );
1255 fadeParameters.mBottomAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mBottomFadeThresholdOffset, 1.f ), Vector2( relayoutData.mTextViewSize.height, 0.f ) );
1257 // Traverses all characters and calculates the visibility.
1259 std::size_t infoTableCharacterIndex = 0u;
1261 relayoutParameters.mIndices.mLineIndex = 0u;
1263 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
1264 endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
1265 lineLayoutIt != endLineLayoutIt;
1266 ++lineLayoutIt, ++relayoutParameters.mIndices.mLineIndex )
1268 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
1270 relayoutParameters.mIndices.mWordIndex = 0u;
1272 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(),
1273 endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.end();
1274 wordLayoutIt != endWordLayoutIt;
1275 ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
1277 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
1279 relayoutParameters.mIsFirstCharacterOfWord = true;
1280 relayoutParameters.mWordSize = wordLayoutInfo.mSize;
1281 relayoutParameters.mIndices.mCharacterIndex = 0u;
1283 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
1284 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
1285 characterLayoutIt != endCharacterLayoutIt;
1286 ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex )
1288 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
1290 relayoutParameters.mIsVisible = true;
1291 fadeParameters.mIsPartiallyVisible = false;
1293 // Calculates the visibility for the current character.
1294 CalculateVisibilityForFade( layoutParameters,
1295 characterLayoutInfo,
1300 // Updates the visibility for text-input..
1301 std::vector<Toolkit::TextView::CharacterLayoutInfo>::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex;
1303 Toolkit::TextView::CharacterLayoutInfo& characterLayoutTableInfo( *it );
1305 characterLayoutTableInfo.mIsVisible = relayoutParameters.mIsVisible;
1307 relayoutParameters.mIsFirstCharacterOfWord = false;
1313 void UpdateVisibilityForEllipsize( const TextView::LayoutParameters& layoutParameters,
1314 const TextView::VisualParameters& visualParameters,
1315 TextView::RelayoutData& relayoutData )
1317 // Traverses the laid-out lines and checks which ones doesn't fit in the text-view's boundary.
1318 for( Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineInfoIt = relayoutData.mLines.begin(), endLineInfoIt = relayoutData.mLines.end();
1319 lineInfoIt != endLineInfoIt;
1322 const Toolkit::TextView::LineLayoutInfo& lineInfo( *lineInfoIt );
1324 // To check if a laid-out line fits in the text-view's boundary,
1325 // get the position of the first character is needed and do the test
1326 // with the laid-out line size.
1328 // An bearing offset may have been applied to the first character so it's needed to
1329 // get the start position of the line.
1331 // Some parameters used in the CalculateVisibilityForEllipsize() function.
1332 EllipsizeParameters ellipsizeParameters;
1334 // Retrieves the first index and the last index of the line.
1335 ellipsizeParameters.mFirstIndex = lineInfo.mCharacterGlobalIndex;
1336 ellipsizeParameters.mLastIndex = 0u;
1337 if( ( lineInfoIt + 1u ) != endLineInfoIt )
1339 const Toolkit::TextView::LineLayoutInfo& nextLineInfo( *( lineInfoIt + 1u ) );
1340 ellipsizeParameters.mLastIndex = nextLineInfo.mCharacterGlobalIndex - 1u;
1344 ellipsizeParameters.mLastIndex = relayoutData.mCharacterLayoutInfoTable.size() - 1u;
1347 // Retrieves the first character of the line and build the position of the line with the bearing.
1348 const Toolkit::TextView::CharacterLayoutInfo& characterInfo = *( relayoutData.mCharacterLayoutInfoTable.begin() + ellipsizeParameters.mFirstIndex );
1350 // Calculates the bearing offset applied to the first character.
1351 const float bearingOffset = ( lineInfo.mSize.height - lineInfo.mAscender ) - characterInfo.mDescender;
1353 // Build the position of the line by removing the bearing offset from the first character's position.
1354 const Vector3 position( characterInfo.mPosition.x,
1355 characterInfo.mPosition.y + bearingOffset,
1356 characterInfo.mPosition.z );
1358 // Checks if the line needs to be ellipsized,
1359 ellipsizeParameters.mIsLineWidthFullyVisible = IsVisible( position,
1361 relayoutData.mTextViewSize,
1362 FULLY_VISIBLE_WIDTH );
1364 // If the exceed policy is EllipsizeEndOriginal it's enough to check
1365 // if the line fits in the width.
1366 ellipsizeParameters.mEllipsizeLine = !ellipsizeParameters.mIsLineWidthFullyVisible;
1368 // If the exceed policy is EllipsizeEnd, it's needed to check if the next line exceeds the text-view's height.
1369 // If the next line exceeds the text-view height then it's going to be invisible and current line needs to be ellipsized.
1370 ellipsizeParameters.mIsLineHeightFullyVisible = true;
1371 ellipsizeParameters.mIsNextLineFullyVisibleHeight = true;
1372 if( ( TextView::EllipsizeEnd == layoutParameters.mExceedPolicy ) ||
1373 ( TextView::SplitEllipsizeEnd == layoutParameters.mExceedPolicy ) )
1375 // Need to check if there is lines which doesn't fit in the height.
1377 ellipsizeParameters.mIsLineHeightFullyVisible = IsVisible( position,
1379 relayoutData.mTextViewSize,
1380 FULLY_VISIBLE_HEIGHT );
1382 ellipsizeParameters.mEllipsizeLine = ellipsizeParameters.mEllipsizeLine && ellipsizeParameters.mIsLineHeightFullyVisible;
1384 if( ellipsizeParameters.mIsLineHeightFullyVisible && !ellipsizeParameters.mEllipsizeLine )
1386 // Current line is not ellipsized.
1387 // Need to check if there is a next line and if it's not visible. If there is, current line needs to be ellipsized.
1388 Toolkit::TextView::LineLayoutInfoContainer::const_iterator nextLineInfoIt = lineInfoIt + 1u;
1389 if( nextLineInfoIt != endLineInfoIt )
1391 // Retrives the position of the first character of the line and remove
1392 // the bearing offset to build to build the position of the line.
1393 const Toolkit::TextView::LineLayoutInfo& nextLineInfo( *nextLineInfoIt );
1394 const Toolkit::TextView::CharacterLayoutInfo& characterInfo = *( relayoutData.mCharacterLayoutInfoTable.begin() + nextLineInfo.mCharacterGlobalIndex );
1396 const float bearingOffset = ( ( lineInfo.mSize.height - lineInfo.mAscender ) - characterInfo.mDescender ) * relayoutData.mShrinkFactor;
1398 const Vector3 position( characterInfo.mPosition.x,
1399 characterInfo.mPosition.y + bearingOffset,
1400 characterInfo.mPosition.z );
1402 ellipsizeParameters.mIsNextLineFullyVisibleHeight = IsVisible( position,
1404 relayoutData.mTextViewSize,
1405 FULLY_VISIBLE_HEIGHT );
1407 // If the next line is not visible, current line have to be ellipsized.
1408 ellipsizeParameters.mEllipsizeLine = !ellipsizeParameters.mIsNextLineFullyVisibleHeight;
1413 if( !ellipsizeParameters.mIsNextLineFullyVisibleHeight )
1415 ellipsizeParameters.mLineWidth = position.x + lineInfo.mSize.width - relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mSize.width;
1418 // Sets the line descender.
1419 ellipsizeParameters.mLineDescender = lineInfo.mSize.height - lineInfo.mAscender;
1421 // At this point, ellipsizeLine distinguish if a piece of line have to be ellipsized or not.
1422 EllipsizeLine( layoutParameters, ellipsizeParameters, relayoutData );
1426 void UpdateVisibility( const TextView::LayoutParameters& layoutParameters,
1427 const TextView::VisualParameters& visualParameters,
1428 TextView::RelayoutData& relayoutData )
1430 switch( layoutParameters.mExceedPolicy )
1432 case TextView::FadeOriginal:
1433 case TextView::OriginalFade:
1434 case TextView::Fade:
1435 case TextView::SplitFade: // Fall through
1437 UpdateVisibilityForFade( layoutParameters,
1442 case TextView::EllipsizeEndOriginal:
1443 case TextView::SplitEllipsizeEnd:
1444 case TextView::EllipsizeEnd: // Fall through
1446 // Set first all characters to visible as UpdateVisibilityForEllipsize() doesn't traverse all of them.
1447 SetTextVisible( relayoutData );
1449 UpdateVisibilityForEllipsize( layoutParameters,
1456 SetTextVisible( relayoutData );
1463 * Creates an image actor for the emoticon.
1465 * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending).
1466 * @param[in,out] characterLayout Layout info for the character.
1467 * @param[in] character The character.
1469 void CreateEmoticon( const TextView::VisualParameters& visualParameters,
1470 TextViewProcessor::CharacterLayoutInfo& characterLayout,
1471 const Character& character )
1473 // The character is an emoticon.
1474 ImageActor imageActor = ImageActor::DownCast( characterLayout.mGlyphActor );
1477 imageActor = ImageActor::New();
1479 GlyphImage image = GlyphImage::New( character );
1483 imageActor.SetImage( image );
1487 imageActor.SetPosition( Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x,
1488 characterLayout.mPosition.y + characterLayout.mOffset.y,
1489 characterLayout.mPosition.z ) );
1490 imageActor.SetSize( characterLayout.mSize );
1492 // Sets the sort modifier value.
1493 imageActor.SetSortModifier( visualParameters.mSortModifier );
1495 characterLayout.mGlyphActor = imageActor;
1499 * Creates text-actors for the given text.
1501 * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending).
1502 * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info.
1503 * @param[in,out] line Layout info for the line.
1504 * @param[in,out] characterLayout Layout info for the character.
1505 * @param[in] character The character.
1506 * @param[in] style The character's style.
1507 * @param[in,out] currentTextActorInfo Temporary stores the text-actor's info to be set.
1508 * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles.
1510 void CreateTextActor( const TextView::VisualParameters& visualParameters,
1511 TextView::RelayoutData& relayoutData,
1512 const TextViewProcessor::LineLayoutInfo& line,
1513 TextViewProcessor::CharacterLayoutInfo& characterLayout,
1514 const Character& character,
1515 const TextStyle& style,
1516 CurrentTextActorInfo& currentTextActorInfo,
1517 bool createGlyphActors )
1519 // Set the text-actor for the current traversed text.
1520 if( currentTextActorInfo.textActor )
1522 currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
1523 currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
1524 currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
1526 SetVisualParameters( currentTextActorInfo,
1529 line.mSize.height );
1532 currentTextActorInfo.text = Text( character );
1533 currentTextActorInfo.position = Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x,
1534 characterLayout.mPosition.y + characterLayout.mOffset.y,
1535 characterLayout.mPosition.z );
1536 currentTextActorInfo.size = characterLayout.mSize * relayoutData.mShrinkFactor;
1538 currentTextActorInfo.color = style.GetTextColor();
1539 currentTextActorInfo.color.a = characterLayout.mColorAlpha;
1541 currentTextActorInfo.gradientColor = characterLayout.mGradientColor;
1542 currentTextActorInfo.startPoint = characterLayout.mStartPoint;
1543 currentTextActorInfo.endPoint = characterLayout.mEndPoint;
1545 TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor );
1547 if( createGlyphActors )
1551 // Try to reuse first the text-actor of this character.
1552 textActor.SetTextStyle( style );
1556 // If there is no text-actor, try to retrieve one from the cache.
1557 textActor = relayoutData.mTextActorCache.RetrieveTextActor();
1559 // If still there is no text-actor, create one.
1562 TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_OFF );
1563 textActor = TextActor::New( Text(), parameters );
1567 textActor.SetTextStyle( style );
1570 characterLayout.mGlyphActor = textActor;
1573 // Update the current text-actor.
1574 currentTextActorInfo.textActor = textActor;
1578 * Traverses the whole line initializating renderable-actor handles and updating them with the new size and position.
1580 * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending).
1581 * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info.
1582 * @param[in,out] line Layout info for the line.
1583 * @param[in,out] characterGlobalIndex Index to the character within the whole text.
1584 * @param[in,out] lineLayoutInfoIndex Index to the table of laid out lines.
1585 * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles.
1587 void UpdateTextActorInfoForLine( const TextView::VisualParameters& visualParameters,
1588 TextView::RelayoutData& relayoutData,
1589 TextViewProcessor::LineLayoutInfo& line,
1590 std::size_t& characterGlobalIndex,
1591 std::size_t& lineLayoutInfoIndex,
1592 bool createGlyphActors )
1594 CurrentTextActorInfo currentTextActorInfo;
1596 const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of laid out lines.
1597 bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last laid out line.
1598 bool glyphActorCreatedForLine = false; // Whether a renderable actor has been created for this line.
1600 TextStyle currentStyle; // style for the current text-actor.
1602 Vector4 currentGradientColor; // gradient color for the current text-actor.
1603 Vector2 currentStartPoint; // start point for the current text-actor.
1604 Vector2 currentEndPoint; // end point for the current text-actor.
1606 bool currentIsColorGlyph = false; // Whether current glyph is an emoticon.
1608 std::vector<TextActor> textActorsToRemove; // Keep a vector of text-actors to be included into the cache.
1610 std::size_t characterLineIndex = 0u; // Index to the character (within the line).
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& characterLayout( *characterIt );
1623 // Check if there is a new line.
1624 const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex );
1628 // Point to the next line.
1629 ++lineLayoutInfoIndex;
1630 if( lineLayoutInfoIndex >= lineLayoutInfoSize )
1632 // Arrived at last line.
1633 lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector.
1635 glyphActorCreatedForLine = false;
1638 // Do not create a glyph-actor if there is no text.
1639 const Character character = characterLayout.mStyledText.mText[0u]; // there are only one character per character layout.
1640 const TextStyle& style = characterLayout.mStyledText.mStyle;
1642 bool appendCharacter = false;
1644 if( characterLayout.mIsColorGlyph ||
1645 !character.IsWhiteSpace() || // A new line character is also a white space.
1646 ( character.IsWhiteSpace() && style.IsUnderlineEnabled() ) )
1648 // Do not create a glyph-actor if it's a white space (without underline) or a new line character.
1650 // Creates one glyph-actor for each counsecutive group of characters, with the same style, per line, or if it's an emoticon.
1652 if( !glyphActorCreatedForLine ||
1653 characterLayout.mIsColorGlyph ||
1654 ( characterLayout.mIsColorGlyph != currentIsColorGlyph ) ||
1655 ( style != currentStyle ) ||
1656 ( characterLayout.mGradientColor != currentGradientColor ) ||
1657 ( characterLayout.mStartPoint != currentStartPoint ) ||
1658 ( characterLayout.mEndPoint != currentEndPoint ) )
1660 characterLayout.mSetText = false;
1661 characterLayout.mSetStyle = false;
1663 // There is a new style or a new line.
1664 glyphActorCreatedForLine = true;
1666 if( characterLayout.mIsColorGlyph )
1668 CreateEmoticon( visualParameters,
1674 CreateTextActor( visualParameters,
1680 currentTextActorInfo,
1681 createGlyphActors );
1684 // Update style to be checked with next characters.
1685 currentStyle = style;
1686 currentGradientColor = characterLayout.mGradientColor;
1687 currentStartPoint = characterLayout.mStartPoint;
1688 currentEndPoint = characterLayout.mEndPoint;
1689 currentIsColorGlyph = characterLayout.mIsColorGlyph;
1691 characterLayout.mGlyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT );
1692 characterLayout.mGlyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT );
1696 DALI_ASSERT_DEBUG( !characterLayout.mIsColorGlyph && "TextViewProcessor::InitializeTextActorInfo. An image-actor doesn't store more than one emoticon." );
1698 // Same style than previous one.
1700 // Add the character to the current text-actor and update the size.
1701 appendCharacter = true;
1703 TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor );
1706 // There is a previously created text-actor for this character.
1707 // If this character has another one put it into the cache.
1708 textActor.SetText( "" );
1709 textActorsToRemove.push_back( textActor );
1712 if( characterLayout.mGlyphActor )
1714 characterLayout.mGlyphActor.Reset();
1717 } // no white space / new line char
1720 appendCharacter = true;
1723 if( appendCharacter )
1725 // Add the character to the current text-actor and update the size.
1726 if( characterLayout.mIsVisible && ( TextViewProcessor::LineSeparator != word.mType ) )
1728 currentTextActorInfo.text.Append( character );
1730 currentTextActorInfo.position.y = std::min( currentTextActorInfo.position.y, ( characterLayout.mPosition.y + characterLayout.mOffset.y ) );
1731 currentTextActorInfo.size.width += characterLayout.mSize.width * relayoutData.mShrinkFactor;
1732 currentTextActorInfo.size.height = std::max( currentTextActorInfo.size.height, characterLayout.mSize.height * relayoutData.mShrinkFactor );
1736 ++characterGlobalIndex;
1737 ++characterLineIndex;
1741 if( !currentTextActorInfo.text.IsEmpty() )
1743 if( currentTextActorInfo.textActor )
1745 currentTextActorInfo.textActor.SetText( currentTextActorInfo.text );
1746 currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position );
1747 currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size );
1749 SetVisualParameters( currentTextActorInfo,
1752 line.mSize.height );
1756 // Insert the spare text-actors into the cache.
1757 relayoutData.mTextActorCache.InsertTextActors( textActorsToRemove );
1760 void UpdateTextActorInfo( const TextView::VisualParameters& visualParameters,
1761 TextView::RelayoutData& relayoutData,
1762 bool createGlyphActors )
1764 if( relayoutData.mTextLayoutInfo.mLinesLayoutInfo.empty() )
1766 // nothing to do if there is no lines.
1770 std::size_t characterGlobalIndex = 0u; // Index to the global character (within the whole text).
1771 std::size_t lineLayoutInfoIndex = 0u; // Index to the laid out line info.
1773 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), lineEndIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
1774 lineIt != lineEndIt;
1777 TextViewProcessor::LineLayoutInfo& line( *lineIt );
1779 UpdateTextActorInfoForLine( visualParameters,
1782 characterGlobalIndex,
1783 lineLayoutInfoIndex,
1784 createGlyphActors );
1787 for( std::vector<RenderableActor>::iterator it = relayoutData.mEllipsizedGlyphActors.begin(),
1788 endIt = relayoutData.mEllipsizedGlyphActors.end();
1792 RenderableActor glyphActor = ( *it );
1794 glyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT );
1795 glyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT );
1797 // Sets the sort modifier value.
1798 glyphActor.SetSortModifier( visualParameters.mSortModifier );
1800 // Enables or disables the blending.
1801 glyphActor.SetBlendMode( !visualParameters.mSnapshotModeEnabled ? BlendingMode::ON : BlendingMode::OFF );
1805 void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelayout::TextUnderlineStatus& textUnderlineStatus )
1807 // Traverse the whole text to find all groups of consecutive underlined characters in the same laid-out line.
1809 // 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.
1810 // According with the layout option, one of this lines could be laid-out in more than one.
1812 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), lineEndIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
1813 lineIt != lineEndIt;
1816 TextViewProcessor::LineLayoutInfo& line( *lineIt );
1818 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = line.mWordsLayoutInfo.begin(), wordEndIt = line.mWordsLayoutInfo.end();
1819 wordIt != wordEndIt;
1822 TextViewProcessor::WordLayoutInfo& word( *wordIt );
1824 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
1825 characterIt != characterEndIt;
1828 TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
1830 // Check if current character is the first of a new laid-out line
1831 const bool isNewLine = ( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() ) &&
1832 ( textUnderlineStatus.mCharacterGlobalIndex == ( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) ).mCharacterGlobalIndex );
1835 ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
1838 if( character.mStyledText.mStyle.IsUnderlineEnabled() )
1840 if( !textUnderlineStatus.mCurrentUnderlineStatus || // Current character is underlined but previous one it wasn't.
1841 isNewLine ) // Current character is underlined and is the first of current laid-out line.
1843 // Create a new underline info for the current underlined characters.
1844 UnderlineInfo underlineInfo;
1845 underlineInfo.mMaxHeight = character.mSize.height;
1846 underlineInfo.mMaxThickness = character.mUnderlineThickness;
1847 underlineInfo.mPosition = character.mUnderlinePosition;
1849 textUnderlineStatus.mUnderlineInfo.push_back( underlineInfo );
1851 textUnderlineStatus.mCurrentUnderlineStatus = true; // Set the current text is underlined.
1855 // Retrieve last underline info and update it if current underline thickness is bigger.
1856 UnderlineInfo& underlineInfo( *( textUnderlineStatus.mUnderlineInfo.end() - 1u ) );
1858 underlineInfo.mMaxHeight = std::max( underlineInfo.mMaxHeight, character.mSize.height );
1860 if( character.mUnderlineThickness > underlineInfo.mMaxThickness )
1862 underlineInfo.mMaxThickness = character.mUnderlineThickness;
1863 underlineInfo.mPosition = character.mUnderlinePosition;
1869 textUnderlineStatus.mCurrentUnderlineStatus = false;
1872 ++textUnderlineStatus.mCharacterGlobalIndex;
1873 } // end characters.
1878 void SetUnderlineInfo( TextView::RelayoutData& relayoutData )
1880 // 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.
1881 TextViewRelayout::TextUnderlineStatus textUnderlineStatus;
1883 // Traverse the whole text to find all groups of consecutive underlined characters in the same laid-out line.
1884 CalculateUnderlineInfo( relayoutData, textUnderlineStatus );
1886 if( textUnderlineStatus.mUnderlineInfo.empty() )
1888 // There is no underlined text. Just exit.
1892 // At this point textUnderlineStatus.mUnderlineInfo has for each group of consecutive underlined characters their maximum thickness, position and maximum height.
1893 // Traverse the whole text and set the previously stored underline info in the text style.
1895 std::vector<UnderlineInfo>::const_iterator underlineInfoIt = textUnderlineStatus.mUnderlineInfo.begin();
1896 std::vector<UnderlineInfo>::const_iterator underlineInfoEndIt = textUnderlineStatus.mUnderlineInfo.end();
1898 UnderlineInfo underlineInfo;
1900 if( underlineInfoIt < underlineInfoEndIt )
1902 underlineInfo = ( *underlineInfoIt );
1905 // Whether current text is underlined.
1906 textUnderlineStatus.mCurrentUnderlineStatus = false;
1907 textUnderlineStatus.mCharacterGlobalIndex = 0u;
1908 textUnderlineStatus.mLineGlobalIndex = 0u;
1910 float currentLineHeight = 0.f;
1911 float currentLineAscender = 0.f;
1913 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(), lineEndIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
1914 lineIt != lineEndIt;
1917 TextViewProcessor::LineLayoutInfo& line( *lineIt );
1919 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = line.mWordsLayoutInfo.begin(), wordEndIt = line.mWordsLayoutInfo.end();
1920 wordIt != wordEndIt;
1923 TextViewProcessor::WordLayoutInfo& word( *wordIt );
1925 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end();
1926 characterIt != characterEndIt;
1929 TextViewProcessor::CharacterLayoutInfo& character( *characterIt );
1931 // Check if current character is the first of a new laid-out line
1933 bool isNewLine = false;
1935 if( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() )
1937 const Toolkit::TextView::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) );
1938 isNewLine = ( textUnderlineStatus.mCharacterGlobalIndex == lineLayoutInfo.mCharacterGlobalIndex );
1942 currentLineHeight = lineLayoutInfo.mSize.height;
1943 currentLineAscender = lineLayoutInfo.mAscender;
1944 ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one.
1948 if( character.mStyledText.mStyle.IsUnderlineEnabled() )
1950 if( textUnderlineStatus.mCurrentUnderlineStatus )
1954 // Retrieves the thickness and position for the next piece of underlined text.
1955 if( underlineInfoIt < underlineInfoEndIt )
1958 if( underlineInfoIt < underlineInfoEndIt )
1960 underlineInfo = *underlineInfoIt;
1966 textUnderlineStatus.mCurrentUnderlineStatus = true;
1968 // Before setting the position it needs to be adjusted to match the base line.
1969 const float bearingOffset = ( currentLineHeight - currentLineAscender ) - ( character.mSize.height - character.mAscender );
1970 const float positionOffset = ( underlineInfo.mMaxHeight - character.mSize.height ) - bearingOffset;
1972 // Sets the underline's parameters.
1973 character.mStyledText.mStyle.SetUnderline( true, underlineInfo.mMaxThickness, underlineInfo.mPosition - positionOffset );
1975 // Mark the character to be set the new style into the text-actor.
1976 character.mSetStyle = true;
1980 if( textUnderlineStatus.mCurrentUnderlineStatus )
1982 textUnderlineStatus.mCurrentUnderlineStatus = false;
1984 // Retrieves the thickness and position for the next piece of underlined text.
1985 if( underlineInfoIt < underlineInfoEndIt )
1988 if( underlineInfoIt < underlineInfoEndIt )
1990 underlineInfo = *underlineInfoIt;
1996 ++textUnderlineStatus.mCharacterGlobalIndex;
1997 } // end of characters.
2002 void RemoveGlyphActors( Actor textView,
2003 const std::vector<RenderableActor>& glyphActors )
2005 // Removes previously inserted renderable-actors.
2006 // The SplitByNewLineChar::Relayout(), SplitByWord::Relayout() and SplitByChar::Relayout() functions add
2007 // renderable-actors to the text-view. A handle to these renderable-actors are stored and passed to this function
2008 // in order to remove 'only' renderable-actors added by these functions.
2009 // Any other actor added by a programmer or application won't be removed.
2011 for( std::vector<RenderableActor>::const_reverse_iterator it = glyphActors.rbegin(), endIt = glyphActors.rend(); it != endIt; ++it )
2013 textView.Remove( *it );
2017 void InsertToTextView( Actor textView,
2018 TextView::RelayoutData& relayoutData )
2020 // Add text-actors to the text-view.
2022 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
2023 endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
2024 lineLayoutIt != endLineLayoutIt;
2027 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
2029 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.begin(),
2030 endWordLayoutIt = lineLayoutInfo.mWordsLayoutInfo.end();
2031 wordLayoutIt != endWordLayoutIt;
2034 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
2036 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
2037 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
2038 characterLayoutIt != endCharacterLayoutIt;
2039 ++characterLayoutIt )
2041 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
2043 if( characterLayoutInfo.mIsVisible && characterLayoutInfo.mGlyphActor ) // White spaces and '\n' characters doesn't have a text-actor.
2045 //Add to the text-view.
2046 textView.Add( characterLayoutInfo.mGlyphActor );
2047 relayoutData.mGlyphActors.push_back( characterLayoutInfo.mGlyphActor );
2053 for( std::vector<RenderableActor>::iterator it = relayoutData.mEllipsizedGlyphActors.begin(),
2054 endIt = relayoutData.mEllipsizedGlyphActors.end();
2058 RenderableActor glyphActor = ( *it );
2060 //Add to the text-view.
2061 textView.Add( glyphActor );
2062 relayoutData.mGlyphActors.push_back( glyphActor );
2064 relayoutData.mEllipsizedGlyphActors.clear();
2067 RenderableActor CreateGlyphActor( const Text& text, const TextStyle& style, TextActorCache& cache )
2069 TextActor textActor = cache.RetrieveTextActor();
2073 // Update the text-actor.
2074 textActor.SetText( text );
2075 textActor.SetTextStyle( style );
2079 // The text-actor cache is empty. Create a new one.
2080 TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_OFF );
2081 textActor = TextActor::New( text, parameters );
2087 } // namespace TextViewRelayout
2089 } // namespace Internal
2091 } // namespace Toolkit