2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 "split-by-word-policies.h"
25 #include "relayout-utilities.h"
26 #include "text-view-processor.h"
27 #include <dali/integration-api/debug.h>
44 Vector3 OriginalPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters,
45 const TextView::LayoutParameters& layoutParameters,
46 TextView::RelayoutData& relayoutData )
48 const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x );
49 const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y );
51 if( relayoutParameters.mIsNewLine ||
52 relayoutParameters.mIsFirstCharacter ||
53 ( relayoutParameters.mIsFirstCharacterOfWord && ( wordOffset + relayoutParameters.mWordSize.width > relayoutData.mTextViewSize.width ) ) )
55 if( !relayoutParameters.mIsNewLine &&
56 ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewLineCharacter ) )
58 // Current character is a white space. Don't want to move a white space to the next line.
59 // These white spaces are placed just in the edge.
60 return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f );
64 // Calculates the length of the portion of the line which doesn't exceed the text-view's width and the max character height for the current line.
65 TextViewRelayout::SubLineLayoutInfo subLineInfo;
66 subLineInfo.mLineLength = 0.f;
67 subLineInfo.mMaxCharHeight = 0.f;
68 subLineInfo.mMaxAscender = 0.f;
69 const TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin() + relayoutParameters.mIndices.mLineIndex ) );
71 TextViewRelayout::CalculateSubLineLayout( relayoutData.mTextViewSize.width,
72 relayoutParameters.mIndices,
74 TextViewRelayout::WrapByWord,
78 if( subLineInfo.mLineLength < Math::MACHINE_EPSILON_1000 )
80 // It may mean there is a word which is actually longer than the width of the text-view.
81 // In that case the length of this word is needed.
82 if( !lineLayoutInfo.mWordGroupsLayoutInfo.empty() )
84 const TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *( lineLayoutInfo.mWordGroupsLayoutInfo.begin() + relayoutParameters.mIndices.mGroupIndex ) );
85 if( !wordGroupLayoutInfo.mWordsLayoutInfo.empty() )
87 const TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *( wordGroupLayoutInfo.mWordsLayoutInfo.begin() + relayoutParameters.mIndices.mWordIndex ) );
88 subLineInfo.mLineLength = wordLayoutInfo.mSize.width;
93 // Stores some info to calculate the line justification in a post-process.
94 TextView::LineJustificationInfo justificationInfo;
96 justificationInfo.mIndices = relayoutParameters.mIndices;
97 justificationInfo.mLineLength = subLineInfo.mLineLength;
99 relayoutData.mLineJustificationInfo.push_back( justificationInfo );
101 Toolkit::TextView::LineLayoutInfo lineInfo;
102 lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line.
103 lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of line.
104 lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of line.
105 relayoutData.mLines.push_back( lineInfo );
107 return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f );
112 return Vector3( wordOffset, previousPositionY, 0.f );
117 * Calculates character position.
118 * @param[in] relayoutParameters Temporary layout parameters (previous size, previous position, ... )
119 * @param[in] layoutParameters The layout parameters.
120 * @param[in] relayoutData The text-view's data structures.
121 * @return The character's position.
123 Vector3 SplitWhenExceedPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters,
124 const TextView::LayoutParameters& layoutParameters,
125 TextView::RelayoutData& relayoutData )
127 const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x );
128 const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y );
130 if( ( relayoutParameters.mIsNewLine || relayoutParameters.mIsFirstCharacter ) ||
131 ( relayoutParameters.mIsFirstCharacterOfWord && ( wordOffset + relayoutParameters.mWordSize.width > relayoutData.mTextViewSize.width ) ) ||
132 ( wordOffset + relayoutParameters.mCharacterSize.width > relayoutData.mTextViewSize.width ) )
134 if( !relayoutParameters.mIsNewLine &&
135 ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewLineCharacter ) )
137 // Current character is a white space. Don't want to move a white space to the next line.
138 // These white spaces are placed just in the edge.
139 return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f );
143 // Calculates the line length and the max character height for the current line.
144 TextViewRelayout::SubLineLayoutInfo subLineInfo;
145 subLineInfo.mLineLength = 0.f;
146 subLineInfo.mMaxCharHeight = 0.f;
147 subLineInfo.mMaxAscender = 0.f;
148 const TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin() + relayoutParameters.mIndices.mLineIndex ) );
150 TextViewRelayout::CalculateSubLineLayout( relayoutData.mTextViewSize.width,
151 relayoutParameters.mIndices,
153 TextViewRelayout::WrapByWordAndSplit,
154 1.f, // Shrink factor.
157 // Stores some info to calculate the line justification in a post-process.
158 TextView::LineJustificationInfo justificationInfo;
160 justificationInfo.mIndices = relayoutParameters.mIndices;
161 justificationInfo.mLineLength = subLineInfo.mLineLength;
163 relayoutData.mLineJustificationInfo.push_back( justificationInfo );
165 Toolkit::TextView::LineLayoutInfo lineInfo;
166 lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line.
167 lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of line.
168 lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of line.
169 relayoutData.mLines.push_back( lineInfo );
171 return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f );
176 return Vector3( wordOffset, previousPositionY, 0.f );
181 * Calculates character position.
182 * @param[in] relayoutParameters Temporary layout parameters (previous size, previous position, ... )
183 * @param[in] layoutParameters The layout parameters.
184 * @param[in] relayoutData The text-view's data structures.
185 * @return The character's position.
187 Vector3 ShrinkWidthWhenExceedPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters,
188 const TextView::LayoutParameters& layoutParameters,
189 TextView::RelayoutData& relayoutData )
191 const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x );
192 const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y );
193 const Size wordSize = relayoutParameters.mWordSize * relayoutData.mShrinkFactor;
195 if( ( relayoutParameters.mIsNewLine || relayoutParameters.mIsFirstCharacter ) || // isNewLine is true when '\n' is found.
196 ( relayoutParameters.mIsFirstCharacterOfWord && ( wordOffset + wordSize.width > relayoutData.mTextViewSize.width ) ) ) // The word doesn't fit in the parent width.
198 if( !relayoutParameters.mIsNewLine &&
199 ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewLineCharacter ) )
201 // Current character is a white space. Don't want to move a white space to the next line.
202 // These white spaces are placed just in the edge.
203 return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f );
207 // Calculates the line length and the max character height for the current line.
208 TextViewRelayout::SubLineLayoutInfo subLineInfo;
209 subLineInfo.mLineLength = 0.f;
210 subLineInfo.mMaxCharHeight = 0.f;
211 subLineInfo.mMaxAscender = 0.f;
212 const TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin() + relayoutParameters.mIndices.mLineIndex ) );
214 TextViewRelayout::CalculateSubLineLayout( relayoutData.mTextViewSize.width,
215 relayoutParameters.mIndices,
217 TextViewRelayout::WrapByWord,
218 relayoutData.mShrinkFactor,
221 // Stores some info to calculate the line justification in a post-process.
222 TextView::LineJustificationInfo justificationInfo;
224 justificationInfo.mIndices = relayoutParameters.mIndices;
225 justificationInfo.mLineLength = subLineInfo.mLineLength;
227 relayoutData.mLineJustificationInfo.push_back( justificationInfo );
229 Toolkit::TextView::LineLayoutInfo lineInfo;
230 lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line.
231 lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of line.
232 lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of line.
233 relayoutData.mLines.push_back( lineInfo );
235 return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset * relayoutData.mShrinkFactor, 0.f );
240 return Vector3( wordOffset, previousPositionY, 0.f );
244 void CalculatePositionsForShrinkWhenExceed( TextView::RelayoutData& relayoutData,
245 const TextView::LayoutParameters& layoutParameters,
246 const float shrinkFactor,
247 float& newTextHeight )
249 const float parentWidth = relayoutData.mTextViewSize.width;
250 TextViewProcessor::TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo;
252 relayoutData.mLineJustificationInfo.clear();
254 // Reset the text height. This value is returned in order to shrink further or not the text.
257 // Whether the first character is being processed.
258 bool isFirstChar = true;
260 // Stores the size of the previous character.
262 // Stores the position of the previous character.
263 Vector3 previousPosition;
265 // Reset the index of lines.
266 TextViewProcessor::TextInfoIndices indices;
268 // Whether the last character of the whole text is a new line char.
269 // This information is used to increase or not the height of the whole text by one line.
270 // Increase the whole text's height by one line is useful i.e. in TextInput to place the cursor
271 // after pressing 'Enter' in the last line.
272 bool isLastCharacterNewLineChar = false;
273 // Stores the height of the last character. This height used to be added to the whole text height if
274 // isLastCharacterNewLineChar is true.
275 float lastCharHeight = 0.f;
277 relayoutData.mLines.clear();
278 std::size_t characterGlobalIndex = 0;
280 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineIt = textLayoutInfo.mLinesLayoutInfo.begin(), lineEndIt = textLayoutInfo.mLinesLayoutInfo.end();
282 ++lineIt, ++indices.mLineIndex )
284 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineIt );
286 // The next character is in a new line.
287 bool isNewLine = true;
289 // Reset the index of groups of words.
290 indices.mGroupIndex = 0;
292 for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(), groupEndIt = lineLayoutInfo.mWordGroupsLayoutInfo.end();
293 groupIt != groupEndIt;
294 ++groupIt, ++indices.mGroupIndex )
296 TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *groupIt );
298 // Reset the index of words.
299 indices.mWordIndex = 0;
301 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordGroupLayoutInfo.mWordsLayoutInfo.begin(), wordEndIt = wordGroupLayoutInfo.mWordsLayoutInfo.end();
303 ++wordIt, ++indices.mWordIndex )
305 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordIt );
307 // Reset the index of the character.
308 indices.mCharacterIndex = 0;
310 // Whether current character is the first of the word.
311 bool isFirstCharOfWord = true;
312 const float wordOffset = previousPosition.x + previousSize.width;
314 isLastCharacterNewLineChar = ( TextViewProcessor::LineSeparator == wordLayoutInfo.mType );
316 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator charIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), charEndIt = wordLayoutInfo.mCharactersLayoutInfo.end();
318 ++charIt, ++indices.mCharacterIndex )
320 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *charIt );
321 lastCharHeight = characterLayoutInfo.mSize.height * shrinkFactor;
323 const float previousPositionY = isFirstChar ? 0.f : previousPosition.y;
325 if( ( isNewLine || isFirstChar ) ||
326 ( isFirstCharOfWord && ( wordOffset + wordLayoutInfo.mSize.width * shrinkFactor > parentWidth ) ) )
330 // Calculates the line length and the max character height for the current line.
331 TextViewRelayout::SubLineLayoutInfo subLineInfo;
332 subLineInfo.mLineLength = 0.f;
333 subLineInfo.mMaxCharHeight = 0.f;
334 subLineInfo.mMaxAscender = 0.f;
335 TextViewRelayout::CalculateSubLineLayout( parentWidth,
338 TextViewRelayout::WrapByWord,
342 characterLayoutInfo.mPosition = Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset * shrinkFactor, 0.f );
344 newTextHeight += subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset * shrinkFactor;
346 Toolkit::TextView::LineLayoutInfo lineInfo;
347 lineInfo.mCharacterGlobalIndex = characterGlobalIndex; // Index to the first character of the next line.
348 lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of line.
349 lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of line.
350 relayoutData.mLines.push_back( lineInfo );
353 // Stores some info to calculate the line justification in a post-process.
354 TextView::LineJustificationInfo justificationInfo;
356 justificationInfo.mIndices = indices;
357 justificationInfo.mLineLength = subLineInfo.mLineLength;
359 relayoutData.mLineJustificationInfo.push_back( justificationInfo );
363 characterLayoutInfo.mPosition = previousPosition + Vector3( previousSize.width, 0.f, 0.f );
366 // Get last line info and calculate the bearing.
367 const Toolkit::TextView::LineLayoutInfo& lineInfo( *( relayoutData.mLines.end() - 1 ) );
368 const float bearingOffset = ( ( lineInfo.mSize.height - lineInfo.mAscender ) - ( characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender ) ) * shrinkFactor;
370 previousSize = characterLayoutInfo.mSize * shrinkFactor;
371 previousPosition = characterLayoutInfo.mPosition;
372 characterLayoutInfo.mPosition.y -= bearingOffset;
373 isFirstCharOfWord = false;
376 ++characterGlobalIndex;
382 if( isLastCharacterNewLineChar )
384 newTextHeight += lastCharHeight + layoutParameters.mLineHeightOffset * shrinkFactor;
388 float RelayoutForShrinkToFit( TextView::RelayoutData& relayoutData,
389 const TextView::LayoutParameters& layoutParameters )
391 const Size& textViewSize = relayoutData.mTextViewSize;
392 TextViewProcessor::TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo;
394 // First step is assure the longest word fits in the text view width.
395 float shrinkFactor = ( textLayoutInfo.mMaxWordWidth > textViewSize.width ? textViewSize.width / textLayoutInfo.mMaxWordWidth : 1.f );
397 // Out parameter. Will store the new text height after relayout the text.
398 float newTextHeight = 0.f;
400 // Relayout the text for the given character's sizes.
401 CalculatePositionsForShrinkWhenExceed( relayoutData,
406 if( newTextHeight > textViewSize.height )
408 // After relayouting, the text exceeds the text view height.
409 // Find a new scale factor to fit all the text in the text view size is needed.
411 // The next algorithm does some iterations to calculate an acceptable scale factor.
412 // Some magic numbers are defined.
414 const float MIN_RATIO( 0.90f ); // The algorithm finishes if the ratio
415 const float MAX_RATIO( 1.00f ); // new_text_height / text_view_height is between this two values
416 const unsigned int MAX_ITERATIONS( 8 ); // or max_iteration is reached.
418 float ratio = newTextHeight / textViewSize.height;
420 float maxScaleFactor = shrinkFactor; // bigger scale factors than maxScaleFactor will produce a too big text.
421 float minScaleFactor = shrinkFactor * ( textViewSize.height / newTextHeight ); // smaller scale factors than minScaleFactor will produce a too small text.
423 for( unsigned int iterations = 0; ( ( MIN_RATIO > ratio ) || ( ratio > MAX_RATIO ) ) && ( iterations < MAX_ITERATIONS ); ++iterations )
425 // Calculates the new scale factor.
426 // The new scale factor is always between the min and max scale factors.
427 // If ratio < 1 it means the text is too small and a bigger scale factor is needed. In this case the algorithm selects a new scale factor close to
428 // minScaleFactor. Alternatively if the text is too big a new scale factor close to maxScaleFactor is selected.
429 // This allows the text shrink or grow smoothly.
430 shrinkFactor = minScaleFactor + ( ratio < 1.f ? 0.4f : 0.6f ) * ( maxScaleFactor - minScaleFactor );
432 CalculatePositionsForShrinkWhenExceed( relayoutData, // Relayout the text for the given character's sizes.
437 // Calculates the new text size ratio. It allows update the min and max scale factors.
438 // If the ratio is not good enough a new scale factor between min and max could be used in next iteration.
439 ratio = newTextHeight / textViewSize.height;
442 minScaleFactor = shrinkFactor;
446 maxScaleFactor = shrinkFactor;
450 if( ratio > MAX_RATIO )
452 // The algorithm didn't find an acceptable scale factor.
453 // In that case the text is shrunk to fit in the boundaries of the text view actor.
454 shrinkFactor = minScaleFactor;
456 CalculatePositionsForShrinkWhenExceed( relayoutData,
466 void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameters,
467 TextView::RelayoutData& relayoutData )
469 TextViewRelayout::RelayoutParameters relayoutParameters;
472 relayoutData.mCharacterLayoutInfoTable.clear();
473 relayoutData.mLines.clear();
474 relayoutData.mTextSizeForRelayoutOption = Size();
476 // Calculates the text size for split by char.
477 Vector4 minMaxXY( std::numeric_limits<float>::max(),
478 std::numeric_limits<float>::max(),
479 std::numeric_limits<float>::min(),
480 std::numeric_limits<float>::min() );
482 relayoutData.mShrinkFactor = 1.f; // Shrink factor used when the exceed policy contains ShrinkToFit
484 if( TextView::Shrink== layoutParameters.mExceedPolicy )
486 // Relays-out the text for the shrink to fit policy.
487 relayoutData.mShrinkFactor = RelayoutForShrinkToFit( relayoutData, layoutParameters );
489 else if( TextView::ShrinkOriginal == layoutParameters.mExceedPolicy )
491 relayoutData.mShrinkFactor = ( relayoutData.mTextLayoutInfo.mMaxWordWidth > relayoutData.mTextViewSize.width ? relayoutData.mTextViewSize.width / relayoutData.mTextLayoutInfo.mMaxWordWidth : 1.f );
494 relayoutParameters.mPositionOffset = Vector3::ZERO;
495 relayoutParameters.mIsFirstCharacter = true;
496 relayoutParameters.mIndices.mLineIndex = 0;
497 relayoutParameters.mCharacterGlobalIndex = 0;
499 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
500 endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
501 lineLayoutIt != endLineLayoutIt;
502 ++lineLayoutIt, ++relayoutParameters.mIndices.mLineIndex )
504 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
506 relayoutParameters.mIsNewLine = true;
507 relayoutParameters.mLineSize = lineLayoutInfo.mSize;
508 relayoutParameters.mIndices.mGroupIndex = 0;
510 for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(),
511 endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end();
512 groupLayoutIt != endGroupLayoutIt;
513 ++groupLayoutIt, ++relayoutParameters.mIndices.mGroupIndex )
515 TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *groupLayoutIt );
517 relayoutParameters.mIndices.mWordIndex = 0;
519 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.begin(),
520 endWordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.end();
521 wordLayoutIt != endWordLayoutIt;
522 ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
524 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
525 relayoutParameters.mIsWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType;
526 relayoutParameters.mIsNewLineCharacter = TextViewProcessor::LineSeparator == wordLayoutInfo.mType;
528 relayoutParameters.mIsFirstCharacterOfWord = true;
529 relayoutParameters.mWordSize = wordLayoutInfo.mSize;
530 relayoutParameters.mIndices.mCharacterIndex = 0;
532 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
533 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
534 ( characterLayoutIt != endCharacterLayoutIt );
535 ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex )
537 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
539 relayoutParameters.mCharacterSize = characterLayoutInfo.mSize;
541 switch( layoutParameters.mExceedPolicy )
543 case TextView::OriginalShrink:
544 case TextView::SplitShrink:
545 case TextView::ShrinkFade:
547 DALI_LOG_WARNING( "SplitByWord::CalculateSizeAndPosition() policy not implemented.\n" );
550 case TextView::Original:
551 case TextView::OriginalFade:
552 case TextView::FadeOriginal:
554 case TextView::EllipsizeEndOriginal:
555 case TextView::EllipsizeEnd: // Fall Through
557 characterLayoutInfo.mPosition = OriginalPosition( relayoutParameters,
561 relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f );
564 case TextView::SplitOriginal:
566 characterLayoutInfo.mPosition = SplitWhenExceedPosition( relayoutParameters,
570 relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f );
573 case TextView::SplitFade:
575 characterLayoutInfo.mPosition = SplitWhenExceedPosition( relayoutParameters,
579 relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f );
582 case TextView::ShrinkOriginal:
584 characterLayoutInfo.mPosition = ShrinkWidthWhenExceedPosition( relayoutParameters,
588 relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor, 0.f, 0.f );
591 case TextView::Shrink:
593 // Does nothing. All the job has been done in the RelayoutForShrinkToFit() function.
598 DALI_LOG_WARNING( "SplitByWord::CalculateSizeAndPosition() policy combination not possible.\n" );
602 // Get last line info and calculate the bearing (used to align glyphs with the baseline).
603 if( TextView::Shrink != layoutParameters.mExceedPolicy )
605 TextViewRelayout::CalculateBearing( characterLayoutInfo, relayoutData );
608 // updates min and max position to calculate the text size for split by word.
609 TextViewRelayout::UpdateLayoutInfoTable( minMaxXY,
616 ++relayoutParameters.mCharacterGlobalIndex;
617 relayoutParameters.mIsFirstCharacter = false;
618 relayoutParameters.mIsFirstCharacterOfWord = false;
619 relayoutParameters.mIsNewLine = false;
622 } // end group of words
625 if( relayoutData.mCharacterLayoutInfoTable.empty() )
627 relayoutData.mTextSizeForRelayoutOption = Size();
631 relayoutData.mTextSizeForRelayoutOption.width = minMaxXY.z - minMaxXY.x;
632 relayoutData.mTextSizeForRelayoutOption.height = minMaxXY.w - minMaxXY.y;
635 // Check if the last character is a new line character. In that case the height should be added.
636 if( !relayoutData.mTextLayoutInfo.mLinesLayoutInfo.empty() )
638 const TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end() - 1 ) );
640 if( lineLayoutInfo.mWordGroupsLayoutInfo.empty() ) // if it's empty, it means the last character is a new line character.
642 relayoutData.mTextSizeForRelayoutOption.height += lineLayoutInfo.mSize.height * relayoutData.mShrinkFactor;
649 void Relayout( Actor textView,
650 TextView::RelayoutOperationMask relayoutOperationMask,
651 const TextView::LayoutParameters& layoutParameters,
652 const TextView::VisualParameters& visualParameters,
653 TextView::RelayoutData& relayoutData )
655 if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
657 relayoutData.mLineJustificationInfo.clear();
658 CalculateSizeAndPosition( layoutParameters,
661 TextViewRelayout::SetUnderlineInfo( relayoutData );
664 if( relayoutOperationMask & TextView::RELAYOUT_ALIGNMENT )
666 TextViewRelayout::UpdateAlignment( layoutParameters,
670 if( relayoutOperationMask & TextView::RELAYOUT_VISIBILITY )
672 TextViewRelayout::UpdateVisibility( layoutParameters,
677 if( relayoutOperationMask & TextView::RELAYOUT_INITIALIZE_TEXT_ACTORS )
679 TextViewProcessor::InitializeTextActorInfo( relayoutData );
682 if( relayoutOperationMask & TextView::RELAYOUT_TEXT_ACTOR_UPDATE )
684 TextViewRelayout::UpdateTextActorInfo( visualParameters,
688 if( ( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW ) ||
689 ( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST ) )
691 TextViewRelayout::InsertToTextView( relayoutOperationMask,
697 } // namespace SplitByWord
699 } // namespace Internal
701 } // namespace Toolkit