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-new-line-char-policies.h"
25 #include "relayout-utilities.h"
26 #include "text-view-processor.h"
27 #include <dali/integration-api/debug.h>
38 namespace SplitByNewLineChar
44 Vector3 SplitPosition( 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 ( wordOffset + relayoutParameters.mCharacterSize.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 const TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin() + relayoutParameters.mIndices.mLineIndex ) );
66 TextViewRelayout::SubLineLayoutInfo subLineInfo;
67 subLineInfo.mLineLength = 0.f;
68 subLineInfo.mMaxCharHeight = 0.f;
69 subLineInfo.mMaxAscender = 0.f;
70 TextViewRelayout::CalculateSubLineLayout( relayoutData.mTextViewSize.width,
71 relayoutParameters.mIndices,
73 TextViewRelayout::WrapByLineAndSplit,
77 // Stores some info to calculate the line justification in a post-process.
78 TextView::LineJustificationInfo justificationInfo;
80 justificationInfo.mIndices = relayoutParameters.mIndices;
81 justificationInfo.mLineLength = subLineInfo.mLineLength;
83 relayoutData.mLineJustificationInfo.push_back( justificationInfo );
85 Toolkit::TextView::LineLayoutInfo lineInfo;
86 lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line.
87 lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of line.
88 lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of line.
89 relayoutData.mLines.push_back( lineInfo );
91 return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f );
96 return Vector3( wordOffset, previousPositionY, 0.f );
100 void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameters,
101 TextView::RelayoutData& relayoutData )
104 relayoutData.mCharacterLayoutInfoTable.clear();
105 relayoutData.mLines.clear();
106 relayoutData.mTextSizeForRelayoutOption = Size();
107 relayoutData.mShrinkFactor = 1.f;
109 // Calculates the text size for split by char.
110 Vector4 minMaxXY( std::numeric_limits<float>::max(),
111 std::numeric_limits<float>::max(),
112 std::numeric_limits<float>::min(),
113 std::numeric_limits<float>::min() );
115 TextViewRelayout::RelayoutParameters relayoutParameters;
117 if( TextView::ShrinkOriginal == layoutParameters.mExceedPolicy )
119 if( relayoutData.mTextLayoutInfo.mWholeTextSize.width > relayoutData.mTextViewSize.width )
121 relayoutData.mShrinkFactor = relayoutData.mTextViewSize.width / relayoutData.mTextLayoutInfo.mWholeTextSize.width;
124 else if( TextView::Shrink == layoutParameters.mExceedPolicy )
126 if( ( relayoutData.mTextLayoutInfo.mWholeTextSize.width > relayoutData.mTextViewSize.width ) ||
127 ( relayoutData.mTextLayoutInfo.mWholeTextSize.height > relayoutData.mTextViewSize.height ) )
129 relayoutData.mShrinkFactor = std::min( relayoutData.mTextViewSize.width / relayoutData.mTextLayoutInfo.mWholeTextSize.width,
130 relayoutData.mTextViewSize.height / relayoutData.mTextLayoutInfo.mWholeTextSize.height );
134 relayoutParameters.mIsFirstCharacter = true;
135 relayoutParameters.mIndices.mLineIndex = 0;
136 relayoutParameters.mPositionOffset = Vector3::ZERO;
137 relayoutParameters.mCharacterGlobalIndex = 0;
139 for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
140 endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
141 lineLayoutIt != endLineLayoutIt;
142 ++lineLayoutIt, ++relayoutParameters.mIndices.mLineIndex )
144 TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
146 relayoutParameters.mLineSize = lineLayoutInfo.mSize * relayoutData.mShrinkFactor;
148 relayoutParameters.mIsNewLine = true;
149 relayoutParameters.mIndices.mGroupIndex = 0;
151 for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(),
152 endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end();
153 groupLayoutIt != endGroupLayoutIt;
154 ++groupLayoutIt, ++relayoutParameters.mIndices.mGroupIndex )
156 TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *groupLayoutIt );
158 relayoutParameters.mIndices.mWordIndex = 0;
160 for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.begin(),
161 endWordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.end();
162 wordLayoutIt != endWordLayoutIt;
163 ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
165 TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
166 relayoutParameters.mIsWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType;
167 relayoutParameters.mIsNewLineCharacter = TextViewProcessor::LineSeparator == wordLayoutInfo.mType;
169 relayoutParameters.mIsFirstCharacterOfWord = true;
170 relayoutParameters.mWordSize = wordLayoutInfo.mSize;
171 relayoutParameters.mIndices.mCharacterIndex = 0;
173 if( relayoutParameters.mIsNewLine )
175 // Stores some info to calculate the line justification in a post-process.
176 const bool isSplitOriginal = layoutParameters.mExceedPolicy == TextView::SplitOriginal;
178 if( !isSplitOriginal )
180 TextView::LineJustificationInfo justificationInfo;
182 justificationInfo.mIndices = relayoutParameters.mIndices;
183 justificationInfo.mLineLength = relayoutParameters.mLineSize.width;
185 relayoutData.mLineJustificationInfo.push_back( justificationInfo );
189 for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
190 endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
191 characterLayoutIt != endCharacterLayoutIt;
192 ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex )
194 TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
195 relayoutParameters.mCharacterSize = characterLayoutInfo.mSize;
197 relayoutParameters.mCharacterSize = characterLayoutInfo.mSize;
199 switch( layoutParameters.mExceedPolicy )
201 case TextView::OriginalShrink:
202 case TextView::SplitShrink:
203 case TextView::ShrinkFade: // Fall Through
205 DALI_LOG_WARNING( "SplitByNewLineChar::CalculateSizeAndPosition() policy not implemented.\n" );
208 case TextView::Original: // Fall Through
209 case TextView::ShrinkOriginal: // Fall Through
210 case TextView::Shrink: // Fall Through
211 case TextView::OriginalFade: // Fall Through
212 case TextView::FadeOriginal: // Fall Through
213 case TextView::Fade: // Fall Through
214 case TextView::EllipsizeEndOriginal: // Fall Through
215 case TextView::EllipsizeEnd: // Fall Through
217 if( relayoutParameters.mIsNewLine )
219 relayoutParameters.mPositionOffset.x = 0.f;
220 relayoutParameters.mPositionOffset.y += lineLayoutInfo.mSize.height * relayoutData.mShrinkFactor;
223 characterLayoutInfo.mPosition = relayoutParameters.mPositionOffset;
225 relayoutParameters.mPositionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor;
227 if( relayoutParameters.mIsNewLine ||
228 relayoutParameters.mIsFirstCharacter )
230 Toolkit::TextView::LineLayoutInfo lineInfo;
231 lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line.
232 lineInfo.mSize = relayoutParameters.mLineSize; // Size of this piece of line.
233 lineInfo.mAscender = lineLayoutInfo.mAscender * relayoutData.mShrinkFactor; // Ascender of this piece of line.
234 relayoutData.mLines.push_back( lineInfo );
238 case TextView::SplitOriginal:
239 case TextView::SplitFade:
240 case TextView::SplitEllipsizeEnd: // Fall Through
242 characterLayoutInfo.mPosition = SplitPosition( relayoutParameters,
246 relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f );
251 DALI_LOG_WARNING( "SplitByNewLineChar::CalculateSizeAndPosition() Layout configuration not possible.\n" );
256 // Get last line info and calculate the bearing (used to align glyphs with the baseline).
257 TextViewRelayout::CalculateBearing( characterLayoutInfo, relayoutData );
259 // updates min and max position to calculate the text size for split by new line char.
260 TextViewRelayout::UpdateLayoutInfoTable( minMaxXY,
267 ++relayoutParameters.mCharacterGlobalIndex;
268 relayoutParameters.mIsFirstCharacter = false;
269 relayoutParameters.mIsNewLine = false;
272 } // end group of words
275 if( relayoutData.mCharacterLayoutInfoTable.empty() )
277 relayoutData.mTextSizeForRelayoutOption = Size();
281 relayoutData.mTextSizeForRelayoutOption.width = minMaxXY.z - minMaxXY.x;
282 relayoutData.mTextSizeForRelayoutOption.height = minMaxXY.w - minMaxXY.y;
285 // Check if the last character is a new line character. In that case the height should be added.
286 if( !relayoutData.mTextLayoutInfo.mLinesLayoutInfo.empty() )
288 const TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end() - 1 ) );
290 if( lineLayoutInfo.mWordGroupsLayoutInfo.empty() ) // if it's empty, it means the last character is a new line character.
292 relayoutData.mTextSizeForRelayoutOption.height += lineLayoutInfo.mSize.height * relayoutData.mShrinkFactor;
299 void Relayout( Actor textView,
300 TextView::RelayoutOperationMask relayoutOperationMask,
301 const TextView::LayoutParameters& layoutParameters,
302 const TextView::VisualParameters& visualParameters,
303 TextView::RelayoutData& relayoutData )
305 if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
307 relayoutData.mLineJustificationInfo.clear();
308 CalculateSizeAndPosition( layoutParameters,
311 TextViewRelayout::SetUnderlineInfo( relayoutData );
314 if( relayoutOperationMask & TextView::RELAYOUT_ALIGNMENT )
316 TextViewRelayout::UpdateAlignment( layoutParameters,
320 if( relayoutOperationMask & TextView::RELAYOUT_VISIBILITY )
322 TextViewRelayout::UpdateVisibility( layoutParameters,
327 if( relayoutOperationMask & TextView::RELAYOUT_INITIALIZE_TEXT_ACTORS )
329 TextViewProcessor::InitializeTextActorInfo( relayoutData );
332 if( relayoutOperationMask & TextView::RELAYOUT_TEXT_ACTOR_UPDATE )
334 TextViewRelayout::UpdateTextActorInfo( visualParameters,
338 if( ( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW ) ||
339 ( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST ) )
341 TextViewRelayout::InsertToTextView( relayoutOperationMask,
347 } // namespace SplitByNewLineChar
349 } // namespace Internal
351 } // namespace Toolkit