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/split-by-new-line-char-policies.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
24 #include <dali-toolkit/internal/controls/text-view/text-view-processor.h>
35 namespace SplitByNewLineChar
41 Vector3 SplitPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters,
42 const TextView::LayoutParameters& layoutParameters,
43 TextView::RelayoutData& relayoutData )
45 const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x );
46 const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y );
48 if( relayoutParameters.mIsNewLine ||
49 relayoutParameters.mIsFirstCharacter ||
50 ( wordOffset + relayoutParameters.mCharacterSize.width > relayoutData.mTextViewSize.width ) )
52 if( !relayoutParameters.mIsNewLine &&
53 ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewParagraphCharacter ) )
55 // Current character is a white space. Don't want to move a white space to the next line.
56 // These white spaces are placed just in the edge.
57 return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f );
61 const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + relayoutParameters.mIndices.mParagraphIndex ) );
63 TextViewRelayout::LineLayoutInfo subLineInfo;
64 subLineInfo.mLineLength = 0.f;
65 subLineInfo.mMaxCharHeight = 0.f;
66 subLineInfo.mMaxAscender = 0.f;
67 TextViewRelayout::CalculateLineLayout( relayoutData.mTextViewSize.width,
68 relayoutParameters.mIndices,
70 TextViewRelayout::WrapByParagraphCharacterAndSplit,
74 // Stores some info to calculate the line justification in a post-process.
75 TextView::LineJustificationInfo justificationInfo;
77 justificationInfo.mIndices = relayoutParameters.mIndices;
78 justificationInfo.mLineLength = subLineInfo.mLineLength;
80 relayoutData.mLineJustificationInfo.push_back( justificationInfo );
82 Toolkit::TextView::LineLayoutInfo lineInfo;
83 lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line.
84 lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph.
85 lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph.
86 relayoutData.mLines.push_back( lineInfo );
88 return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f );
93 return Vector3( wordOffset, previousPositionY, 0.f );
97 void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameters,
98 TextView::RelayoutData& relayoutData )
101 relayoutData.mCharacterLayoutInfoTable.clear();
102 relayoutData.mLines.clear();
103 relayoutData.mTextSizeForRelayoutOption = Size();
104 relayoutData.mShrinkFactor = 1.f;
106 // Calculates the text size for split by char.
107 Vector4 minMaxXY( std::numeric_limits<float>::max(),
108 std::numeric_limits<float>::max(),
109 std::numeric_limits<float>::min(),
110 std::numeric_limits<float>::min() );
112 TextViewRelayout::RelayoutParameters relayoutParameters;
114 if( TextView::ShrinkOriginal == layoutParameters.mExceedPolicy )
116 if( relayoutData.mTextLayoutInfo.mWholeTextSize.width > relayoutData.mTextViewSize.width )
118 relayoutData.mShrinkFactor = relayoutData.mTextViewSize.width / relayoutData.mTextLayoutInfo.mWholeTextSize.width;
121 else if( TextView::Shrink == layoutParameters.mExceedPolicy )
123 if( ( relayoutData.mTextLayoutInfo.mWholeTextSize.width > relayoutData.mTextViewSize.width ) ||
124 ( relayoutData.mTextLayoutInfo.mWholeTextSize.height > relayoutData.mTextViewSize.height ) )
126 relayoutData.mShrinkFactor = std::min( relayoutData.mTextViewSize.width / relayoutData.mTextLayoutInfo.mWholeTextSize.width,
127 relayoutData.mTextViewSize.height / relayoutData.mTextLayoutInfo.mWholeTextSize.height );
131 relayoutParameters.mIsFirstCharacter = true;
132 relayoutParameters.mIndices.mParagraphIndex = 0u;
133 relayoutParameters.mPositionOffset = Vector3::ZERO;
134 relayoutParameters.mCharacterGlobalIndex = 0u;
136 for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(),
137 endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end();
138 paragraphLayoutIt != endParagraphLayoutIt;
139 ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex )
141 TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt );
143 relayoutParameters.mParagraphSize = paragraphLayoutInfo.mSize * relayoutData.mShrinkFactor;
145 relayoutParameters.mIsNewLine = true;
146 relayoutParameters.mIndices.mWordIndex = 0u;
148 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(),
149 endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end();
150 wordLayoutIt != endWordLayoutIt;
151 ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
153 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
154 relayoutParameters.mIsWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType;
155 relayoutParameters.mIsNewParagraphCharacter = TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType;
157 relayoutParameters.mIsFirstCharacterOfWord = true;
158 relayoutParameters.mWordSize = wordLayoutInfo.mSize;
159 relayoutParameters.mIndices.mCharacterIndex = 0u;
161 if( relayoutParameters.mIsNewLine )
163 // Stores some info to calculate the line justification in a post-process.
164 const bool isSplitOriginal = layoutParameters.mExceedPolicy == TextView::SplitOriginal;
166 if( !isSplitOriginal )
168 TextView::LineJustificationInfo justificationInfo;
170 justificationInfo.mIndices = relayoutParameters.mIndices;
171 justificationInfo.mLineLength = relayoutParameters.mParagraphSize.width;
173 relayoutData.mLineJustificationInfo.push_back( justificationInfo );
177 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
178 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
179 characterLayoutIt != endCharacterLayoutIt;
180 ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex )
182 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
183 relayoutParameters.mCharacterSize = characterLayoutInfo.mSize;
185 relayoutParameters.mCharacterSize = characterLayoutInfo.mSize;
187 switch( layoutParameters.mExceedPolicy )
189 case TextView::OriginalShrink:
190 case TextView::SplitShrink:
191 case TextView::ShrinkFade: // Fall Through
193 DALI_LOG_WARNING( "SplitByNewLineChar::CalculateSizeAndPosition() policy not implemented.\n" );
196 case TextView::Original: // Fall Through
197 case TextView::ShrinkOriginal: // Fall Through
198 case TextView::Shrink: // Fall Through
199 case TextView::OriginalFade: // Fall Through
200 case TextView::FadeOriginal: // Fall Through
201 case TextView::Fade: // Fall Through
202 case TextView::EllipsizeEndOriginal: // Fall Through
203 case TextView::EllipsizeEnd: // Fall Through
205 if( relayoutParameters.mIsNewLine )
207 relayoutParameters.mPositionOffset.x = 0.f;
208 relayoutParameters.mPositionOffset.y += paragraphLayoutInfo.mSize.height * relayoutData.mShrinkFactor;
211 characterLayoutInfo.mPosition = relayoutParameters.mPositionOffset;
213 relayoutParameters.mPositionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor;
215 if( relayoutParameters.mIsNewLine ||
216 relayoutParameters.mIsFirstCharacter )
218 Toolkit::TextView::LineLayoutInfo lineInfo;
219 lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line.
220 lineInfo.mSize = relayoutParameters.mParagraphSize; // Size of this piece of paragraph.
221 lineInfo.mAscender = paragraphLayoutInfo.mAscender * relayoutData.mShrinkFactor; // Ascender of this piece of paragraph.
222 relayoutData.mLines.push_back( lineInfo );
226 case TextView::SplitOriginal:
227 case TextView::SplitFade:
228 case TextView::SplitEllipsizeEnd: // Fall Through
230 characterLayoutInfo.mPosition = SplitPosition( relayoutParameters,
234 relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f );
239 DALI_LOG_WARNING( "SplitByNewLineChar::CalculateSizeAndPosition() Layout configuration not possible.\n" );
244 // Get last line info and calculate the bearing (used to align glyphs with the baseline).
245 TextViewRelayout::CalculateBearing( characterLayoutInfo, relayoutData );
247 // updates min and max position to calculate the text size for split by new line char.
248 TextViewRelayout::UpdateLayoutInfoTable( minMaxXY,
254 ++relayoutParameters.mCharacterGlobalIndex;
255 relayoutParameters.mIsFirstCharacter = false;
256 relayoutParameters.mIsNewLine = false;
261 if( relayoutData.mCharacterLayoutInfoTable.empty() )
263 relayoutData.mTextSizeForRelayoutOption = Size();
267 relayoutData.mTextSizeForRelayoutOption.width = minMaxXY.z - minMaxXY.x;
268 relayoutData.mTextSizeForRelayoutOption.height = minMaxXY.w - minMaxXY.y;
271 // Check if the last character is a new paragraph character. In that case the height should be added.
272 if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() )
274 const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) );
276 if( paragraphLayoutInfo.mWordsLayoutInfo.empty() ) // if it's empty, it means the last character is a new paragraph character.
278 relayoutData.mTextSizeForRelayoutOption.height += paragraphLayoutInfo.mSize.height * relayoutData.mShrinkFactor;
285 void Relayout( Actor textView,
286 TextView::RelayoutOperationMask relayoutOperationMask,
287 const TextView::LayoutParameters& layoutParameters,
288 const TextView::VisualParameters& visualParameters,
289 TextView::RelayoutData& relayoutData )
291 if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
293 relayoutData.mLineJustificationInfo.clear();
294 CalculateSizeAndPosition( layoutParameters,
297 TextViewRelayout::SetUnderlineInfo( relayoutData );
300 if( relayoutOperationMask & TextView::RELAYOUT_ALIGNMENT )
302 TextViewRelayout::UpdateAlignment( layoutParameters,
306 if( relayoutOperationMask & TextView::RELAYOUT_VISIBILITY )
308 TextViewRelayout::UpdateVisibility( layoutParameters,
313 const bool initializeTextActors = relayoutOperationMask & TextView::RELAYOUT_INITIALIZE_TEXT_ACTORS;
314 const bool updateTextActors = relayoutOperationMask & TextView::RELAYOUT_TEXT_ACTOR_UPDATE;
315 if( initializeTextActors || updateTextActors )
317 TextViewRelayout::UpdateTextActorInfo( visualParameters,
319 initializeTextActors );
322 if( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW )
324 TextViewRelayout::InsertToTextView( textView,
329 } // namespace SplitByNewLineChar
331 } // namespace Internal
333 } // namespace Toolkit