Fix issues related with cameras.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-view / text-view-word-group-processor.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 // INTERNAL INCLUDES
18 #include "text-view-word-group-processor.h"
19 #include "text-view-word-processor.h"
20 #include "text-view-processor-helper-functions.h"
21 #include "text-processor.h"
22
23 namespace Dali
24 {
25
26 namespace Toolkit
27 {
28
29 namespace Internal
30 {
31
32 namespace TextViewProcessor
33 {
34
35 /////////////////////
36 // Layout info.
37 /////////////////////
38
39 WordGroupLayoutInfo::WordGroupLayoutInfo()
40 : mSize(),
41   mAscender( 0.f ),
42   mDirection( LTR ),
43   mWordsLayoutInfo(),
44   mNumberOfCharacters( 0 )
45 {
46 }
47
48 WordGroupLayoutInfo::WordGroupLayoutInfo( const WordGroupLayoutInfo& group )
49 : mSize( group.mSize ),
50   mAscender( group.mAscender ),
51   mDirection( group.mDirection ),
52   mWordsLayoutInfo( group.mWordsLayoutInfo ),
53   mNumberOfCharacters( group.mNumberOfCharacters )
54 {
55 }
56
57 WordGroupLayoutInfo& WordGroupLayoutInfo::operator=( const WordGroupLayoutInfo& group )
58 {
59   mSize = group.mSize;
60   mAscender = group.mAscender;
61   mDirection = group.mDirection;
62   mWordsLayoutInfo = group.mWordsLayoutInfo;
63   mNumberOfCharacters = group.mNumberOfCharacters;
64
65   return *this;
66 }
67
68 void UpdateGroupLayoutInfo( TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo )
69 {
70   wordGroupLayoutInfo.mSize = Size();
71
72   for( WordLayoutInfoContainer::iterator it = wordGroupLayoutInfo.mWordsLayoutInfo.begin(), endIt = wordGroupLayoutInfo.mWordsLayoutInfo.end();
73        it != endIt;
74        ++it )
75   {
76     WordLayoutInfo& layoutInfo( *it );
77
78     UpdateSize( wordGroupLayoutInfo.mSize, layoutInfo.mSize );
79   }
80 }
81
82 void CreateWordGroupInfo( const MarkupProcessor::StyledTextArray& wordGroup,
83                           TextViewProcessor::TextLayoutInfo& textLayoutInfo,
84                           TextViewProcessor::WordGroupLayoutInfo& wordGroupLayoutInfo )
85 {
86   // Set the direction of the group.
87   wordGroupLayoutInfo.mDirection = ( TextProcessor::BeginsRightToLeftCharacter( wordGroup ) ? TextViewProcessor::RTL : TextViewProcessor::LTR );
88
89   // Split the group of words in words
90   std::vector<MarkupProcessor::StyledTextArray> words;
91   TextProcessor::SplitInWords( wordGroup, words );
92
93   // if last word has a new line separator, create a new word.
94   if( !words.empty() )
95   {
96     MarkupProcessor::StyledTextArray& word( *( words.end() - 1 ) );
97     if( word.size() > 1 )
98     {
99       // do nothing if the word has only one character.
100       MarkupProcessor::StyledText& styledText( *( word.end() - 1 ) );
101       if( !styledText.mText.IsEmpty() )
102       {
103         const std::size_t length = styledText.mText.GetLength();
104         if( styledText.mText[length-1].IsNewLine() )
105         {
106           // Last character of this word is a new line character.
107
108           // Remove line separator character from current word.
109           styledText.mText.Remove( length - 1, 1 );
110
111           // Create a new word with the line separator character.
112           MarkupProcessor::StyledText newLineText( Text( styledText.mText[length-1] ), styledText.mStyle );
113
114           MarkupProcessor::StyledTextArray newLineWord;
115           newLineWord.push_back( newLineText );
116
117           words.push_back( newLineWord );
118         }
119       }
120     }
121   }
122
123   // Reverse if right to left.
124   if( TextViewProcessor::RTL == wordGroupLayoutInfo.mDirection )
125   {
126     std::reverse( words.begin(), words.end() );
127   }
128
129   std::string lastCharacterFont; // Keeps the font used by the last character. It's used to set the font to a word separator.
130
131   // Traverse all words.
132   for( std::vector<MarkupProcessor::StyledTextArray>::const_iterator wordIt = words.begin(), wordEndIt = words.end(); wordIt != wordEndIt; ++wordIt )
133   {
134     const MarkupProcessor::StyledTextArray& word( *wordIt );
135
136     // Data structures for the new word.
137     WordLayoutInfo wordLayoutInfo;
138
139     CreateWordTextInfo( word,
140                         wordLayoutInfo );
141
142     // White space's size could be different depending on the type of font. It's important to use the same font than the previous character to
143     // avoid 'jumps' of characters when there is a switch between one text-actor per character and one text-actor per line and/or style.
144     if( WordSeparator == wordLayoutInfo.mType )
145     {
146       // If current word is a word separator (white space) then the font of the last character is set.
147       for( CharacterLayoutInfoContainer::iterator characterIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), characterEndIt = wordLayoutInfo.mCharactersLayoutInfo.end();
148            characterIt != characterEndIt;
149            ++characterIt )
150       {
151         CharacterLayoutInfo& characterLayout( *characterIt );
152
153         characterLayout.mStyledText.mStyle.SetFontName( lastCharacterFont );
154       }
155     }
156     else
157     {
158       // kepps the font of the last character.
159       if( !wordLayoutInfo.mCharactersLayoutInfo.empty() )
160       {
161         lastCharacterFont = ( *( wordLayoutInfo.mCharactersLayoutInfo.end() - 1 ) ).mStyledText.mStyle.GetFontName();
162       }
163     }
164
165     // Update layout info for the current group of words.
166     wordGroupLayoutInfo.mNumberOfCharacters += wordLayoutInfo.mCharactersLayoutInfo.size();
167     UpdateSize( wordGroupLayoutInfo.mSize, wordLayoutInfo.mSize );
168     wordGroupLayoutInfo.mAscender = std::max( wordGroupLayoutInfo.mAscender, wordLayoutInfo.mAscender );
169
170     // Add current word to the group of words.
171     wordGroupLayoutInfo.mWordsLayoutInfo.push_back( wordLayoutInfo );
172
173     // Update the max word width figure.
174     textLayoutInfo.mMaxWordWidth = std::max( textLayoutInfo.mMaxWordWidth, wordLayoutInfo.mSize.width );
175   } // end of words
176 }
177
178 void RemoveCharactersFromWordGroupInfo( TextView::RelayoutData& relayoutData,
179                                         const std::size_t numberOfCharacters,
180                                         bool& mergeWords,
181                                         bool& mergeLines,
182                                         TextViewProcessor::TextInfoIndices& textInfoIndicesBegin,
183                                         TextViewProcessor::TextInfoIndices& textInfoIndicesEnd,
184                                         TextViewProcessor::TextInfoIndices& textInfoMergeIndicesBegin,
185                                         TextViewProcessor::TextInfoIndices& textInfoMergeIndicesEnd,
186                                         TextViewProcessor::WordGroupLayoutInfo& groupLayout,
187                                         std::vector<TextActor>& removedTextActorsFromFirstWord,
188                                         std::vector<TextActor>& removedTextActorsFromLastWord )
189 {
190   const TextViewProcessor::TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo;
191
192   if( textInfoIndicesBegin.mWordIndex < textInfoIndicesEnd.mWordIndex )
193   {
194     // Deleted text is from different words. The two different words may be merged.
195
196     // Get first word.
197     WordLayoutInfo& firstWordLayout( *( groupLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex ) );
198
199     // Get last word.
200     WordLayoutInfo& lastWordLayout( *( groupLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex ) );
201
202     // whether first or last word need to be split and merged.
203     bool mergeFromBegin = false;
204     bool mergeToEnd = false;
205
206     if( textInfoIndicesBegin.mCharacterIndex > 0 )
207     {
208       // First word is going to be split. It could be merged with the last word.
209       mergeFromBegin = true;
210       textInfoMergeIndicesBegin.mWordIndex = textInfoIndicesBegin.mWordIndex;
211     }
212     else if( ( textInfoIndicesBegin.mCharacterIndex == 0 ) && ( textInfoIndicesBegin.mWordIndex > 0 ) )
213     {
214       // First word is going to be removed completely.
215       // Check if previous word could be merged.
216
217       // Get word before.
218       WordLayoutInfo& previousWordLayout( *( groupLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex - 1 ) );
219       if( WordSeparator != previousWordLayout.mType )
220       {
221         // Previous word is not a word separator, so could be merged.
222         mergeFromBegin = true;
223         textInfoMergeIndicesBegin.mWordIndex = textInfoIndicesBegin.mWordIndex - 1;
224       }
225     }
226
227     if( mergeFromBegin )
228     {
229       // First word (or previous one) could be merged. Check if last one could be merged as well.
230
231       if( textInfoIndicesEnd.mCharacterIndex + 1 < lastWordLayout.mCharactersLayoutInfo.size() )
232       {
233         // Last word is going to be split. It could be merged with the first word.
234         mergeToEnd = true;
235         textInfoMergeIndicesEnd.mWordIndex = textInfoIndicesEnd.mWordIndex;
236       }
237       else if( ( textInfoIndicesEnd.mCharacterIndex + 1 == lastWordLayout.mCharactersLayoutInfo.size() ) && ( textInfoIndicesEnd.mWordIndex + 1 < groupLayout.mWordsLayoutInfo.size() ) )
238       {
239         // Last word is going to be removed completely.
240         // Check if the word after could be merged.
241
242         // Get word after.
243         WordLayoutInfo& afterWordLayout( *( groupLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex + 1 ) );
244         if( WordSeparator != afterWordLayout.mType )
245         {
246           // The word after is not a word separator, so could be merged.
247           mergeToEnd = true;
248           textInfoMergeIndicesEnd.mWordIndex = textInfoIndicesEnd.mWordIndex + 1;
249         }
250       }
251
252       // Merge words only if both words could be merged.
253       mergeWords = mergeFromBegin && mergeToEnd;
254     }
255
256     if( ( textInfoIndicesEnd.mCharacterIndex + 1 == lastWordLayout.mCharactersLayoutInfo.size() ) && ( textInfoIndicesEnd.mWordIndex + 1 == groupLayout.mWordsLayoutInfo.size() ) )
257     {
258       // Last word of the line is going to be removed completely.
259       // Check if it's a line separator.
260
261       if( LineSeparator == lastWordLayout.mType )
262       {
263         // The line separator is going to be removed.
264         if( textInfoIndicesBegin.mLineIndex + 1 < textLayoutInfo.mLinesLayoutInfo.size() )
265         {
266           //  Line need to be merged.
267           textInfoMergeIndicesBegin.mLineIndex = textInfoIndicesBegin.mLineIndex;
268           textInfoMergeIndicesEnd.mLineIndex = textInfoIndicesBegin.mLineIndex + 1;
269           mergeLines= true;
270
271           ++textInfoIndicesBegin.mLineIndex; // increase both indices,
272           textInfoIndicesEnd.mLineIndex +=2; // will delete last line.
273         }
274       }
275     }
276
277     if( textInfoIndicesBegin.mCharacterIndex > 0 )
278     {
279       // First word needs to be split.
280
281       // Store text-actors before removing them.
282       CollectTextActors( removedTextActorsFromFirstWord, firstWordLayout, textInfoIndicesBegin.mCharacterIndex, firstWordLayout.mCharactersLayoutInfo.size() );
283
284       RemoveCharactersFromWord( textInfoIndicesBegin.mCharacterIndex,
285                                 firstWordLayout.mCharactersLayoutInfo.size() - textInfoIndicesBegin.mCharacterIndex,
286                                 firstWordLayout );
287
288       ++textInfoIndicesBegin.mWordIndex; // will delete from the word after.
289     }
290
291     if( textInfoIndicesEnd.mCharacterIndex + 1 < lastWordLayout.mCharactersLayoutInfo.size() )
292     {
293       // Last word needs to be split.
294
295       // Store text-actors before removing them.
296       CollectTextActors( removedTextActorsFromLastWord, lastWordLayout, 0, textInfoIndicesEnd.mCharacterIndex + 1 );
297
298       RemoveCharactersFromWord( 0,
299                                 textInfoIndicesEnd.mCharacterIndex + 1,
300                                 lastWordLayout );
301
302       if( mergeWords )
303       {
304         // This word is going to be merged, so is not needed.
305         ++textInfoIndicesEnd.mWordIndex; // will delete the last word.
306       }
307     }
308     else if( textInfoIndicesEnd.mCharacterIndex + 1 == lastWordLayout.mCharactersLayoutInfo.size() )
309     {
310       // The whole last word is going to be removed.
311       ++textInfoIndicesEnd.mWordIndex; // will delete the last word.
312
313       if( ( WordSeparator == lastWordLayout.mType ) && mergeWords )
314       {
315         // The last word is a word separator and the word after is going to be merged so is not needed.
316         ++textInfoIndicesEnd.mWordIndex; // will delete the word after the last one.
317       }
318     }
319   }
320   else
321   {
322     // Chraracters to be removed are from the same word.
323
324     RemoveCharactersFromWordInfo( relayoutData,
325                                   numberOfCharacters,
326                                   mergeWords,
327                                   mergeLines,
328                                   textInfoIndicesBegin,
329                                   textInfoIndicesEnd,
330                                   textInfoMergeIndicesBegin,
331                                   textInfoMergeIndicesEnd,
332                                   groupLayout,
333                                   removedTextActorsFromFirstWord );
334   } // word indices
335 }
336
337 void RemoveWordsFromWordGroup( const std::size_t wordIndex,
338                                const std::size_t numberOfWords,
339                                WordGroupLayoutInfo& wordGroupLayoutInfo )
340 {
341   // Removes words from a group of words.
342
343   // * Check if words or lines can be merged after removing a word or line separator have to be done outside this method.
344
345   // * Note: Currently it's only used to remove a number of words from the beginning, or
346   //         from wordIndex index to the end. This function doesn't merge words (if a white space is removed)
347   //         TODO: merge words if required.
348
349   const std::size_t wordEndIndex = wordIndex + numberOfWords;
350
351   // Remove words from layout info.
352   wordGroupLayoutInfo.mWordsLayoutInfo.erase( wordGroupLayoutInfo.mWordsLayoutInfo.begin() + wordIndex,
353                                               wordGroupLayoutInfo.mWordsLayoutInfo.begin() + wordEndIndex );
354
355   // update layout info
356   wordGroupLayoutInfo.mSize = Size();
357   wordGroupLayoutInfo.mAscender = 0.f;
358   wordGroupLayoutInfo.mNumberOfCharacters = 0;
359   for( WordLayoutInfoContainer::const_iterator it = wordGroupLayoutInfo.mWordsLayoutInfo.begin(), endIt = wordGroupLayoutInfo.mWordsLayoutInfo.end();
360        it != endIt;
361        ++it )
362   {
363     const WordLayoutInfo& info( *it );
364
365     UpdateSize( wordGroupLayoutInfo.mSize, info.mSize );
366     wordGroupLayoutInfo.mAscender = std::max( wordGroupLayoutInfo.mAscender, info.mAscender );
367     wordGroupLayoutInfo.mNumberOfCharacters += info.mCharactersLayoutInfo.size();
368   }
369 }
370
371 void SplitWordGroup( const TextInfoIndices& indices,
372                      WordGroupLayoutInfo& firstWordGroupLayoutInfo,
373                      WordGroupLayoutInfo& lastWordGroupLayoutInfo )
374 {
375   // Splits a group of words in two.
376   // A word may be split in two as well.
377
378   // * Split the word pointed by indices.mWordIndex using the indices.mCharacterIndex index.
379   // * Add the last part of the word as first word of the last part of the group of words.
380   // * Add folliwing words to the last part of the new group of words.
381   // * Remove from the first part of the group of words all words added to the last part of the group of words.
382   // * Update layout info.
383
384   //early returns
385   if( ( 0 == indices.mWordIndex ) && ( 0 == indices.mCharacterIndex ) )
386   {
387     // the whole group of words goes to the last part of the group.
388     lastWordGroupLayoutInfo = firstWordGroupLayoutInfo;
389
390     firstWordGroupLayoutInfo = WordGroupLayoutInfo();
391
392     return;
393   }
394
395   if( !firstWordGroupLayoutInfo.mWordsLayoutInfo.empty() )
396   {
397     const std::size_t numberOfWords = firstWordGroupLayoutInfo.mWordsLayoutInfo.size();
398     if( indices.mWordIndex == numberOfWords - 1 )
399     {
400       const WordLayoutInfo& word( *( firstWordGroupLayoutInfo.mWordsLayoutInfo.end() - 1 ) );
401       if( indices.mCharacterIndex == word.mCharactersLayoutInfo.size() )
402       {
403         // the whole group of words goes to the first part.
404
405         // Just delete whatever there is in the last part of the group of words.
406         lastWordGroupLayoutInfo = WordGroupLayoutInfo();
407
408         return;
409       }
410     }
411   }
412
413   lastWordGroupLayoutInfo = WordGroupLayoutInfo();
414
415   // 1) Split the word within the group of words to be split.
416   WordLayoutInfo& firstWordLayoutInfo( *( firstWordGroupLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex ) );
417   WordLayoutInfo lastWordLayoutInfo;
418
419   SplitWord( indices.mCharacterIndex,
420              firstWordLayoutInfo,
421              lastWordLayoutInfo );
422
423   // 2) Add last part of the word to the new group of words.
424   if( !lastWordLayoutInfo.mCharactersLayoutInfo.empty() )
425   {
426     lastWordGroupLayoutInfo.mWordsLayoutInfo.push_back( lastWordLayoutInfo );
427   }
428
429   // 3) Add words from word-position + 1 to the end.
430   lastWordGroupLayoutInfo.mWordsLayoutInfo.insert( lastWordGroupLayoutInfo.mWordsLayoutInfo.end(),
431                                                    firstWordGroupLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex + 1, firstWordGroupLayoutInfo.mWordsLayoutInfo.end() );
432
433   // 4) update layout info of the last group of words.
434   lastWordGroupLayoutInfo.mDirection = firstWordGroupLayoutInfo.mDirection;
435
436   for( WordLayoutInfoContainer::iterator it = lastWordGroupLayoutInfo.mWordsLayoutInfo.begin(), endIt = lastWordGroupLayoutInfo.mWordsLayoutInfo.end();
437        it != endIt;
438        ++it )
439   {
440     WordLayoutInfo& layoutInfo( *it );
441
442     UpdateSize( lastWordGroupLayoutInfo.mSize, layoutInfo.mSize );
443     lastWordGroupLayoutInfo.mNumberOfCharacters += layoutInfo.mCharactersLayoutInfo.size();
444     lastWordGroupLayoutInfo.mAscender = std::max( lastWordGroupLayoutInfo.mAscender, layoutInfo.mAscender );
445   }
446
447   // 5) Remove words added to the last part of the group of words from the first group of words.
448
449   // if the number of characters of the last word of the first group is zero, it should be removed.
450   const std::size_t index = ( firstWordLayoutInfo.mCharactersLayoutInfo.empty() ? indices.mWordIndex : indices.mWordIndex + 1 );
451
452   firstWordGroupLayoutInfo.mWordsLayoutInfo.erase( firstWordGroupLayoutInfo.mWordsLayoutInfo.begin() + index, firstWordGroupLayoutInfo.mWordsLayoutInfo.end() );
453
454   // 6) update layout info of the first group of words.
455   firstWordGroupLayoutInfo.mSize = Size();
456   firstWordGroupLayoutInfo.mAscender = 0.f;
457   firstWordGroupLayoutInfo.mNumberOfCharacters = 0;
458   for( WordLayoutInfoContainer::iterator it = firstWordGroupLayoutInfo.mWordsLayoutInfo.begin(), endIt = firstWordGroupLayoutInfo.mWordsLayoutInfo.end();
459        it != endIt;
460        ++it )
461   {
462     WordLayoutInfo& layoutInfo( *it );
463
464     UpdateSize( firstWordGroupLayoutInfo.mSize, layoutInfo.mSize );
465     firstWordGroupLayoutInfo.mNumberOfCharacters += layoutInfo.mCharactersLayoutInfo.size();
466     firstWordGroupLayoutInfo.mAscender = std::max( firstWordGroupLayoutInfo.mAscender, layoutInfo.mAscender );
467   }
468 }
469
470 void MergeWordGroup( WordGroupLayoutInfo& firstWordGroupLayoutInfo,
471                      const WordGroupLayoutInfo& lastWordGroupLayoutInfo )
472 {
473   // Merges two given groups of words.
474   //
475   // Can't merge two groups if they have text with different directions (RTL , LTR )
476   // or if the last word of the first one is a line separator (new line character)
477
478   // Early returns
479
480   if( lastWordGroupLayoutInfo.mWordsLayoutInfo.empty() )
481   {
482     // Nothing to merge if last group is empty.
483     return;
484   }
485
486   if( firstWordGroupLayoutInfo.mWordsLayoutInfo.empty() )
487   {
488     // If first group is empty, just copy the last group to the first one.
489     firstWordGroupLayoutInfo = lastWordGroupLayoutInfo;
490
491     return;
492   }
493
494   // Check both groups have the same direction.
495   if( firstWordGroupLayoutInfo.mDirection != lastWordGroupLayoutInfo.mDirection )
496   {
497     DALI_ASSERT_ALWAYS( !"TextViewProcessor::MergeWordGroup(). ERROR: groups with different direction can't be merged." );
498   }
499
500   // Check first group doesn't finish with a new line character.
501   WordLayoutInfo& lastWordLayout( *( firstWordGroupLayoutInfo.mWordsLayoutInfo.end() - 1 ) );
502   if( LineSeparator == lastWordLayout.mType )
503   {
504     DALI_ASSERT_ALWAYS( !"TextViewProcessor::MergeWordGroup(). ERROR: A group of words can't be merged to another group which finishes with a new line character." );
505   }
506
507   // If the las word of the first group or the first word of the last group is a white space, both groups can be concatenated.
508   // Otherwise both words need to be merged first.
509   const WordLayoutInfo& firstWordLayout( *lastWordGroupLayoutInfo.mWordsLayoutInfo.begin() );
510
511   std::size_t index = 0;
512   if( ( WordSeparator != lastWordLayout.mType ) && ( WordSeparator != firstWordLayout.mType ) && ( LineSeparator != firstWordLayout.mType ) )
513   {
514     // Last word of the first group is not a word separator and first word of the last group is not a word or line separator.
515     // Words need to be merged.
516
517     MergeWord( lastWordLayout,
518                firstWordLayout );
519
520     // After merging two words, the rest of the words need to be added.
521     ++index; // By increasing this index the word already merged won't be added again.
522   }
523
524   // Merge layout info
525   firstWordGroupLayoutInfo.mWordsLayoutInfo.insert( firstWordGroupLayoutInfo.mWordsLayoutInfo.end(),
526                                                     lastWordGroupLayoutInfo.mWordsLayoutInfo.begin() + index, lastWordGroupLayoutInfo.mWordsLayoutInfo.end() );
527   UpdateSize( firstWordGroupLayoutInfo.mSize, lastWordGroupLayoutInfo.mSize );
528   firstWordGroupLayoutInfo.mAscender = std::max( firstWordGroupLayoutInfo.mAscender, lastWordGroupLayoutInfo.mAscender );
529   firstWordGroupLayoutInfo.mNumberOfCharacters += lastWordGroupLayoutInfo.mNumberOfCharacters;
530 }
531
532 void CollectTextActorsFromGroups( std::vector<TextActor>& textActors, const LineLayoutInfo& line, const std::size_t groupIndexBegin, const std::size_t groupIndexEnd )
533 {
534   for( WordGroupLayoutInfoContainer::const_iterator groupIt = line.mWordGroupsLayoutInfo.begin() + groupIndexBegin, groupEndIt = line.mWordGroupsLayoutInfo.begin() + groupIndexEnd;
535        groupIt != groupEndIt;
536        ++groupIt )
537   {
538     const WordGroupLayoutInfo& group( *groupIt );
539
540     CollectTextActorsFromWords( textActors, group, 0, group.mWordsLayoutInfo.size() );
541   }
542 }
543
544 } //namespace TextViewProcessor
545
546 } //namespace Internal
547
548 } //namespace Toolkit
549
550 } //namespace Dali