Fix issues related with cameras.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-view / split-by-char-policies.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 //     http://floralicense.org/license/
9 //
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.
15 //
16
17 // FILE HEADER
18
19 #include "split-by-char-policies.h"
20
21 // EXTERNAL INCLUDES
22
23 // INTERNAL INCLUDES
24
25 #include "relayout-utilities.h"
26 #include "text-view-processor.h"
27 #include <dali/integration-api/debug.h>
28
29 namespace Dali
30 {
31
32 namespace Toolkit
33 {
34
35 namespace Internal
36 {
37
38 namespace SplitByChar
39 {
40
41 namespace
42 {
43
44 Vector3 NoShrinkWhenExceedPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters,
45                                     const TextView::LayoutParameters& layoutParameters,
46                                     TextView::RelayoutData& relayoutData )
47 {
48   const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x );
49   const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y );
50
51   if( ( relayoutParameters.mIsNewLine ||
52         relayoutParameters.mIsFirstCharacter ||
53         ( wordOffset + relayoutParameters.mCharacterSize.width > relayoutData.mTextViewSize.width ) ) )
54   {
55     if( !relayoutParameters.mIsNewLine &&
56         ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewLineCharacter ) )
57     {
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 );
61     }
62     else
63     {
64       // Calculate the line length 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 ) );
70
71       TextViewRelayout::CalculateSubLineLayout( relayoutData.mTextViewSize.width,
72                                                 relayoutParameters.mIndices,
73                                                 lineLayoutInfo,
74                                                 TextViewRelayout::WrapByCharacter,
75                                                 1.f, // Shrink factor
76                                                 subLineInfo );
77
78       // Stores some info to calculate the line justification in a post-process.
79       TextView::LineJustificationInfo justificationInfo;
80
81       justificationInfo.mIndices = relayoutParameters.mIndices;
82       justificationInfo.mLineLength = subLineInfo.mLineLength;
83
84       relayoutData.mLineJustificationInfo.push_back( justificationInfo );
85
86       Toolkit::TextView::LineLayoutInfo lineInfo;
87       lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex;    // Index to the first character of the next line.
88       lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of line.
89       lineInfo.mAscender = subLineInfo.mMaxAscender;                                // Ascender of this piece of line.
90       relayoutData.mLines.push_back( lineInfo );
91
92       return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f );
93     }
94   }
95   else
96   {
97     return Vector3( wordOffset, previousPositionY, 0.f );
98   }
99 }
100
101 void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameters,
102                                TextView::RelayoutData& relayoutData )
103 {
104   TextViewRelayout::RelayoutParameters relayoutParameters;
105
106   // clear
107   relayoutData.mCharacterLayoutInfoTable.clear();
108   relayoutData.mLines.clear();
109   relayoutData.mTextSizeForRelayoutOption = Size();
110
111   // Calculate the text size for split by char.
112   Vector4 minMaxXY( std::numeric_limits<float>::max(),
113                     std::numeric_limits<float>::max(),
114                     std::numeric_limits<float>::min(),
115                     std::numeric_limits<float>::min() );
116
117   relayoutData.mShrinkFactor = 1.f; // Shrink factor used when the exceed policy contains ShrinkToFit
118
119   relayoutParameters.mPositionOffset = Vector3::ZERO;
120   relayoutParameters.mIsFirstCharacter = true;
121   relayoutParameters.mIndices.mLineIndex = 0;
122   relayoutParameters.mCharacterGlobalIndex = 0;
123
124   for( TextViewProcessor::LineLayoutInfoContainer::iterator lineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.begin(),
125          endLineLayoutIt = relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end();
126        lineLayoutIt != endLineLayoutIt;
127        ++lineLayoutIt, ++relayoutParameters.mIndices.mLineIndex )
128   {
129     TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *lineLayoutIt );
130
131     relayoutParameters.mIsNewLine = true;
132     relayoutParameters.mLineSize = lineLayoutInfo.mSize;
133     relayoutParameters.mIndices.mGroupIndex = 0;
134
135     for( TextViewProcessor::WordGroupLayoutInfoContainer::iterator groupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.begin(),
136            endGroupLayoutIt = lineLayoutInfo.mWordGroupsLayoutInfo.end();
137          groupLayoutIt != endGroupLayoutIt;
138          ++groupLayoutIt, ++relayoutParameters.mIndices.mGroupIndex )
139     {
140       TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo( *groupLayoutIt );
141
142       relayoutParameters.mIndices.mWordIndex = 0;
143
144       for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.begin(),
145              endWordLayoutIt = wordGroupLayoutInfo.mWordsLayoutInfo.end();
146            wordLayoutIt != endWordLayoutIt;
147            ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex )
148       {
149         TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt );
150         relayoutParameters.mIsWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType;
151         relayoutParameters.mIsNewLineCharacter = TextViewProcessor::LineSeparator == wordLayoutInfo.mType;
152
153         relayoutParameters.mIsFirstCharacterOfWord = true;
154         relayoutParameters.mWordSize = wordLayoutInfo.mSize;
155         relayoutParameters.mIndices.mCharacterIndex = 0;
156
157         for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(),
158                endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end();
159              characterLayoutIt != endCharacterLayoutIt;
160              ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex )
161         {
162           TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt );
163
164           relayoutParameters.mCharacterSize = characterLayoutInfo.mSize;
165
166           switch( layoutParameters.mExceedPolicy )
167           {
168             case TextView::OriginalShrink:
169             case TextView::SplitOriginal:
170             case TextView::SplitFade:
171             case TextView::SplitShrink:
172             case TextView::ShrinkOriginal:
173             case TextView::ShrinkFade:
174             case TextView::Shrink:
175             case TextView::EllipsizeEndOriginal:
176             case TextView::EllipsizeEnd: // Fall Through
177             {
178               DALI_LOG_WARNING( "SplitByChar::CalculateSizeAndPosition() policy not implemented.\n" );
179               break;
180             }
181             case TextView::OriginalFade:
182             case TextView::FadeOriginal:
183             case TextView::Original:
184             case TextView::Fade: // Fall Through
185             {
186               characterLayoutInfo.mPosition = NoShrinkWhenExceedPosition( relayoutParameters,
187                                                                           layoutParameters,
188                                                                           relayoutData );
189
190               relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f );
191               break;
192             }
193             default:
194             {
195               DALI_LOG_WARNING( "SplitByChar::CalculateSizeAndPosition() policy combination not possible.\n" );
196             }
197           }
198
199           // Get last line info and calculate the bearing (used to align glyphs with the baseline).
200           TextViewRelayout::CalculateBearing( characterLayoutInfo, relayoutData );
201
202           // updates min and max position to calculate the text size for split by char.
203           TextViewRelayout::UpdateLayoutInfoTable( minMaxXY,
204                                                    wordGroupLayoutInfo,
205                                                    wordLayoutInfo,
206                                                    characterLayoutInfo,
207                                                    relayoutParameters,
208                                                    relayoutData );
209
210           ++relayoutParameters.mCharacterGlobalIndex;
211           relayoutParameters.mIsFirstCharacter = false;
212           relayoutParameters.mIsNewLine = false;
213         } // end characters
214       } // end words
215     } // end group of words
216   } // end lines
217
218   if( relayoutData.mCharacterLayoutInfoTable.empty() )
219   {
220     relayoutData.mTextSizeForRelayoutOption = Size();
221   }
222   else
223   {
224     relayoutData.mTextSizeForRelayoutOption.width = minMaxXY.z - minMaxXY.x;
225     relayoutData.mTextSizeForRelayoutOption.height = minMaxXY.w - minMaxXY.y;
226   }
227
228   // Check if the last character is a new line character. In that case the height should be added.
229   if( !relayoutData.mTextLayoutInfo.mLinesLayoutInfo.empty() )
230   {
231     const TextViewProcessor::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mTextLayoutInfo.mLinesLayoutInfo.end() - 1 ) );
232
233     if( lineLayoutInfo.mWordGroupsLayoutInfo.empty() ) // if it's empty, it means the last character is a new line character.
234     {
235       relayoutData.mTextSizeForRelayoutOption.height += lineLayoutInfo.mSize.height;
236     }
237   }
238 }
239
240 } // namespace
241
242 void Relayout( Actor textView,
243                TextView::RelayoutOperationMask relayoutOperationMask,
244                const TextView::LayoutParameters& layoutParameters,
245                const TextView::VisualParameters& visualParameters,
246                TextView::RelayoutData& relayoutData )
247 {
248   if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION )
249   {
250     relayoutData.mLineJustificationInfo.clear();
251     CalculateSizeAndPosition( layoutParameters,
252                               relayoutData );
253
254     TextViewRelayout::SetUnderlineInfo( relayoutData );
255   }
256
257   if( relayoutOperationMask & TextView::RELAYOUT_ALIGNMENT )
258   {
259     TextViewRelayout::UpdateAlignment( layoutParameters,
260                                        relayoutData );
261   }
262
263   if( relayoutOperationMask & TextView::RELAYOUT_VISIBILITY )
264   {
265     TextViewRelayout::UpdateVisibility( layoutParameters,
266                                         visualParameters,
267                                         relayoutData );
268   }
269
270   if( relayoutOperationMask & TextView::RELAYOUT_INITIALIZE_TEXT_ACTORS )
271   {
272     TextViewProcessor::InitializeTextActorInfo( relayoutData );
273   }
274
275   if( relayoutOperationMask & TextView::RELAYOUT_TEXT_ACTOR_UPDATE )
276   {
277     TextViewRelayout::UpdateTextActorInfo( visualParameters,
278                                            relayoutData );
279   }
280
281   if( ( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW ) ||
282       ( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST ) )
283   {
284     TextViewRelayout::InsertToTextView( relayoutOperationMask,
285                                         textView,
286                                         relayoutData );
287   }
288 }
289
290 } // namespace SplitByChar
291
292 } // namespace Internal
293
294 } // namespace Toolkit
295
296 } // namespace Dali