188377b89339f93b52d0adb58a3544f0b2d12d30
[platform/core/uifw/dali-toolkit.git] / automated-tests / dali-internal-test-suite / text-view / utc-Dali-TextView.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 #include <iostream>
18
19 #include <stdlib.h>
20 #include <tet_api.h>
21
22 #include <dali/public-api/dali-core.h>
23 #include <dali-toolkit/dali-toolkit.h>
24
25 #include <dali-toolkit-test-suite-utils.h>
26
27 // Internal headers are allowed here
28 #include <dali-toolkit/internal/controls/text-view/text-view-processor.h>
29 #include <dali-toolkit/internal/controls/text-view/text-view-line-processor.h>
30 #include <dali-toolkit/internal/controls/text-view/text-view-word-group-processor.h>
31 #include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
32 #include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
33
34 using namespace Dali;
35 using namespace Dali::Toolkit;
36 using namespace Dali::Toolkit::Internal;
37
38 namespace
39 {
40
41 const Toolkit::Internal::TextView::LayoutParameters DEFAULT_LAYOUT_PARAMETERS;
42 const Toolkit::Internal::TextView::VisualParameters DEFAULT_VISUAL_PARAMETERS;
43
44 // Data structures used to create an 'experiment' in TET cases
45
46 struct SplitWordTest
47 {
48   std::string description;
49   std::string input;
50   std::size_t position;
51   std::string firstResult;
52   std::string lastResult;
53 };
54
55 struct SplitWordGroupTest
56 {
57   std::string description;
58   std::string input;
59   std::size_t wordPosition;
60   std::size_t position;
61   std::string firstResult;
62   std::string lastResult;
63 };
64
65 struct SplitLineTest
66 {
67   std::string description;
68   std::string input;
69   std::size_t groupPosition;
70   std::size_t wordPosition;
71   std::size_t position;
72   float       lineHeightOffset;
73   std::string firstResult;
74   std::string lastResult;
75 };
76
77 struct MergeWordsTest
78 {
79   std::string description;
80   std::string inputFirst;
81   std::string inputLast;
82   std::string result;
83 };
84
85 struct MergeWordGroupsTest
86 {
87   std::string description;
88   std::string inputFirst;
89   std::string inputLast;
90   std::string result;
91 };
92
93 struct MergeLinesTest
94 {
95   std::string description;
96   std::string inputFirst;
97   std::string inputLast;
98   float       lineHeightOffset;
99   std::string result;
100 };
101
102 struct RemoveCharactersFromWordTest
103 {
104   std::string description;
105   std::string input;
106   std::size_t position;
107   std::size_t numberOfCharacters;
108   std::string result;
109 };
110
111 struct RemoveWordsFromGroupTest
112 {
113   std::string description;
114   std::string input;
115   std::size_t wordIndex;
116   std::size_t numberOfWords;
117   std::string result;
118 };
119
120 struct RemoveGroupsFromLineTest
121 {
122   std::string description;
123   std::string input;
124   std::size_t groupIndex;
125   std::size_t numberOfGroups;
126   float       lineHeightOffset;
127   std::string result;
128 };
129
130 enum UpdateTextInfoOperation
131 {
132   Insert,
133   Remove,
134   Replace
135 };
136
137 struct UpdateTextInfoTest
138 {
139   std::string             description;
140   UpdateTextInfoOperation operation;
141   std::string             input;
142   std::size_t             position;
143   std::size_t             numberOfCharacters;
144   std::string             inputText;
145   float                   lineHeightOffset;
146   std::string             result;
147 };
148
149 // Useful Print functions when something goes wrong.
150
151 void Print( const TextViewProcessor::CharacterLayoutInfo& character )
152 {
153   std::cout << "             height : " << character.mHeight << std::endl;
154   std::cout << "            advance : " << character.mAdvance << std::endl;
155   std::cout << "            bearing : " << character.mBearing << std::endl;
156   std::cout << "          mPosition : " << character.mPosition << std::endl;
157   std::cout << "              mSize : " << character.mSize << std::endl;
158   std::cout << "          mAscender : " << character.mAscender << std::endl;
159
160   TextActor textActor = TextActor::DownCast( character.mGlyphActor );
161   if( textActor )
162   {
163     std::cout << "[" << textActor.GetText() << "]";
164   }
165   else
166   {
167     std::cout << "{" << character.mStyledText.mText.GetText() << "}";
168   }
169 }
170
171 void Print( const TextViewProcessor::WordLayoutInfo& word )
172 {
173   std::cout << "[";
174   std::cout << "              mSize : " << word.mSize << std::endl;
175   std::cout << "          mAscender : " << word.mAscender << std::endl;
176   std::cout << "              mType : " << word.mType << std::endl;
177   std::cout << "mNumberOfCharacters : " << word.mCharactersLayoutInfo.size() << std::endl;
178   std::cout << "[";
179   for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator it = word.mCharactersLayoutInfo.begin(), endIt = word.mCharactersLayoutInfo.end(); it != endIt; ++it )
180   {
181     Print( *it );
182   }
183   std::cout << "]"; std::cout << std::endl;
184   std::cout << "]"; std::cout << std::endl;
185 }
186
187 void Print( const TextViewProcessor::WordGroupLayoutInfo& wordGroup )
188 {
189   std::cout << "(";
190   std::cout << "              mSize : " << wordGroup.mSize << std::endl;
191   std::cout << "          mAscender : " << wordGroup.mAscender << std::endl;
192   std::cout << "         mDirection : " << wordGroup.mDirection << std::endl;
193   std::cout << "mNumberOfCharacters : " << wordGroup.mNumberOfCharacters << std::endl;
194   for( TextViewProcessor::WordLayoutInfoContainer::const_iterator it = wordGroup.mWordsLayoutInfo.begin(), endIt = wordGroup.mWordsLayoutInfo.end(); it != endIt; ++it )
195   {
196     Print( *it );
197   }
198   std::cout << ")"; std::cout << std::endl;
199 }
200
201 void Print( const TextViewProcessor::LineLayoutInfo& line )
202 {
203   std::cout << "<";
204   std::cout << "              mSize : " << line.mSize << std::endl;
205   std::cout << "          mAscender : " << line.mAscender << std::endl;
206   std::cout << "mNumberOfCharacters : " << line.mNumberOfCharacters << std::endl;
207   for( TextViewProcessor::WordGroupLayoutInfoContainer::const_iterator it = line.mWordGroupsLayoutInfo.begin(), endIt = line.mWordGroupsLayoutInfo.end(); it != endIt; ++it )
208   {
209     Print( *it );
210   }
211   std::cout << ">" << std::endl;
212 }
213
214 void Print( const TextViewProcessor::TextLayoutInfo& text )
215 {
216   std::cout << "||";
217   for( TextViewProcessor::LineLayoutInfoContainer::const_iterator it = text.mLinesLayoutInfo.begin(), endIt = text.mLinesLayoutInfo.end(); it != endIt; ++it )
218   {
219     Print( *it );
220   }
221   std::cout << "||" << std::endl;
222 }
223
224 void Print( const TextStyle& style )
225 {
226   std::cout << " font name : " << style.GetFontName() << std::endl;
227   std::cout << " : " << style.GetFontStyle() << std::endl;
228   std::cout << " : " << style.GetFontPointSize() << std::endl;
229   std::cout << " : " << style.GetWeight() << std::endl;
230   std::cout << " : " << style.GetTextColor() << std::endl;
231   std::cout << " : " << style.GetItalics() << std::endl;
232   std::cout << " : " << style.GetUnderline() << std::endl;
233   std::cout << " : " << style.GetShadow() << std::endl;
234   std::cout << " : " << style.GetShadowColor() << std::endl;
235   std::cout << " : " << style.GetShadowOffset() << std::endl;
236   std::cout << " : " << style.GetGlow() << std::endl;
237   std::cout << " : " << style.GetGlowColor() << std::endl;
238   std::cout << " : " << style.GetGlowIntensity() << std::endl;
239   std::cout << " : " << style.GetSmoothEdge() << std::endl;
240   std::cout << " : " << style.GetOutline() << std::endl;
241   std::cout << " : " << style.GetOutlineThickness() << std::endl;
242 }
243
244 // Test functions used to check if two data structures are equal.
245
246 bool TestEqual( float x, float y )
247 {
248   return ( fabsf( x - y ) < Math::MACHINE_EPSILON_1000 );
249 }
250
251 bool TestEqual( const TextViewProcessor::CharacterLayoutInfo& character1,
252                 const TextViewProcessor::CharacterLayoutInfo& character2 )
253 {
254   if( !TestEqual( character1.mHeight, character2.mHeight ) )
255   {
256     return false;
257   }
258   if( !TestEqual( character1.mAdvance, character2.mAdvance ) )
259   {
260     return false;
261   }
262   if( !TestEqual( character1.mBearing, character2.mBearing ) )
263   {
264     return false;
265   }
266
267   if( !TestEqual( character1.mPosition.x, character2.mPosition.x ) )
268   {
269     return false;
270   }
271   if( !TestEqual( character1.mPosition.y, character2.mPosition.y ) )
272   {
273     return false;
274   }
275
276   if( !TestEqual( character1.mSize.x, character2.mSize.x ) )
277   {
278     return false;
279   }
280   if( !TestEqual( character1.mSize.y, character2.mSize.y ) )
281   {
282     return false;
283   }
284
285   if( !TestEqual( character1.mAscender, character2.mAscender ) )
286   {
287     return false;
288   }
289
290   if( character1.mGlyphActor && !character2.mGlyphActor )
291   {
292     return false;
293   }
294
295   if( !character1.mGlyphActor && character2.mGlyphActor )
296   {
297     return false;
298   }
299
300   std::string text1;
301   std::string text2;
302   TextStyle style1;
303   TextStyle style2;
304
305   TextActor textActor1 = TextActor::DownCast( character1.mGlyphActor );
306   TextActor textActor2 = TextActor::DownCast( character2.mGlyphActor );
307   if( textActor1 )
308   {
309     text1 = textActor1.GetText();
310     style1 = textActor1.GetTextStyle();
311
312     text2 = textActor2.GetText();
313     style2 = textActor2.GetTextStyle();
314   }
315
316   if( text1 != text2 )
317   {
318     return false;
319   }
320
321   if( style1 != style2 )
322   {
323     return false;
324   }
325
326   text1 = character1.mStyledText.mText.GetText();
327   style1 = character1.mStyledText.mStyle;
328
329   text2 = character2.mStyledText.mText.GetText();
330   style2 = character2.mStyledText.mStyle;
331
332   if( text1 != text2 )
333   {
334     return false;
335   }
336
337   if( style1 != style2 )
338   {
339     return false;
340   }
341
342   return true;
343 }
344
345 bool TestEqual( const TextViewProcessor::WordLayoutInfo& word1,
346                 const TextViewProcessor::WordLayoutInfo& word2 )
347 {
348   if( !TestEqual( word1.mSize.x, word2.mSize.x ) )
349   {
350     return false;
351   }
352   if( !TestEqual( word1.mSize.y, word2.mSize.y ) )
353   {
354     return false;
355   }
356
357   if( !TestEqual( word1.mAscender, word2.mAscender ) )
358   {
359     return false;
360   }
361
362   if( word1.mType != word2.mType )
363   {
364     return false;
365   }
366
367   if( word1.mCharactersLayoutInfo.size() != word2.mCharactersLayoutInfo.size() )
368   {
369     return false;
370   }
371
372   for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator it1 = word1.mCharactersLayoutInfo.begin(), endIt1 = word1.mCharactersLayoutInfo.end(),
373          it2 = word2.mCharactersLayoutInfo.begin(), endIt2 = word2.mCharactersLayoutInfo.end();
374        ( it1 != endIt1 ) && ( it2 != endIt2 );
375        ++it1, ++it2 )
376   {
377     if( !TestEqual( *it1, *it2 ) )
378     {
379       return false;
380     }
381   }
382
383   return true;
384 }
385
386 bool TestEqual( const TextViewProcessor::WordGroupLayoutInfo& group1,
387                 const TextViewProcessor::WordGroupLayoutInfo& group2 )
388 {
389
390   if( group1.mNumberOfCharacters != group2.mNumberOfCharacters )
391   {
392     return false;
393   }
394
395   if( group1.mWordsLayoutInfo.size() != group2.mWordsLayoutInfo.size() )
396   {
397     return false;
398   }
399
400   if( !TestEqual( group1.mSize.x, group2.mSize.x ) )
401   {
402     return false;
403   }
404   if( !TestEqual( group1.mSize.y, group2.mSize.y ) )
405   {
406     return false;
407   }
408
409   if( !TestEqual( group1.mAscender, group2.mAscender ) )
410   {
411     return false;
412   }
413
414   if( group1.mDirection != group2.mDirection )
415   {
416     return false;
417   }
418
419   for( TextViewProcessor::WordLayoutInfoContainer::const_iterator it1 = group1.mWordsLayoutInfo.begin(), endIt1 = group1.mWordsLayoutInfo.end(),
420          it2 = group2.mWordsLayoutInfo.begin(), endIt2 = group2.mWordsLayoutInfo.end();
421        ( it1 != endIt1 ) && ( it2 != endIt2 );
422        ++it1, ++it2 )
423   {
424     if( !TestEqual( *it1, *it2 ) )
425     {
426       return false;
427     }
428   }
429
430   return true;
431 }
432
433 bool TestEqual( const TextViewProcessor::LineLayoutInfo& line1,
434                 const TextViewProcessor::LineLayoutInfo& line2 )
435 {
436   if( !TestEqual( line1.mSize.x, line2.mSize.x ) )
437   {
438     return false;
439   }
440   if( !TestEqual( line1.mSize.y, line2.mSize.y ) )
441   {
442     return false;
443   }
444
445   if( !TestEqual( line1.mAscender, line2.mAscender ) )
446   {
447     return false;
448   }
449
450   if( line1.mNumberOfCharacters != line2.mNumberOfCharacters )
451   {
452     return false;
453   }
454
455   if( line1.mWordGroupsLayoutInfo.size() != line2.mWordGroupsLayoutInfo.size() )
456   {
457     return false;
458   }
459
460   for( TextViewProcessor::WordGroupLayoutInfoContainer::const_iterator it1 = line1.mWordGroupsLayoutInfo.begin(), endIt1 = line1.mWordGroupsLayoutInfo.end(),
461          it2 = line2.mWordGroupsLayoutInfo.begin(), endIt2 = line2.mWordGroupsLayoutInfo.end();
462        ( it1 != endIt1 ) && ( it2 != endIt2 );
463        ++it1, ++it2 )
464   {
465     if( !TestEqual( *it1, *it2 ) )
466     {
467       return false;
468     }
469   }
470
471   return true;
472 }
473
474 bool TestEqual( const TextViewProcessor::TextLayoutInfo& text1,
475                 const TextViewProcessor::TextLayoutInfo& text2 )
476 {
477   if( !TestEqual( text1.mWholeTextSize.x, text2.mWholeTextSize.x ) )
478   {
479     return false;
480   }
481   if( !TestEqual( text1.mWholeTextSize.y, text2.mWholeTextSize.y ) )
482   {
483     return false;
484   }
485
486   if( !TestEqual( text1.mMaxWordWidth, text2.mMaxWordWidth ) )
487   {
488     return false;
489   }
490
491   if( text1.mNumberOfCharacters != text2.mNumberOfCharacters )
492   {
493     return false;
494   }
495
496   if( text1.mLinesLayoutInfo.size() != text2.mLinesLayoutInfo.size() )
497   {
498     return false;
499   }
500
501   for( TextViewProcessor::LineLayoutInfoContainer::const_iterator it1 = text1.mLinesLayoutInfo.begin(), endIt1 = text1.mLinesLayoutInfo.end(),
502          it2 = text2.mLinesLayoutInfo.begin(), endIt2 = text2.mLinesLayoutInfo.end();
503        ( it1 != endIt1 ) && ( it2 != endIt2 );
504        ++it1, ++it2 )
505   {
506     if( !TestEqual( *it1, *it2 ) )
507     {
508       return false;
509     }
510   }
511
512   return true;
513 }
514
515 /**
516  * Splits the \e input word in two by the given \e position and checks the results with \e firstResult and \e lastResult.
517  *
518  * If the test fails it prints a short description and the line where this function was called.
519  *
520  * @param description Short description of the experiment. i.e. "Split the word from the beginning. (position 0)".
521  * @param input The input word.
522  * @param position Where to split the word.
523  * @param firstResult First part of the split word.
524  * @param lastResult Last part of the split word.
525  * @param location Where this function has been called.
526  *
527  * @return \e true if the experiment is successful. Otherwise returns \e false.
528  */
529 bool TestSplitWord( const std::string& description, const std::string& input, const size_t position, const std::string& firstResult, const std::string& lastResult, const char* location )
530 {
531   tet_printf( "%s", description.c_str() );
532
533   // Create layout info for the input word.
534   Toolkit::Internal::TextView::RelayoutData relayoutData;
535   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
536
537   MarkupProcessor::StyledTextArray inputStyledText;
538   MarkupProcessor::GetStyledTextArray( input, inputStyledText );
539
540   TextViewProcessor::CreateTextInfo( inputStyledText,
541                                      DEFAULT_LAYOUT_PARAMETERS,
542                                      relayoutData );
543
544   // Get the input word
545   TextViewProcessor::WordLayoutInfo inputWordLayout;
546
547   if( !inputLayout.mLinesLayoutInfo.empty() )
548   {
549     const TextViewProcessor::LineLayoutInfo& line( *inputLayout.mLinesLayoutInfo.begin() );
550     if( !line.mWordGroupsLayoutInfo.empty() )
551     {
552       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
553       if( !group.mWordsLayoutInfo.empty() )
554       {
555         inputWordLayout = *( *( *inputLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
556       }
557     }
558   }
559
560   // Create layout info for the first part of the result (after split the word)
561
562   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
563   TextViewProcessor::TextLayoutInfo& firstResultLayout( firstRelayoutData.mTextLayoutInfo );
564
565   MarkupProcessor::StyledTextArray firstResultStyledText;
566   MarkupProcessor::GetStyledTextArray( firstResult, firstResultStyledText );
567
568   TextViewProcessor::CreateTextInfo( firstResultStyledText,
569                                      DEFAULT_LAYOUT_PARAMETERS,
570                                      firstRelayoutData );
571
572   // Get the first result word
573   TextViewProcessor::WordLayoutInfo firstResultWordLayout;
574
575   if( !firstResultLayout.mLinesLayoutInfo.empty() )
576   {
577     const TextViewProcessor::LineLayoutInfo& line( *firstResultLayout.mLinesLayoutInfo.begin() );
578     if( !line.mWordGroupsLayoutInfo.empty() )
579     {
580       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
581       if( !group.mWordsLayoutInfo.empty() )
582       {
583         firstResultWordLayout = *( *( *firstResultLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
584       }
585     }
586   }
587
588   // Create layout info for the last part of the result (after split the word)
589
590   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
591   TextViewProcessor::TextLayoutInfo& lastResultLayout( lastRelayoutData.mTextLayoutInfo );
592
593   MarkupProcessor::StyledTextArray lastResultStyledText;
594   MarkupProcessor::GetStyledTextArray( lastResult, lastResultStyledText );
595
596   TextViewProcessor::CreateTextInfo( lastResultStyledText,
597                                      DEFAULT_LAYOUT_PARAMETERS,
598                                      lastRelayoutData );
599
600   // Get the last result word
601   TextViewProcessor::WordLayoutInfo lastResultWordLayout;
602
603   if( !lastResultLayout.mLinesLayoutInfo.empty() )
604   {
605     const TextViewProcessor::LineLayoutInfo& line( *lastResultLayout.mLinesLayoutInfo.begin() );
606     if( !line.mWordGroupsLayoutInfo.empty() )
607     {
608       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
609       if( !group.mWordsLayoutInfo.empty() )
610       {
611         lastResultWordLayout = *( *( *lastResultLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
612       }
613     }
614   }
615
616   // Split the word.
617
618   TextViewProcessor::WordLayoutInfo lastWordLayoutInfo;
619
620   SplitWord( position,
621              inputWordLayout,
622              lastWordLayoutInfo );
623
624   // Test results
625   if( !TestEqual( inputWordLayout, firstResultWordLayout ) )
626   {
627     tet_printf( "Fail. different layout info. %s", location );
628     return false;
629   }
630
631   if( !TestEqual( lastWordLayoutInfo, lastResultWordLayout ) )
632   {
633     tet_printf( "Fail. different layout info. %s", location );
634     return false;
635   }
636
637   return true;
638 }
639
640 /**
641  * Splits the \e input group of words in two by the given \e wordPosition and \e position and checks the results with \e firstResult and \e lastResult.
642  *
643  * If the test fails it prints a short description and the line where this function was called.
644  *
645  * @param description Short description of the experiment. i.e. "Split the group of words from the beginning. (wordPosition 0 and position 0)".
646  * @param input The input word.
647  * @param wordPosition Index to the word within the group where to split the group.
648  * @param position Where to split the word.
649  * @param firstResult First part of the split group of words.
650  * @param lastResult Last part of the split group of words.
651  * @param location Where this function has been called.
652  *
653  * @return \e true if the experiment is successful. Otherwise returns \e false.
654  */
655 bool TestSplitWordGroup( const std::string& description,
656                          const std::string& input,
657                          const size_t wordPosition,
658                          const size_t position,
659                          const std::string& firstResult,
660                          const std::string& lastResult,
661                          const char* location )
662 {
663   tet_printf( "%s", description.c_str() );
664
665   // Create layout info for the input group of words.
666   Toolkit::Internal::TextView::RelayoutData relayoutData;
667   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
668
669   MarkupProcessor::StyledTextArray inputStyledText;
670   MarkupProcessor::GetStyledTextArray( input, inputStyledText );
671
672   TextViewProcessor::CreateTextInfo( inputStyledText,
673                                      DEFAULT_LAYOUT_PARAMETERS,
674                                      relayoutData );
675
676   // Get the input group of words
677   TextViewProcessor::WordGroupLayoutInfo inputWordGroupLayout;
678
679   if( !inputLayout.mLinesLayoutInfo.empty() )
680   {
681     const TextViewProcessor::LineLayoutInfo& line( *inputLayout.mLinesLayoutInfo.begin() );
682     if( !line.mWordGroupsLayoutInfo.empty() )
683     {
684       inputWordGroupLayout = *( *inputLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
685     }
686   }
687
688   // Create layout info for the first part of the result (after split the group of words)
689
690   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
691   TextViewProcessor::TextLayoutInfo& firstResultLayout( firstRelayoutData.mTextLayoutInfo );
692
693   MarkupProcessor::StyledTextArray firstResultStyledText;
694   MarkupProcessor::GetStyledTextArray( firstResult, firstResultStyledText );
695
696   TextViewProcessor::CreateTextInfo( firstResultStyledText,
697                                      DEFAULT_LAYOUT_PARAMETERS,
698                                      firstRelayoutData );
699
700   // Get the first result group of words
701   TextViewProcessor::WordGroupLayoutInfo firstResultWordGroupLayout;
702
703   if( !firstResultLayout.mLinesLayoutInfo.empty() )
704   {
705     const TextViewProcessor::LineLayoutInfo& line( *firstResultLayout.mLinesLayoutInfo.begin() );
706     if( !line.mWordGroupsLayoutInfo.empty() )
707     {
708       firstResultWordGroupLayout = *( *firstResultLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
709     }
710   }
711
712   // Create layout info for the last part of the result (after split the group of words)
713
714   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
715   TextViewProcessor::TextLayoutInfo& lastResultLayout( lastRelayoutData.mTextLayoutInfo );
716
717   MarkupProcessor::StyledTextArray lastResultStyledText;
718   MarkupProcessor::GetStyledTextArray( lastResult, lastResultStyledText );
719
720   TextViewProcessor::CreateTextInfo( lastResultStyledText,
721                                      DEFAULT_LAYOUT_PARAMETERS,
722                                      lastRelayoutData );
723
724   // Get the last result group of words
725   TextViewProcessor::WordGroupLayoutInfo lastResultWordGroupLayout;
726
727   if( !lastResultLayout.mLinesLayoutInfo.empty() )
728   {
729     const TextViewProcessor::LineLayoutInfo& line( *lastResultLayout.mLinesLayoutInfo.begin() );
730     if( !line.mWordGroupsLayoutInfo.empty() )
731     {
732       lastResultWordGroupLayout = *( *lastResultLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
733     }
734   }
735
736   // Split the group of words.
737
738   TextViewProcessor::WordGroupLayoutInfo lastWordGroupLayoutInfo;
739
740   TextViewProcessor::TextInfoIndices indices( 0, 0, wordPosition, position );
741   SplitWordGroup( indices,
742                   inputWordGroupLayout,
743                   lastWordGroupLayoutInfo );
744
745   // Test results
746   if( !TestEqual( inputWordGroupLayout, firstResultWordGroupLayout ) )
747   {
748     tet_printf( "Fail. different layout info. %s", location );
749     return false;
750   }
751
752   if( !TestEqual( lastWordGroupLayoutInfo, lastResultWordGroupLayout ) )
753   {
754     tet_printf( "Fail. different layout info. %s", location );
755     return false;
756   }
757
758   return true;
759 }
760
761 /**
762  * Splits the \e input line in two by the given \e groupPosition, \e wordPosition and \e position and checks the results with \e firstResult and \e lastResult.
763  *
764  * If the test fails it prints a short description and the line where this function was called.
765  *
766  * @param description Short description of the experiment. i.e. "Split the line from the beginning. (groupPosition 0, wordPosition 0 and position 0)".
767  * @param input The input word.
768  * @param groupPosition Index to the group of words within the line where to split the line.
769  * @param wordPosition Index to the word within the group where to split the group.
770  * @param position Where to split the word.
771  * @param lineHeightOffset Offset between lines.
772  * @param firstResult First part of the split line.
773  * @param lastResult Last part of the split line.
774  * @param location Where this function has been called.
775  *
776  * @return \e true if the experiment is successful. Otherwise returns \e false.
777  */
778 bool TestSplitLine( const std::string& description,
779                     const std::string& input,
780                     const size_t groupPosition,
781                     const size_t wordPosition,
782                     const size_t position,
783                     const float lineHeightOffset,
784                     const std::string& firstResult,
785                     const std::string& lastResult,
786                     const char* location )
787 {
788   tet_printf( "%s", description.c_str() );
789
790   // Create layout info for the input line.
791   Toolkit::Internal::TextView::RelayoutData relayoutData;
792   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
793
794   MarkupProcessor::StyledTextArray inputStyledText;
795   MarkupProcessor::GetStyledTextArray( input, inputStyledText );
796
797   TextViewProcessor::CreateTextInfo( inputStyledText,
798                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
799                                                                                     Toolkit::TextView::Original,
800                                                                                     Toolkit::TextView::Original,
801                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
802                                                                                     Toolkit::TextView::Center,
803                                                                                     PointSize( lineHeightOffset ),
804                                                                                     std::string( "..." ) ),
805                                      relayoutData );
806
807   // Get the input line
808   TextViewProcessor::LineLayoutInfo inputLineLayout;
809
810   if( !inputLayout.mLinesLayoutInfo.empty() )
811   {
812     inputLineLayout = *inputLayout.mLinesLayoutInfo.begin();
813   }
814
815   // Create layout info for the first part of the result (after split the line)
816
817   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
818   TextViewProcessor::TextLayoutInfo& firstResultLayout( firstRelayoutData.mTextLayoutInfo );
819
820   MarkupProcessor::StyledTextArray firstResultStyledText;
821   MarkupProcessor::GetStyledTextArray( firstResult, firstResultStyledText );
822
823   TextViewProcessor::CreateTextInfo( firstResultStyledText,
824                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
825                                                                                     Toolkit::TextView::Original,
826                                                                                     Toolkit::TextView::Original,
827                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
828                                                                                     Toolkit::TextView::Center,
829                                                                                     PointSize( lineHeightOffset ),
830                                                                                     std::string( "..." ) ),
831                                      firstRelayoutData );
832
833   // Get the first result line
834   TextViewProcessor::LineLayoutInfo firstResultLineLayout;
835
836   if( !firstResultLayout.mLinesLayoutInfo.empty() )
837   {
838     firstResultLineLayout = *firstResultLayout.mLinesLayoutInfo.begin();
839   }
840
841   // Create layout info for the last part of the result (after split the line)
842
843   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
844   TextViewProcessor::TextLayoutInfo& lastResultLayout( lastRelayoutData.mTextLayoutInfo );
845
846   MarkupProcessor::StyledTextArray lastResultStyledText;
847   MarkupProcessor::GetStyledTextArray( lastResult, lastResultStyledText );
848
849   TextViewProcessor::CreateTextInfo( lastResultStyledText,
850                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
851                                                                                     Toolkit::TextView::Original,
852                                                                                     Toolkit::TextView::Original,
853                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
854                                                                                     Toolkit::TextView::Center,
855                                                                                     PointSize( lineHeightOffset ),
856                                                                                     std::string( "..." ) ),
857                                      lastRelayoutData );
858
859   // Get the last result line
860   TextViewProcessor::LineLayoutInfo lastResultLineLayout;
861
862   if( !lastResultLayout.mLinesLayoutInfo.empty() )
863   {
864     lastResultLineLayout = *lastResultLayout.mLinesLayoutInfo.begin();
865   }
866
867   // Split the line.
868
869   TextViewProcessor::LineLayoutInfo lastLineLayoutInfo;
870
871   TextViewProcessor::TextInfoIndices indices( 0, groupPosition, wordPosition, position );
872   SplitLine( indices,
873              PointSize( lineHeightOffset ),
874              inputLineLayout,
875              lastLineLayoutInfo );
876
877   // Test results
878   if( !TestEqual( inputLineLayout, firstResultLineLayout ) )
879   {
880     tet_printf( "Fail. different layout info. %s", location );
881     return false;
882   }
883
884   if( !TestEqual( lastLineLayoutInfo, lastResultLineLayout ) )
885   {
886     tet_printf( "Fail. different layout info. %s", location );
887     return false;
888   }
889
890   return true;
891 }
892
893 /**
894  * Merges the \e inputFirst word and the \e inputLast word, and checks the results with \e result.
895  *
896  * If the test fails it prints a short description and the line where this function was called.
897  *
898  * @param description Short description of the experiment. i.e. "Merge two words with same style".
899  * @param inputFirst The first part of the word.
900  * @param inputLast The last part of the word.
901  * @param result The merged word.
902  * @param location Where this function has been called.
903  *
904  * @return \e true if the experiment is successful. Otherwise returns \e false.
905  */
906 bool TestMergeWords( const std::string& description, const std::string& inputFirst, const std::string& inputLast, const std::string& result, const char* location )
907 {
908   tet_printf( "%s", description.c_str() );
909
910   // Create layout info for the inputFirst word.
911   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
912   TextViewProcessor::TextLayoutInfo& inputFirstLayout( firstRelayoutData.mTextLayoutInfo );
913
914   MarkupProcessor::StyledTextArray inputFirstStyledText;
915   MarkupProcessor::GetStyledTextArray( inputFirst, inputFirstStyledText );
916
917   TextViewProcessor::CreateTextInfo( inputFirstStyledText,
918                                      DEFAULT_LAYOUT_PARAMETERS,
919                                      firstRelayoutData );
920
921   // Get the input word
922   TextViewProcessor::WordLayoutInfo inputFirstWordLayout;
923
924   if( !inputFirstLayout.mLinesLayoutInfo.empty() )
925   {
926     const TextViewProcessor::LineLayoutInfo& line( *inputFirstLayout.mLinesLayoutInfo.begin() );
927     if( !line.mWordGroupsLayoutInfo.empty() )
928     {
929       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
930       if( !group.mWordsLayoutInfo.empty() )
931       {
932         inputFirstWordLayout = *( *( *inputFirstLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
933       }
934     }
935   }
936
937   // Create layout info for the inputLast word.
938   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
939   TextViewProcessor::TextLayoutInfo& inputLastLayout( lastRelayoutData.mTextLayoutInfo );
940
941   MarkupProcessor::StyledTextArray inputLastStyledText;
942   MarkupProcessor::GetStyledTextArray( inputLast, inputLastStyledText );
943
944   TextViewProcessor::CreateTextInfo( inputLastStyledText,
945                                      DEFAULT_LAYOUT_PARAMETERS,
946                                      lastRelayoutData );
947
948   // Get the input word
949   TextViewProcessor::WordLayoutInfo inputLastWordLayout;
950
951   if( !inputLastLayout.mLinesLayoutInfo.empty() )
952   {
953     const TextViewProcessor::LineLayoutInfo& line( *inputLastLayout.mLinesLayoutInfo.begin() );
954     if( !line.mWordGroupsLayoutInfo.empty() )
955     {
956       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
957       if( !group.mWordsLayoutInfo.empty() )
958       {
959         inputLastWordLayout = *( *( *inputLastLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
960       }
961     }
962   }
963
964   // Create layout info for the result word.
965   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
966   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
967
968   MarkupProcessor::StyledTextArray resultStyledText;
969   MarkupProcessor::GetStyledTextArray( result, resultStyledText );
970
971   TextViewProcessor::CreateTextInfo( resultStyledText,
972                                      DEFAULT_LAYOUT_PARAMETERS,
973                                      resultRelayoutData );
974
975   // Get the result word
976   TextViewProcessor::WordLayoutInfo resultWordLayout;
977
978   if( !resultLayout.mLinesLayoutInfo.empty() )
979   {
980     const TextViewProcessor::LineLayoutInfo& line( *resultLayout.mLinesLayoutInfo.begin() );
981     if( !line.mWordGroupsLayoutInfo.empty() )
982     {
983       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
984       if( !group.mWordsLayoutInfo.empty() )
985       {
986         resultWordLayout = *( *( *resultLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
987       }
988     }
989   }
990
991   MergeWord( inputFirstWordLayout,
992              inputLastWordLayout );
993
994   if( !TestEqual( inputFirstWordLayout, resultWordLayout ) )
995   {
996     tet_printf( "Fail. different layout info. %s", location );
997     return false;
998   }
999
1000   return true;
1001 }
1002
1003 /**
1004  * Merges the \e inputFirst group of words and the \e inputLast group of words, and checks the results with \e result.
1005  *
1006  * If the test fails it prints a short description and the line where this function was called.
1007  *
1008  * @param description Short description of the experiment.
1009  * @param inputFirst The first part of the group of words.
1010  * @param inputLast The last part of the group of words.
1011  * @param result The merged group of word.
1012  * @param location Where this function has been called.
1013  *
1014  * @return \e true if the experiment is successful. Otherwise returns \e false.
1015  */
1016 bool TestMergeGroupsOfWords( const std::string& description, const std::string& inputFirst, const std::string& inputLast, const std::string& result, const char* location )
1017 {
1018   tet_printf( "%s", description.c_str() );
1019
1020   // Create layout info for the inputFirst group of word.
1021   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
1022   TextViewProcessor::TextLayoutInfo& inputFirstLayout( firstRelayoutData.mTextLayoutInfo );
1023
1024   MarkupProcessor::StyledTextArray inputFirstStyledText;
1025   MarkupProcessor::GetStyledTextArray( inputFirst, inputFirstStyledText );
1026
1027   TextViewProcessor::CreateTextInfo( inputFirstStyledText,
1028                                      DEFAULT_LAYOUT_PARAMETERS,
1029                                      firstRelayoutData );
1030
1031   // Get the input group of words.
1032   TextViewProcessor::WordGroupLayoutInfo inputFirstWordGroupLayout;
1033
1034   if( !inputFirstLayout.mLinesLayoutInfo.empty() )
1035   {
1036     const TextViewProcessor::LineLayoutInfo& line( *inputFirstLayout.mLinesLayoutInfo.begin() );
1037     if( !line.mWordGroupsLayoutInfo.empty() )
1038     {
1039       inputFirstWordGroupLayout = *( *inputFirstLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
1040     }
1041   }
1042
1043   // Create layout info for the inputLast group of words.
1044   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
1045   TextViewProcessor::TextLayoutInfo& inputLastLayout( lastRelayoutData.mTextLayoutInfo );
1046
1047   MarkupProcessor::StyledTextArray inputLastStyledText;
1048   MarkupProcessor::GetStyledTextArray( inputLast, inputLastStyledText );
1049
1050   TextViewProcessor::CreateTextInfo( inputLastStyledText,
1051                                      DEFAULT_LAYOUT_PARAMETERS,
1052                                      lastRelayoutData );
1053
1054   // Get the input group of words
1055   TextViewProcessor::WordGroupLayoutInfo inputLastWordGroupLayout;
1056
1057   if( !inputLastLayout.mLinesLayoutInfo.empty() )
1058   {
1059     const TextViewProcessor::LineLayoutInfo& line( *inputLastLayout.mLinesLayoutInfo.begin() );
1060     if( !line.mWordGroupsLayoutInfo.empty() )
1061     {
1062       inputLastWordGroupLayout = *( *inputLastLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
1063     }
1064   }
1065
1066   // Create layout info for the result group of words.
1067   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1068   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1069
1070   MarkupProcessor::StyledTextArray resultStyledText;
1071   MarkupProcessor::GetStyledTextArray( result, resultStyledText );
1072
1073   TextViewProcessor::CreateTextInfo( resultStyledText,
1074                                      DEFAULT_LAYOUT_PARAMETERS,
1075                                      resultRelayoutData );
1076
1077   // Get the result word
1078   TextViewProcessor::WordGroupLayoutInfo resultWordGroupLayout;
1079
1080   if( !resultLayout.mLinesLayoutInfo.empty() )
1081   {
1082     const TextViewProcessor::LineLayoutInfo& line( *resultLayout.mLinesLayoutInfo.begin() );
1083     if( !line.mWordGroupsLayoutInfo.empty() )
1084     {
1085       resultWordGroupLayout = *( *resultLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
1086     }
1087   }
1088
1089   MergeWordGroup( inputFirstWordGroupLayout,
1090                   inputLastWordGroupLayout );
1091
1092   if( !TestEqual( inputFirstWordGroupLayout, resultWordGroupLayout ) )
1093   {
1094     tet_printf( "Fail. different layout info. %s", location );
1095     return false;
1096   }
1097
1098   return true;
1099 }
1100
1101 /**
1102  * Merges the \e inputFirst line and the \e inputLast line, and checks the results with \e result.
1103  *
1104  * If the test fails it prints a short description and the line where this function was called.
1105  *
1106  * @param description Short description of the experiment.
1107  * @param inputFirst The first part of the line.
1108  * @param inputLast The last part of the line.
1109  * @param lineHeightOffset Offset between lines.
1110  * @param result The merged line.
1111  * @param location Where this function has been called.
1112  *
1113  * @return \e true if the experiment is successful. Otherwise returns \e false.
1114  */
1115 bool TestMergeLines( const std::string& description, const std::string& inputFirst, const std::string& inputLast, const float lineHeightOffset, const std::string& result, const char* location )
1116 {
1117   tet_printf( "%s", description.c_str() );
1118
1119   // Create layout info for the inputFirst line.
1120   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
1121   TextViewProcessor::TextLayoutInfo& inputFirstLayout( firstRelayoutData.mTextLayoutInfo );
1122
1123   MarkupProcessor::StyledTextArray inputFirstStyledText;
1124   MarkupProcessor::GetStyledTextArray( inputFirst, inputFirstStyledText );
1125
1126   TextViewProcessor::CreateTextInfo( inputFirstStyledText,
1127                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1128                                                                                     Toolkit::TextView::Original,
1129                                                                                     Toolkit::TextView::Original,
1130                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1131                                                                                     Toolkit::TextView::Center,
1132                                                                                     PointSize( lineHeightOffset ),
1133                                                                                     std::string( "..." ) ),
1134                                      firstRelayoutData );
1135
1136   // Get the input word
1137   TextViewProcessor::LineLayoutInfo inputFirstLineLayout;
1138
1139   if( !inputFirstLayout.mLinesLayoutInfo.empty() )
1140   {
1141     inputFirstLineLayout = *inputFirstLayout.mLinesLayoutInfo.begin();
1142   }
1143
1144   // Create layout info for the inputLast line.
1145   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
1146   TextViewProcessor::TextLayoutInfo& inputLastLayout( lastRelayoutData.mTextLayoutInfo );
1147
1148   MarkupProcessor::StyledTextArray inputLastStyledText;
1149   MarkupProcessor::GetStyledTextArray( inputLast, inputLastStyledText );
1150
1151   TextViewProcessor::CreateTextInfo( inputLastStyledText,
1152                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1153                                                                                     Toolkit::TextView::Original,
1154                                                                                     Toolkit::TextView::Original,
1155                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1156                                                                                     Toolkit::TextView::Center,
1157                                                                                     PointSize( lineHeightOffset ),
1158                                                                                     std::string( "..." ) ),
1159                                      lastRelayoutData );
1160
1161   // Get the input word
1162   TextViewProcessor::LineLayoutInfo inputLastLineLayout;
1163
1164   if( !inputLastLayout.mLinesLayoutInfo.empty() )
1165   {
1166     inputLastLineLayout = *inputLastLayout.mLinesLayoutInfo.begin();
1167   }
1168
1169   // Create layout info for the result word.
1170   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1171   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1172
1173   MarkupProcessor::StyledTextArray resultStyledText;
1174   MarkupProcessor::GetStyledTextArray( result, resultStyledText );
1175
1176   TextViewProcessor::CreateTextInfo( resultStyledText,
1177                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1178                                                                                     Toolkit::TextView::Original,
1179                                                                                     Toolkit::TextView::Original,
1180                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1181                                                                                     Toolkit::TextView::Center,
1182                                                                                     PointSize( lineHeightOffset ),
1183                                                                                     std::string( "..." ) ),
1184                                      resultRelayoutData );
1185
1186   // Get the result word
1187   TextViewProcessor::LineLayoutInfo resultLineLayout;
1188
1189   if( !resultLayout.mLinesLayoutInfo.empty() )
1190   {
1191     resultLineLayout = *resultLayout.mLinesLayoutInfo.begin();
1192   }
1193
1194   MergeLine( inputFirstLineLayout,
1195              inputLastLineLayout );
1196
1197   if( !TestEqual( inputFirstLineLayout, resultLineLayout ) )
1198   {
1199     tet_printf( "Fail. different layout info. %s", location );
1200     return false;
1201   }
1202
1203   return true;
1204 }
1205
1206 /**
1207  * Removes from the \e input word the \e numberOfCharacters characters starting from the given \e position and checks the results with \e result.
1208  *
1209  * If the test fails it prints a short description and the line where this function was called.
1210  *
1211  * @param description Short description of the experiment. i.e. "Remove a whole group of characters. Merge".
1212  * @param input The input word.
1213  * @param position Where to start to remove characters
1214  * @param numberOfCharacters The number of characters to remove.
1215  * @param result The word without the removed characters.
1216  * @param location Where this function has been called.
1217  *
1218  * @return \e true if the experiment is successful. Otherwise returns \e false.
1219  */
1220 bool TestRemoveCharactersFromWord( const std::string& description, const std::string& input, const std::size_t position, const std::size_t numberOfCharacters, const std::string& result, const char* location )
1221 {
1222   tet_printf( "%s", description.c_str() );
1223
1224   // Create layout info for the input word.
1225   Toolkit::Internal::TextView::RelayoutData relayoutData;
1226   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
1227
1228   MarkupProcessor::StyledTextArray inputStyledText;
1229   MarkupProcessor::GetStyledTextArray( input, inputStyledText );
1230
1231   TextViewProcessor::CreateTextInfo( inputStyledText,
1232                                      DEFAULT_LAYOUT_PARAMETERS,
1233                                      relayoutData );
1234
1235   // Get the input word
1236   TextViewProcessor::WordLayoutInfo inputWordLayout;
1237
1238   if( !inputLayout.mLinesLayoutInfo.empty() )
1239   {
1240     const TextViewProcessor::LineLayoutInfo& line( *inputLayout.mLinesLayoutInfo.begin() );
1241     if( !line.mWordGroupsLayoutInfo.empty() )
1242     {
1243       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
1244       if( !group.mWordsLayoutInfo.empty() )
1245       {
1246         inputWordLayout = *( *( *inputLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
1247       }
1248     }
1249   }
1250
1251   // Create layout info for the result word.
1252   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1253   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1254
1255   MarkupProcessor::StyledTextArray resultStyledText;
1256   MarkupProcessor::GetStyledTextArray( result, resultStyledText );
1257
1258   TextViewProcessor::CreateTextInfo( resultStyledText,
1259                                      DEFAULT_LAYOUT_PARAMETERS,
1260                                      resultRelayoutData );
1261
1262   // Get the result word
1263   TextViewProcessor::WordLayoutInfo resultWordLayout;
1264
1265   if( !resultLayout.mLinesLayoutInfo.empty() )
1266   {
1267     const TextViewProcessor::LineLayoutInfo& line( *resultLayout.mLinesLayoutInfo.begin() );
1268     if( !line.mWordGroupsLayoutInfo.empty() )
1269     {
1270       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
1271       if( !group.mWordsLayoutInfo.empty() )
1272       {
1273         resultWordLayout = *( *( *resultLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
1274       }
1275     }
1276   }
1277
1278   RemoveCharactersFromWord( position,
1279                             numberOfCharacters,
1280                             inputWordLayout );
1281
1282   if( !TestEqual( inputWordLayout, resultWordLayout ) )
1283   {
1284     tet_printf( "Fail. different layout info. %s", location );
1285     return false;
1286   }
1287
1288   return true;
1289 }
1290
1291 /**
1292  * Removes from the \e input group of words the \e numberOfWords words starting from the given \e wordIndex and checks the results with \e result.
1293  *
1294  * If the test fails it prints a short description and the line where this function was called.
1295  *
1296  * @param description Short description of the experiment.
1297  * @param input The input group of words.
1298  * @param wordIndex Where to start to remove words.
1299  * @param numberOfWords The number of words to remove.
1300  * @param result The group of words without the removed words.
1301  * @param location Where this function has been called.
1302  *
1303  * @return \e true if the experiment is successful. Otherwise returns \e false.
1304  */
1305 bool TestRemoveWordsFromGroup( const std::string& description, const std::string& input, const std::size_t wordIndex, const std::size_t numberOfWords, const std::string& result, const char* location )
1306 {
1307   tet_printf( "%s", description.c_str() );
1308
1309   // Create layout info for the input group of words.
1310   Toolkit::Internal::TextView::RelayoutData relayoutData;
1311   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
1312
1313   MarkupProcessor::StyledTextArray inputStyledText;
1314   MarkupProcessor::GetStyledTextArray( input, inputStyledText );
1315
1316   TextViewProcessor::CreateTextInfo( inputStyledText,
1317                                      DEFAULT_LAYOUT_PARAMETERS,
1318                                      relayoutData );
1319
1320   // Get the input group of words
1321   TextViewProcessor::WordGroupLayoutInfo inputWordGroupLayout;
1322
1323   if( !inputLayout.mLinesLayoutInfo.empty() )
1324   {
1325     const TextViewProcessor::LineLayoutInfo& line( *inputLayout.mLinesLayoutInfo.begin() );
1326     if( !line.mWordGroupsLayoutInfo.empty() )
1327     {
1328       inputWordGroupLayout = *( *inputLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
1329     }
1330   }
1331
1332   // Create layout info for the result group of words.
1333   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1334   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1335
1336   MarkupProcessor::StyledTextArray resultStyledText;
1337   MarkupProcessor::GetStyledTextArray( result, resultStyledText );
1338
1339   TextViewProcessor::CreateTextInfo( resultStyledText,
1340                                      DEFAULT_LAYOUT_PARAMETERS,
1341                                      resultRelayoutData );
1342
1343   // Get the result group of words.
1344   TextViewProcessor::WordGroupLayoutInfo resultWordGroupLayout;
1345
1346   if( !resultLayout.mLinesLayoutInfo.empty() )
1347   {
1348     const TextViewProcessor::LineLayoutInfo& line( *resultLayout.mLinesLayoutInfo.begin() );
1349     if( !line.mWordGroupsLayoutInfo.empty() )
1350     {
1351       resultWordGroupLayout = *( *resultLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
1352     }
1353   }
1354
1355   RemoveWordsFromWordGroup( wordIndex,
1356                             numberOfWords,
1357                             inputWordGroupLayout );
1358
1359   if( !TestEqual( inputWordGroupLayout, resultWordGroupLayout ) )
1360   {
1361     tet_printf( "Fail. different layout info. %s", location );
1362     return false;
1363   }
1364
1365   return true;
1366 }
1367
1368
1369 /**
1370  * Removes from the \e input line the \e numberOfGroups groups of words starting from the given \e groupIndex and checks the results with \e result.
1371  *
1372  * If the test fails it prints a short description and the line where this function was called.
1373  *
1374  * @param description Short description of the experiment.
1375  * @param input The input line.
1376  * @param groupIndex Where to start to remove groups of words
1377  * @param numberOfGroups The number of groups of words to remove.
1378  * @param lineHeightOffset Offset between lines.
1379  * @param result The line without the removed groups of words.
1380  * @param location Where this function has been called.
1381  *
1382  * @return \e true if the experiment is successful. Otherwise returns \e false.
1383  */
1384 bool TestRemoveGroupsFromLine( const std::string& description, const std::string& input, const std::size_t groupIndex, const std::size_t numberOfGroups, const float lineHeightOffset, const std::string& result, const char* location )
1385 {
1386   tet_printf( "%s", description.c_str() );
1387
1388   // Create layout info for the input line.
1389   Toolkit::Internal::TextView::RelayoutData relayoutData;
1390   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
1391
1392   MarkupProcessor::StyledTextArray inputStyledText;
1393   MarkupProcessor::GetStyledTextArray( input, inputStyledText );
1394
1395   TextViewProcessor::CreateTextInfo( inputStyledText,
1396                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1397                                                                                     Toolkit::TextView::Original,
1398                                                                                     Toolkit::TextView::Original,
1399                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1400                                                                                     Toolkit::TextView::Center,
1401                                                                                     PointSize( lineHeightOffset ),
1402                                                                                     std::string( "..." ) ),
1403                                      relayoutData );
1404
1405   // Get the input line
1406   TextViewProcessor::LineLayoutInfo inputLineLayout;
1407
1408   if( !inputLayout.mLinesLayoutInfo.empty() )
1409   {
1410     inputLineLayout = *inputLayout.mLinesLayoutInfo.begin();
1411   }
1412
1413   // Create layout info for the result line.
1414   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1415   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1416
1417   MarkupProcessor::StyledTextArray resultStyledText;
1418   MarkupProcessor::GetStyledTextArray( result, resultStyledText );
1419
1420   TextViewProcessor::CreateTextInfo( resultStyledText,
1421                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1422                                                                                     Toolkit::TextView::Original,
1423                                                                                     Toolkit::TextView::Original,
1424                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1425                                                                                     Toolkit::TextView::Center,
1426                                                                                     PointSize( lineHeightOffset ),
1427                                                                                     std::string( "..." ) ),
1428                                      resultRelayoutData );
1429
1430   // Get the result line
1431   TextViewProcessor::LineLayoutInfo resultLineLayout;
1432
1433   if( !resultLayout.mLinesLayoutInfo.empty() )
1434   {
1435     resultLineLayout = *resultLayout.mLinesLayoutInfo.begin();
1436   }
1437
1438   RemoveWordGroupsFromLine( groupIndex,
1439                             numberOfGroups,
1440                             PointSize( lineHeightOffset ),
1441                             inputLineLayout );
1442
1443   if( !TestEqual( inputLineLayout, resultLineLayout ) )
1444   {
1445     tet_printf( "Fail. different layout info. %s", location );
1446     return false;
1447   }
1448
1449   return true;
1450 }
1451
1452 /**
1453  * Tests inserts, removes and updates operation in the given \e input text and checks with the given \e result.
1454  *
1455  * If the test fails it prints a short description and the line where this function was called.
1456  *
1457  * @param description Short description of the experiment.
1458  * @param operation Type of update operation (insert, remove, replace)
1459  * @param input The input text.
1460  * @param position Where to insert, remove or replace text.
1461  * @param numberOfCharacters Number of characters to remove or replace.
1462  * @param inputText Inserted or updated text.
1463  * @param lineHeightOffset Offset between lines.
1464  * @param result Expected result.
1465  * @param location Where this function has been called.
1466  *
1467  * @return \e true if the experiment is successful. Otherwise returns \e false.
1468  */
1469 bool TestUpdateTextInfo( const std::string& description,
1470                          const UpdateTextInfoOperation operation,
1471                          const std::string& input,
1472                          const std::size_t position,
1473                          const std::size_t numberOfCharacters,
1474                          const std::string& inputText,
1475                          const float lineHeightOffset,
1476                          const std::string& result,
1477                          const char* location )
1478 {
1479   tet_printf( "%s", description.c_str() );
1480
1481   // Create layout info for the input.
1482   Toolkit::Internal::TextView::RelayoutData relayoutData;
1483   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
1484
1485   MarkupProcessor::StyledTextArray inputStyledText;
1486   MarkupProcessor::GetStyledTextArray( input, inputStyledText );
1487
1488   TextViewProcessor::CreateTextInfo( inputStyledText,
1489                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1490                                                                                     Toolkit::TextView::Original,
1491                                                                                     Toolkit::TextView::Original,
1492                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1493                                                                                     Toolkit::TextView::Center,
1494                                                                                     PointSize( lineHeightOffset ),
1495                                                                                     std::string( "..." ) ),
1496                                      relayoutData );
1497
1498   // Create layout info for the result.
1499   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1500   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1501
1502   MarkupProcessor::StyledTextArray resultStyledText;
1503   MarkupProcessor::GetStyledTextArray( result, resultStyledText );
1504
1505   TextViewProcessor::CreateTextInfo( resultStyledText,
1506                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1507                                                                                     Toolkit::TextView::Original,
1508                                                                                     Toolkit::TextView::Original,
1509                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1510                                                                                     Toolkit::TextView::Center,
1511                                                                                     PointSize( lineHeightOffset ),
1512                                                                                     std::string( "..." ) ),
1513                                      resultRelayoutData );
1514
1515   // Choose operation and call appropiate UpdateTextInfo() method.
1516   const Toolkit::Internal::TextView::LayoutParameters layoutParameters( Toolkit::TextView::SplitByNewLineChar,
1517                                                                         Toolkit::TextView::Original,
1518                                                                         Toolkit::TextView::Original,
1519                                                                         static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1520                                                                         Toolkit::TextView::Center,
1521                                                                         PointSize( lineHeightOffset ),
1522                                                                         std::string( "..." ) );
1523
1524   switch( operation )
1525   {
1526     case Insert:
1527     {
1528       MarkupProcessor::StyledTextArray inputStyledText;
1529       MarkupProcessor::GetStyledTextArray( inputText, inputStyledText );
1530
1531       TextViewProcessor::UpdateTextInfo( position,
1532                                          inputStyledText,
1533                                          layoutParameters,
1534                                          relayoutData );
1535       break;
1536     }
1537     case Remove:
1538     {
1539       TextViewProcessor::UpdateTextInfo( position,
1540                                          numberOfCharacters,
1541                                          layoutParameters,
1542                                          relayoutData,
1543                                          TextViewProcessor::CLEAR_TEXT );
1544       break;
1545     }
1546     case Replace:
1547     {
1548       MarkupProcessor::StyledTextArray inputStyledText;
1549       MarkupProcessor::GetStyledTextArray( inputText, inputStyledText );
1550
1551       TextViewProcessor::UpdateTextInfo( position,
1552                                          numberOfCharacters,
1553                                          inputStyledText,
1554                                          layoutParameters,
1555                                          relayoutData );
1556       break;
1557     }
1558     default:
1559     {
1560       tet_printf( "TestUpdateTextInfo: unknown update operation. %s", location );
1561       return false;
1562     }
1563   }
1564
1565   if( !TestEqual( inputLayout, resultLayout ) )
1566   {
1567     tet_printf( "Fail. different layout info. %s", location );
1568
1569     std::cout << "          result : "; Print( inputLayout );
1570     std::cout << " expected result : "; Print( resultLayout );
1571     return false;
1572   }
1573
1574   return true;
1575 }
1576
1577 } // namespace
1578
1579 static void Startup();
1580 static void Cleanup();
1581
1582 extern "C" {
1583   void (*tet_startup)() = Startup;
1584   void (*tet_cleanup)() = Cleanup;
1585 }
1586
1587 enum {
1588   POSITIVE_TC_IDX = 0x01,
1589   NEGATIVE_TC_IDX,
1590 };
1591
1592 #define MAX_NUMBER_OF_TESTS 10000
1593 extern "C" {
1594   struct tet_testlist tet_testlist[MAX_NUMBER_OF_TESTS];
1595 }
1596
1597 // Add test functionality for all APIs in the class (Positive and Negative)
1598 TEST_FUNCTION( UtcDaliTextViewCreateTextInfo, POSITIVE_TC_IDX );                     // Tests data structures are built well.
1599 TEST_FUNCTION( UtcDaliTextViewUpdateTextInfo, POSITIVE_TC_IDX );                     // Tests update operations within a whole text (insert, remove, replace).
1600 TEST_FUNCTION( UtcDaliTextViewSplitWord, POSITIVE_TC_IDX );                          // Tests the split word operation.
1601 TEST_FUNCTION( UtcDaliTextViewSplitWordGroup, POSITIVE_TC_IDX );                     // Tests the split group of words operation.
1602 TEST_FUNCTION( UtcDaliTextViewSplitLine, POSITIVE_TC_IDX );                          // Tests the split line operation.
1603 TEST_FUNCTION( UtcDaliTextViewMergeWord01, POSITIVE_TC_IDX );                        // Tests the merge word operation.
1604 TEST_FUNCTION( UtcDaliTextViewMergeWord02, NEGATIVE_TC_IDX );                        // Tests invalid inputs in the merge word operation.
1605 TEST_FUNCTION( UtcDaliTextViewMergeGroup01, POSITIVE_TC_IDX );                       // Tests the merge group of words operation.
1606 TEST_FUNCTION( UtcDaliTextViewMergeGroup02, NEGATIVE_TC_IDX );                       // Tests invalid inputs in the merge group of words operation.
1607 TEST_FUNCTION( UtcDaliTextViewMergeLine01, POSITIVE_TC_IDX );                        // Tests the merge line operation.
1608 TEST_FUNCTION( UtcDaliTextViewMergeLine02, NEGATIVE_TC_IDX );                        // Tests invalid inputs in the merge line operation.
1609 TEST_FUNCTION( UtcDaliTextViewRemoveCharactersFromWord, POSITIVE_TC_IDX );           // Tests the remove characters from a word operation.
1610 TEST_FUNCTION( UtcDaliTextViewRemoveWordsFromGroup, POSITIVE_TC_IDX );               // Tests the remove words from a group of words operation.
1611 TEST_FUNCTION( UtcDaliTextViewRemoveGroupsFromLine, POSITIVE_TC_IDX );               // Tests the remove groups of words from a line operation.
1612
1613 // Called only once before first test is run.
1614 static void Startup()
1615 {
1616 }
1617
1618 // Called only once after last test is run
1619 static void Cleanup()
1620 {
1621 }
1622
1623 static void UtcDaliTextViewCreateTextInfo()
1624 {
1625   ToolkitTestApplication application;
1626
1627   tet_infoline("UtcDaliTextViewCreateTextInfo : ");
1628
1629   // Metrics for characters
1630
1631   // Font size = 10
1632   //     size : [9.48351, 9.48351]
1633   //  advance : 9.48351
1634   //  bearing : 8.53516
1635   // ascender : 8.53516
1636
1637   // Font size = 12
1638   //     size : [11.3802, 11.3802]
1639   //  advance : 11.3802
1640   //  bearing : 10.2422
1641   // ascender : 10.2422
1642
1643   // Font size = 14
1644   //     size : [13.2769, 13.2769]
1645   //  advance : 13.2769
1646   //  bearing : 11.9492
1647   // ascender : 11.9492
1648
1649   const float WIDTH_10( 9.48351f );
1650   const float HEIGHT_10( 9.48351f );
1651   const float ADVANCE_10( 9.48351f );
1652   const float BEARING_10( 8.53516f );
1653   const float ASCENDER_10( 8.53516f );
1654
1655   const float WIDTH_12( 11.3802f );
1656   const float HEIGHT_12( 11.3802f );
1657   const float ADVANCE_12( 11.3802f );
1658   const float BEARING_12( 10.2422f );
1659   const float ASCENDER_12( 10.2422f );
1660
1661
1662   // Generate a text.
1663   Toolkit::Internal::TextView::RelayoutData relayoutData;
1664   TextViewProcessor::TextLayoutInfo& textLayoutInfo( relayoutData.mTextLayoutInfo );
1665
1666   std::string text( "Hel<font size='10'>lo wo</font>rld!\n"
1667                     "\n" );
1668
1669   MarkupProcessor::StyledTextArray styledText;
1670   MarkupProcessor::GetStyledTextArray( text, styledText );
1671
1672   TextViewProcessor::CreateTextInfo( styledText,
1673                                      DEFAULT_LAYOUT_PARAMETERS,
1674                                      relayoutData );
1675
1676
1677   // Build the text info with metric values.
1678
1679   // Characters
1680
1681   TextViewProcessor::CharacterLayoutInfo layoutInfo10; // ( [lo wo])
1682   layoutInfo10.mHeight = HEIGHT_10;
1683   layoutInfo10.mAdvance = ADVANCE_10;
1684   layoutInfo10.mBearing = BEARING_10;
1685   layoutInfo10.mSize = Size( WIDTH_10, HEIGHT_10 );
1686   layoutInfo10.mAscender = ASCENDER_10;
1687   TextViewProcessor::CharacterLayoutInfo layoutInfo12; // ( [Hel], [rld!] and [CR])
1688   layoutInfo12.mHeight = HEIGHT_12;
1689   layoutInfo12.mAdvance = ADVANCE_12;
1690   layoutInfo12.mBearing = BEARING_12;
1691   layoutInfo12.mSize = Size( WIDTH_12, HEIGHT_12 );
1692   layoutInfo12.mAscender = ASCENDER_12;
1693
1694   TextStyle style10;
1695   style10.SetFontPointSize( PointSize( 10.f ) );
1696   TextStyle style12;
1697   style12.SetFontPointSize( PointSize( 0.f ) ); // point size is set to zero because is a default point size.
1698
1699   layoutInfo12.mStyledText.mStyle = style12;
1700   layoutInfo10.mStyledText.mStyle = style10;
1701
1702   // Words
1703
1704   TextViewProcessor::WordLayoutInfo wordLayout1, wordLayout2, wordLayout3, wordLayout4;
1705
1706   // Hello
1707   wordLayout1.mSize = Size( 3.f * WIDTH_12 + 2.f * WIDTH_10, HEIGHT_12 );
1708   wordLayout1.mAscender = ASCENDER_12;
1709   wordLayout1.mType = TextViewProcessor::NoSeparator;
1710
1711   layoutInfo12.mStyledText.mText = Text( "H" );
1712   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // H
1713   layoutInfo12.mStyledText.mText = Text( "e" );
1714   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // e
1715   layoutInfo12.mStyledText.mText = Text( "l" );
1716   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // l
1717   layoutInfo10.mStyledText.mText = Text( "l" );
1718   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo10 ); // l
1719   layoutInfo10.mStyledText.mText = Text( "o" );
1720   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo10 ); // o
1721
1722   // (white space)
1723   wordLayout2.mSize = Size( WIDTH_10, HEIGHT_10 );
1724   wordLayout2.mAscender = ASCENDER_10;
1725   wordLayout2.mType = TextViewProcessor::WordSeparator;
1726   layoutInfo10.mStyledText.mText = Text( " " );
1727   wordLayout2.mCharactersLayoutInfo.push_back( layoutInfo10 ); // (white space)
1728
1729   // world!
1730   wordLayout3.mSize = Size( 2.f * WIDTH_10 + 4.f * WIDTH_12, HEIGHT_12 );
1731   wordLayout3.mAscender = ASCENDER_12;
1732   wordLayout3.mType = TextViewProcessor::NoSeparator;
1733   layoutInfo10.mStyledText.mText = Text( "w" );
1734   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo10 ); // w
1735   layoutInfo10.mStyledText.mText = Text( "o" );
1736   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo10 ); // o
1737   layoutInfo12.mStyledText.mText = Text( "r" );
1738   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // r
1739   layoutInfo12.mStyledText.mText = Text( "l" );
1740   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // l
1741   layoutInfo12.mStyledText.mText = Text( "d" );
1742   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // d
1743   layoutInfo12.mStyledText.mText = Text( "!" );
1744   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // !
1745
1746   // (new line character)
1747   wordLayout4.mSize = Size( 0.f, HEIGHT_12 );
1748   wordLayout4.mAscender = ASCENDER_12;
1749   wordLayout4.mType = TextViewProcessor::LineSeparator;
1750   layoutInfo12.mStyledText.mText = Text( "\n" );
1751   layoutInfo12.mSize.width = 0.f;
1752   wordLayout4.mCharactersLayoutInfo.push_back( layoutInfo12 ); // (new line char)
1753
1754   // Groups
1755
1756   TextViewProcessor::WordGroupLayoutInfo groupLayout1, groupLayout2;
1757
1758   groupLayout1.mSize = Size( 5.f * WIDTH_10 + 7.f * WIDTH_12, HEIGHT_12 );
1759   groupLayout1.mAscender = ASCENDER_12;
1760   groupLayout1.mDirection = TextViewProcessor::LTR;
1761   groupLayout1.mNumberOfCharacters = 13;
1762   groupLayout1.mWordsLayoutInfo.push_back( wordLayout1 );
1763   groupLayout1.mWordsLayoutInfo.push_back( wordLayout2 );
1764   groupLayout1.mWordsLayoutInfo.push_back( wordLayout3 );
1765   groupLayout1.mWordsLayoutInfo.push_back( wordLayout4 );
1766
1767   groupLayout2.mSize = Size( 0.f, HEIGHT_12 );
1768   groupLayout2.mAscender = ASCENDER_12;
1769   groupLayout2.mDirection = TextViewProcessor::LTR;
1770   groupLayout2.mNumberOfCharacters = 1;
1771   groupLayout2.mWordsLayoutInfo.push_back( wordLayout4 );
1772
1773   // Lines
1774
1775   TextViewProcessor::LineLayoutInfo lineLayout1, lineLayout2, lineLayout3;
1776
1777   lineLayout1.mSize = Size( 5.f * WIDTH_10 + 7.f * WIDTH_12, HEIGHT_12 );
1778   lineLayout1.mAscender = ASCENDER_12;
1779   lineLayout1.mNumberOfCharacters = 13;
1780   lineLayout1.mWordGroupsLayoutInfo.push_back( groupLayout1 );
1781
1782   lineLayout2.mSize = Size( 0.f, HEIGHT_12 );
1783   lineLayout2.mAscender = ASCENDER_12;
1784   lineLayout2.mNumberOfCharacters = 1;
1785   lineLayout2.mWordGroupsLayoutInfo.push_back( groupLayout2 );
1786
1787   lineLayout3.mSize = Size( 0.f, HEIGHT_12 );
1788
1789   // Text (layout)
1790   TextViewProcessor::TextLayoutInfo textLayout;
1791
1792   textLayout.mWholeTextSize = Size( 5.f * WIDTH_10 + 7.f * WIDTH_12, 3.f * HEIGHT_12 );
1793   textLayout.mMaxWordWidth = 2.f * WIDTH_10 + 4.f * WIDTH_12;
1794   textLayout.mNumberOfCharacters = 14;
1795   textLayout.mLinesLayoutInfo.push_back( lineLayout1 );
1796   textLayout.mLinesLayoutInfo.push_back( lineLayout2 );
1797   textLayout.mLinesLayoutInfo.push_back( lineLayout3 );
1798
1799   if(!TestEqual( textLayout, textLayoutInfo ))
1800   {
1801     std::cout << "Layout fails" << std::endl;
1802     Print(textLayout); std::cout << std::endl;
1803     Print(textLayoutInfo); std::cout << std::endl;
1804   }
1805
1806   DALI_TEST_CHECK( TestEqual( textLayout, textLayoutInfo ) );
1807 }
1808
1809 static void UtcDaliTextViewSplitWord()
1810 {
1811   ToolkitTestApplication application;
1812
1813   tet_infoline("UtcDaliTextViewSplitWord : ");
1814
1815   struct SplitWordTest splitWordTests[] =
1816   {
1817     {
1818       std::string( "Split word, position 0." ),
1819       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1820       0,
1821       std::string( "" ),
1822       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1823     },
1824     {
1825       std::string( "Split word, position 8." ),
1826       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1827       8,
1828       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1829       std::string( "" ),
1830     },
1831     {
1832       std::string( "Split word, position 2." ),
1833       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1834       2,
1835       std::string( "<font size='10'>He</font>" ),
1836       std::string( "<font size='12'>ll</font><font size='10'>oooo</font>" ),
1837     },
1838     {
1839       std::string( "Split word, position 3." ),
1840       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1841       3,
1842       std::string( "<font size='10'>He</font><font size='12'>l</font>" ),
1843       std::string( "<font size='12'>l</font><font size='10'>oooo</font>" ),
1844     },
1845     {
1846       std::string( "Split word, position 4." ),
1847       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1848       4,
1849       std::string( "<font size='10'>He</font><font size='12'>ll</font>" ),
1850       std::string( "<font size='10'>oooo</font>" ),
1851     },
1852   };
1853   const std::size_t numberOfTests( 5 );
1854
1855   for( std::size_t index = 0; index < numberOfTests; ++index )
1856   {
1857     const SplitWordTest& test = splitWordTests[index];
1858
1859     if( !TestSplitWord( test.description, test.input, test.position, test.firstResult, test.lastResult, TEST_LOCATION ) )
1860     {
1861       tet_result( TET_FAIL );
1862     }
1863   }
1864
1865   tet_result( TET_PASS );
1866 }
1867
1868 static void UtcDaliTextViewUpdateTextInfo()
1869 {
1870   ToolkitTestApplication application;
1871
1872   tet_infoline("UtcDaliTextViewUpdateTextInfo : ");
1873
1874   struct UpdateTextInfoTest updateTextInfoTest[] =
1875   {
1876     // Remove operations
1877
1878     {
1879       std::string( "Remove from new line character to first character next line." ),
1880       Remove,
1881       std::string("Hello world\nhello world."),
1882       11,
1883       2,
1884       std::string(""),
1885       0.f,
1886       std::string("Hello worldello world."),
1887     },
1888     {
1889       std::string( "Replace style from new line character to first character next line." ),
1890       Replace,
1891       std::string("Hello world\nhello world."),
1892       11,
1893       2,
1894       std::string("<b>\nh</b>"),
1895       0.f,
1896       std::string("Hello world<b>\nh</b>ello world."),
1897     },
1898     {
1899       std::string( "Remove from the beginning to the middle of last word." ),
1900       Remove,
1901       std::string("Hello world, hello world."),
1902       0,
1903       22,
1904       std::string(), // Not used.
1905       0.f,
1906       std::string("ld."),
1907     },
1908     {
1909       std::string( "Remove from the beginning to the middle of the text." ),
1910       Remove,
1911       std::string("Hello world hello world."),
1912       0,
1913       12,
1914       std::string(), // Not used.
1915       0.f,
1916       std::string("hello world."),
1917     },
1918     // Remove within the same word:
1919     // * within the same group of characters.
1920     {
1921       std::string( "Remove within the same word, within the same group of characters" ),
1922       Remove,
1923       std::string("Hello <font size='30'>world\nhello</font> world"),
1924       7,
1925       3,
1926       std::string(), // Not used.
1927       0.f,
1928       std::string( "Hello <font size='30'>wd\nhello</font> world" )
1929     },
1930     // * whole group of characters (merge adjacent group of characters)
1931     {
1932       std::string( "Remove within the same word, whole group of characters (merge adjacent group of characters)" ),
1933       Remove,
1934       std::string("Hello <font size='30'>w<font size='20'>orl</font>d\nhello</font> world"),
1935       7,
1936       3,
1937       std::string(), // Not used.
1938       0.f,
1939       std::string( "Hello <font size='30'>wd\nhello</font> world" )
1940     },
1941     // * whole group of characters (don't merge adjacent gtoup of characters)
1942     {
1943       std::string( "Remove within the same word, whole group of characters (don't merge adjacent gtoup of characters)" ),
1944       Remove,
1945       std::string("Hello <font size='30'>w</font>orl<font size='10'>d\nhello</font> world"),
1946       7,
1947       3,
1948       std::string(), // Not used.
1949       0.f,
1950       std::string( "Hello <font size='30'>w</font><font size='10'>d\nhello</font> world" )
1951     },
1952     // * Remove whole word (merge words)
1953     {
1954       std::string( "Remove within the same word, whole word (merge words)" ),
1955       Remove,
1956       std::string("Hello <font size='30'>w</font>orl<font size='10'>d\nhello</font> world"),
1957       5,
1958       1,
1959       std::string(), // Not used.
1960       0.f,
1961       std::string( "Hello<font size='30'>w</font>orl<font size='10'>d\nhello</font> world" )
1962     },
1963     // * Remove whole word (don't merge words)
1964     {
1965       std::string( "Remove within the same word, whole word (don't merge words)" ),
1966       Remove,
1967       std::string("Hello <font size='30'>w</font>orl<font size='10'>d\nhello</font> world"),
1968       6,
1969       5,
1970       std::string(), // Not used.
1971       0.f,
1972       std::string( "Hello <font size='10'>\nhello</font> world" )
1973     },
1974     // * Remove whole word (merge lines)
1975     {
1976       std::string( "Remove within the same word, whole word (merge lines)" ),
1977       Remove,
1978       std::string("Hello <font size='30'>w</font>orl<font size='10'>d\nhello</font> world"),
1979       11,
1980       1,
1981       std::string(), // Not used.
1982       0.f,
1983       std::string( "Hello <font size='30'>w</font>orl<font size='10'>dhello</font> world" )
1984     },
1985     // * Remove whole group of words
1986     /* TODO check this when RTL text is working
1987     {
1988       std::string( "Remove within the same line, whole group of words (merge groups)" ),
1989       Remove,
1990       std::string("Hello world, שלום עולם, hello world"),
1991       10,
1992       15,
1993       std::string(), // Not used.
1994       0.f,
1995       std::string( "Hello worlello world" )
1996     },
1997     */
1998     // * Remove whole line
1999     {
2000       std::string( "Remove whole line" ),
2001       Remove,
2002       std::string("Hello world, hello world\n"
2003                   "Hello world, hello world\n"
2004                   "Hello world, hello world\n"
2005                   "Hello world, hello world\n"),
2006       25,
2007       25,
2008       std::string(), // Not used.
2009       0.f,
2010       std::string("Hello world, hello world\n"
2011                   "Hello world, hello world\n"
2012                   "Hello world, hello world\n"),
2013     },
2014     {
2015       std::string( "Remove whole line" ),
2016       Remove,
2017       std::string("Hello world, hello world\n"
2018                   "H"),
2019       25,
2020       1,
2021       std::string(), // Not used.
2022       0.f,
2023       std::string("Hello world, hello world\n"),
2024     },
2025
2026
2027     // Insert operations
2028     {
2029       std::string( "insert some text" ),
2030       Insert,
2031       std::string("inpuext"),
2032       4,
2033       0,             // Not used
2034       std::string( "t t" ),
2035       0.f,
2036       std::string( "input text" )
2037     },
2038     {
2039       std::string( "Insert text at the end" ),
2040       Insert,
2041       std::string("touch "),
2042       6,
2043       0,
2044       std::string("me\nhello"),
2045       0.f,
2046       std::string("touch me\nhello")
2047     },
2048
2049     // Replace operations.
2050     {
2051       std::string( "Replace style from the beginning to some point in the middle of the text." ),
2052       Replace,
2053       std::string( "Hello <font color='green'>world</font>" ),
2054       0,
2055       7,
2056       std::string( "<font color='red'>Hello w</font>" ),
2057       0.f,
2058       std::string( "<font color='red'>Hello w</font><font color='green'>orld</font>" )
2059     },
2060     {
2061       std::string( "Replace style from the middle of the text to the end." ),
2062       Replace,
2063       std::string( "Touch me\nhello" ),
2064       6,
2065       8,
2066       std::string( "<b>me\nhello</b>" ),
2067       0.f,
2068       std::string( "Touch <b>me\nhello</b>" )
2069     },
2070     {
2071       std::string( "Remove characters from text. Previous next test:Replace style from the middle of the text 1." ),
2072       Remove,
2073       std::string( "Touch me\nhello\nworld" ),
2074       6,
2075       8,
2076       std::string( "" ),
2077       0.f,
2078       std::string( "Touch \nworld" )
2079     },
2080     {
2081       std::string( "Insert styled text in the middle of a text. Previous: Replace style from the middle of the text 1." ),
2082       Insert,
2083       std::string( "Touch \nworld" ),
2084       6,
2085       0,
2086       std::string( "<b>me\nhello</b>" ),
2087       0.f,
2088       std::string( "Touch <b>me\nhello</b>\nworld" )
2089     },
2090     {
2091       std::string( "Replace style from the middle of the text 1." ),
2092       Replace,
2093       std::string( "Touch me\nhello\nworld" ),
2094       6,
2095       8,
2096       std::string( "<b>me\nhello</b>" ),
2097       0.f,
2098       std::string( "Touch <b>me\nhello</b>\nworld" )
2099     },
2100     {
2101       std::string( "Remove characters from text. Previous next test:Replace style from the middle of the text 2." ),
2102       Remove,
2103       std::string( "Touch me\nhello\nworld" ),
2104       6,
2105       9,
2106       std::string( "" ),
2107       0.f,
2108       std::string( "Touch world" )
2109     },
2110     {
2111       std::string( "Replace style from the middle of the text 2." ),
2112       Replace,
2113       std::string( "Touch me\nhello\nworld" ),
2114       6,
2115       9,
2116       std::string( "<b>me\nhello\n</b>" ),
2117       0.f,
2118       std::string( "Touch <b>me\nhello\n</b>world" )
2119     },
2120   };
2121   const std::size_t numberOfTests( 21 );
2122
2123   for( std::size_t index = 0; index < numberOfTests; ++index )
2124   {
2125     const UpdateTextInfoTest& test = updateTextInfoTest[index];
2126
2127     if( !TestUpdateTextInfo( test.description, test.operation, test.input, test.position, test.numberOfCharacters, test.inputText, test.lineHeightOffset, test.result, TEST_LOCATION ) )
2128     {
2129       tet_result( TET_FAIL );
2130     }
2131   }
2132
2133   tet_result( TET_PASS );
2134 }
2135
2136 static void UtcDaliTextViewSplitWordGroup()
2137 {
2138   ToolkitTestApplication application;
2139
2140   tet_infoline("UtcDaliTextViewSplitWordGroup : ");
2141
2142   struct SplitWordGroupTest splitWordGroupTests[] =
2143   {
2144     {
2145       std::string( "Split word group, wordPosition 0, position 0." ),
2146       std::string( "<u><font size='10'>He<font size='12'>ll</font>oooo wooorld</font></u>" ),
2147       0,
2148       0,
2149       std::string( "" ),
2150       std::string( "<u><font size='10'>He<font size='12'>ll</font>oooo wooorld</font></u>" ),
2151     },
2152     {
2153       std::string( "Split word group, wordPosition 2, position 8." ),
2154       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font>" ),
2155       2,
2156       7,
2157       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font>" ),
2158       std::string( "" ),
2159     },
2160     {
2161       std::string( "Split word group, wordPosition 0, position 2." ),
2162       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font>" ),
2163       0,
2164       2,
2165       std::string( "<font size='10'>He</font>" ),
2166       std::string( "<font size='12'>ll</font><font size='10'>oooo wooorld</font>" ),
2167     },
2168     {
2169       std::string( "Split word group, wordPosition 0, position 3." ),
2170       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font>" ),
2171       0,
2172       3,
2173       std::string( "<font size='10'>He</font><font size='12'>l</font>" ),
2174       std::string( "<font size='12'>l</font><font size='10'>oooo wooorld</font>" ),
2175     },
2176     {
2177       std::string( "Split word group, wordPosition 0, position 4." ),
2178       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font>" ),
2179       0,
2180       4,
2181       std::string( "<font size='10'>He</font><font size='12'>ll</font>" ),
2182       std::string( "<font size='10'>oooo wooorld</font>" ),
2183     },
2184     {
2185       std::string( "Split word group, wordPosition 1, position 0." ),
2186       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font>" ),
2187       1,
2188       0,
2189       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
2190       std::string( "<font size='10'> wooorld</font>" ),
2191     },
2192   };
2193   const std::size_t numberOfTests( 6 );
2194
2195   for( std::size_t index = 0; index < numberOfTests; ++index )
2196   {
2197     const SplitWordGroupTest& test = splitWordGroupTests[index];
2198
2199     if( !TestSplitWordGroup( test.description, test.input, test.wordPosition, test.position, test.firstResult, test.lastResult, TEST_LOCATION ) )
2200     {
2201       tet_result( TET_FAIL );
2202     }
2203   }
2204
2205   tet_result( TET_PASS );
2206 }
2207
2208 static void UtcDaliTextViewSplitLine()
2209 {
2210   ToolkitTestApplication application;
2211
2212   tet_infoline("UtcDaliTextViewSplitLine : ");
2213
2214   struct SplitLineTest splitLineTests[] =
2215   {
2216     {
2217       std::string( "Split line, groupPosition 0, wordPosition 0, position 0." ),
2218       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2219       0,
2220       0,
2221       0,
2222       3.f,
2223       std::string( "" ),
2224       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2225     },
2226     {
2227       std::string( "Split line, groupPosition 2, wordPosition 2, position 4." ),
2228       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2229       2,
2230       2,
2231       4,
2232       0.f,
2233       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2234       std::string( "" ),
2235     },
2236     /* TODO check when RTL is working.
2237     {
2238       std::string( "Split line, groupPosition 1, wordPosition 2, position 0." ),
2239       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2240       1,
2241       2,
2242       0,
2243       0.f,
2244       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום" ),
2245       std::string( " עולם text text" ),
2246     },
2247     {
2248       std::string( "Split line, groupPosition 1, wordPosition 0, position 0." ),
2249       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2250       1,
2251       0,
2252       0,
2253       0.f,
2254       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> " ),
2255       std::string( "שלום עולם text text" ),
2256     },
2257     */
2258     {
2259       std::string( "Split line, groupPosition 2, wordPosition 0, position 0." ),
2260       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2261       2,
2262       0,
2263       0,
2264       6.f,
2265       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם " ),
2266       std::string( "text text" ),
2267     },
2268   };
2269   const std::size_t numberOfTests( 3 );
2270
2271   for( std::size_t index = 0; index < numberOfTests; ++index )
2272   {
2273     const SplitLineTest& test = splitLineTests[index];
2274
2275     if( !TestSplitLine( test.description, test.input, test.groupPosition, test.wordPosition, test.position, test.lineHeightOffset, test.firstResult, test.lastResult, TEST_LOCATION ) )
2276     {
2277       tet_result( TET_FAIL );
2278     }
2279   }
2280
2281   tet_result( TET_PASS );
2282 }
2283
2284 static void UtcDaliTextViewMergeWord01()
2285 {
2286   ToolkitTestApplication application;
2287
2288   tet_infoline("UtcDaliTextViewMergeWord01 : ");
2289
2290   struct MergeWordsTest mergeWordsTests[] =
2291   {
2292     {
2293       std::string( "Merge words with same style." ),
2294       std::string( "Hel" ),
2295       std::string( "lo" ),
2296       std::string( "Hello" ),
2297     },
2298     {
2299       std::string( "Merge words with different styles." ),
2300       std::string( "<font size='10>Hel</font>" ),
2301       std::string( "<font size='20'>lo</font>" ),
2302       std::string( "<font size='10'>Hel</font><font size='20'>lo</font>" )
2303     },
2304   };
2305   const std::size_t numberOfTests( 2 );
2306
2307   for( std::size_t index = 0; index < numberOfTests; ++index )
2308   {
2309     const MergeWordsTest& test = mergeWordsTests[index];
2310
2311     if( !TestMergeWords( test.description, test.inputFirst, test.inputLast, test.result, TEST_LOCATION ) )
2312     {
2313       tet_result( TET_FAIL );
2314     }
2315   }
2316
2317   tet_result( TET_PASS );
2318 }
2319
2320 static void UtcDaliTextViewMergeWord02()
2321 {
2322   // Negative test.
2323   // It test white spaces and new line characters can't be merged to other words.
2324
2325   ToolkitTestApplication application;
2326
2327   tet_infoline("UtcDaliTextViewMergeWord02 : ");
2328
2329   // Generate three words
2330
2331   Toolkit::Internal::TextView::RelayoutData relayoutData01;
2332   Toolkit::Internal::TextView::RelayoutData relayoutData02;
2333   Toolkit::Internal::TextView::RelayoutData relayoutData03;
2334   TextViewProcessor::TextLayoutInfo& textLayoutInfo01( relayoutData01.mTextLayoutInfo );
2335   TextViewProcessor::TextLayoutInfo& textLayoutInfo02( relayoutData02.mTextLayoutInfo );
2336   TextViewProcessor::TextLayoutInfo& textLayoutInfo03( relayoutData03.mTextLayoutInfo );
2337
2338   std::string text01( " " );
2339   std::string text02( "\n" );
2340   std::string text03( "a" );
2341   MarkupProcessor::StyledTextArray styledText01;
2342   MarkupProcessor::StyledTextArray styledText02;
2343   MarkupProcessor::StyledTextArray styledText03;
2344   MarkupProcessor::GetStyledTextArray( text01, styledText01 );
2345   MarkupProcessor::GetStyledTextArray( text02, styledText02 );
2346   MarkupProcessor::GetStyledTextArray( text03, styledText03 );
2347
2348   TextViewProcessor::CreateTextInfo( styledText01,
2349                                      DEFAULT_LAYOUT_PARAMETERS,
2350                                      relayoutData01 );
2351
2352   TextViewProcessor::WordLayoutInfo wordLayoutInfo01;
2353
2354   wordLayoutInfo01 = *( *( *textLayoutInfo01.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
2355
2356   TextViewProcessor::CreateTextInfo( styledText02,
2357                                      DEFAULT_LAYOUT_PARAMETERS,
2358                                      relayoutData02 );
2359
2360   TextViewProcessor::WordLayoutInfo wordLayoutInfo02;
2361
2362   wordLayoutInfo02 = *( *( *textLayoutInfo02.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
2363
2364   TextViewProcessor::CreateTextInfo( styledText03,
2365                                      DEFAULT_LAYOUT_PARAMETERS,
2366                                      relayoutData03 );
2367
2368   TextViewProcessor::WordLayoutInfo wordLayoutInfo03;
2369
2370   wordLayoutInfo03 = *( *( *textLayoutInfo03.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
2371
2372   // Test MergeWord() asserts if white spaces or new line chars are merged.
2373   bool assert1 = false;
2374   bool assert2 = false;
2375   bool assert3 = false;
2376   bool assert4 = false;
2377   bool assert5 = false;
2378   bool assert6 = false;
2379
2380   try
2381   {
2382     MergeWord( wordLayoutInfo01,
2383                wordLayoutInfo02 );
2384   }
2385   catch( Dali::DaliException& e )
2386   {
2387     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2388     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new line characters can't be merged with other words.\"", TEST_LOCATION );
2389     assert1 = true;
2390   }
2391   try
2392   {
2393     MergeWord( wordLayoutInfo01,
2394                wordLayoutInfo03 );
2395   }
2396   catch( Dali::DaliException& e )
2397   {
2398     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2399     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new line characters can't be merged with other words.\"", TEST_LOCATION );
2400     assert2 = true;
2401   }
2402   try
2403   {
2404     MergeWord( wordLayoutInfo02,
2405                wordLayoutInfo01 );
2406   }
2407   catch( Dali::DaliException& e )
2408   {
2409     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2410     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new line characters can't be merged with other words.\"", TEST_LOCATION );
2411     assert3 = true;
2412   }
2413   try
2414   {
2415     MergeWord( wordLayoutInfo02,
2416                wordLayoutInfo03 );
2417   }
2418   catch( Dali::DaliException& e )
2419   {
2420     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2421     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new line characters can't be merged with other words.\"", TEST_LOCATION );
2422     assert4 = true;
2423   }
2424   try
2425   {
2426     MergeWord( wordLayoutInfo03,
2427                wordLayoutInfo01 );
2428   }
2429   catch( Dali::DaliException& e )
2430   {
2431     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2432     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new line characters can't be merged with other words.\"", TEST_LOCATION );
2433     assert5 = true;
2434   }
2435   try
2436   {
2437     MergeWord( wordLayoutInfo03,
2438                wordLayoutInfo02 );
2439   }
2440   catch( Dali::DaliException& e )
2441   {
2442     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2443     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new line characters can't be merged with other words.\"", TEST_LOCATION );
2444     assert6 = true;
2445   }
2446
2447   if( assert1 && assert2 && assert3 && assert4 && assert5 && assert6 )
2448   {
2449     tet_result( TET_PASS );
2450   }
2451   else
2452   {
2453     tet_result( TET_FAIL );
2454   }
2455 }
2456
2457 static void UtcDaliTextViewMergeGroup01()
2458 {
2459   ToolkitTestApplication application;
2460
2461   tet_infoline("UtcDaliTextViewMergeGroup01 : ");
2462
2463   struct MergeWordGroupsTest mergeWordGroupssTests[] =
2464   {
2465     {
2466       std::string( "Merge a void first group." ),
2467       std::string( "" ),
2468       std::string( "Hello world" ),
2469       std::string( "Hello world" ),
2470     },
2471     {
2472       std::string( "Merge a void last group." ),
2473       std::string( "Hello world" ),
2474       std::string( "" ),
2475       std::string( "Hello world" ),
2476     },
2477     {
2478       std::string( "Merge groups and merge last and first words." ),
2479       std::string( "Hello wor" ),
2480       std::string( "ld, hello world" ),
2481       std::string( "Hello world, hello world" ),
2482     },
2483     {
2484       std::string( "Merge groups and don't merge last and first words." ),
2485       std::string( "Hello world, " ),
2486       std::string( "hello world" ),
2487       std::string( "Hello world, hello world" )
2488     },
2489   };
2490   const std::size_t numberOfTests( 4 );
2491
2492   for( std::size_t index = 0; index < numberOfTests; ++index )
2493   {
2494     const MergeWordGroupsTest& test = mergeWordGroupssTests[index];
2495
2496     if( !TestMergeGroupsOfWords( test.description, test.inputFirst, test.inputLast, test.result, TEST_LOCATION ) )
2497     {
2498       tet_result( TET_FAIL );
2499     }
2500   }
2501
2502   tet_result(TET_PASS);
2503 }
2504
2505 static void UtcDaliTextViewMergeGroup02()
2506 {
2507   ToolkitTestApplication application;
2508
2509   tet_infoline("UtcDaliTextViewMergeGroup02 : ");
2510
2511   Toolkit::Internal::TextView::RelayoutData relayoutData01;
2512   Toolkit::Internal::TextView::RelayoutData relayoutData02;
2513   Toolkit::Internal::TextView::RelayoutData relayoutData03;
2514   TextViewProcessor::TextLayoutInfo& textLayoutInfo01( relayoutData01.mTextLayoutInfo );
2515   TextViewProcessor::TextLayoutInfo& textLayoutInfo02( relayoutData02.mTextLayoutInfo );
2516   TextViewProcessor::TextLayoutInfo& textLayoutInfo03( relayoutData03.mTextLayoutInfo );
2517
2518   std::string text01( "Hello \n" );
2519   std::string text02( "world" );
2520   std::string text03( "السلام عليكم" );
2521   MarkupProcessor::StyledTextArray styledText01;
2522   MarkupProcessor::StyledTextArray styledText02;
2523   MarkupProcessor::StyledTextArray styledText03;
2524   MarkupProcessor::GetStyledTextArray( text01, styledText01 );
2525   MarkupProcessor::GetStyledTextArray( text02, styledText02 );
2526   MarkupProcessor::GetStyledTextArray( text03, styledText03 );
2527
2528   TextViewProcessor::CreateTextInfo( styledText01,
2529                                      DEFAULT_LAYOUT_PARAMETERS,
2530                                      relayoutData01 );
2531
2532   TextViewProcessor::WordGroupLayoutInfo wordGroupLayoutInfo01;
2533
2534   wordGroupLayoutInfo01 = *( *textLayoutInfo01.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
2535
2536   TextViewProcessor::CreateTextInfo( styledText02,
2537                                      DEFAULT_LAYOUT_PARAMETERS,
2538                                      relayoutData02 );
2539
2540   TextViewProcessor::WordGroupLayoutInfo wordGroupLayoutInfo02;
2541
2542   wordGroupLayoutInfo02 = *( *textLayoutInfo02.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
2543
2544   TextViewProcessor::CreateTextInfo( styledText03,
2545                                      DEFAULT_LAYOUT_PARAMETERS,
2546                                      relayoutData03 );
2547
2548   TextViewProcessor::WordGroupLayoutInfo wordGroupLayoutInfo03;
2549
2550   wordGroupLayoutInfo03 = *( *textLayoutInfo03.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
2551
2552   bool assert1 = false;
2553   bool assert2 = false;
2554
2555   try
2556   {
2557     MergeWordGroup( wordGroupLayoutInfo01,
2558                     wordGroupLayoutInfo02 );
2559   }
2560   catch( Dali::DaliException& e )
2561   {
2562     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2563     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWordGroup(). ERROR: A group of words can't be merged to another group which finishes with a new line character.\"", TEST_LOCATION );
2564     assert1 = true;
2565   }
2566
2567   try
2568   {
2569     MergeWordGroup( wordGroupLayoutInfo03,
2570                     wordGroupLayoutInfo02 );
2571   }
2572   catch( Dali::DaliException& e )
2573   {
2574     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2575     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWordGroup(). ERROR: groups with different direction can't be merged.\"", TEST_LOCATION );
2576     assert2 = true;
2577   }
2578
2579   if( assert1 && assert2 )
2580   {
2581     tet_result( TET_PASS );
2582   }
2583   else
2584   {
2585     tet_result( TET_FAIL );
2586   }
2587 }
2588
2589 static void UtcDaliTextViewMergeLine01()
2590 {
2591   ToolkitTestApplication application;
2592
2593   tet_infoline("UtcDaliTextViewMergeLine01 : ");
2594
2595   struct MergeLinesTest mergeLinesTests[] =
2596   {
2597     {
2598       std::string( "Merge a void first line." ),
2599       std::string( "" ),
2600       std::string( "Hello world, this is a whole line" ),
2601       2.f,
2602       std::string( "Hello world, this is a whole line" )
2603     },
2604     {
2605       std::string( "Merge a void last line." ),
2606       std::string( "Hello world, this is a whole line" ),
2607       std::string( "" ),
2608       0.f,
2609       std::string( "Hello world, this is a whole line" )
2610     },
2611     /* TODO: check when RTL text is working.
2612     {
2613       std::string( "Merge lines and merge last and first groups" ),
2614       std::string( "Hello world, שלום" ),
2615       std::string( " עולם, hello world." ),
2616       6.f,
2617       std::string( "Hello world, שלום עולם, hello world." )
2618     },
2619     {
2620       std::string( "Merge lines and don't merge last and first words." ),
2621       std::string( "Hello world, " ),
2622       std::string( "שלום עולם, hello world." ),
2623       3.f,
2624       std::string( "Hello world, שלום עולם, hello world." )
2625     },
2626     */
2627     {
2628       std::string( "Merge lines. Don't merge words" ),
2629       std::string( "Hello world," ),
2630       std::string( " this is a whole line" ),
2631       0.f,
2632       std::string( "Hello world, this is a whole line" )
2633     },
2634     {
2635       std::string( "Merge lines. Merge words" ),
2636       std::string( "Hello world, th" ),
2637       std::string( "is is a whole line" ),
2638       0.f,
2639       std::string( "Hello world, this is a whole line" )
2640     },
2641   };
2642   const std::size_t numberOfTests( 4 );
2643
2644   for( std::size_t index = 0; index < numberOfTests; ++index )
2645   {
2646     const MergeLinesTest& test = mergeLinesTests[index];
2647
2648     if( !TestMergeLines( test.description, test.inputFirst, test.inputLast, test.lineHeightOffset, test.result, TEST_LOCATION ) )
2649     {
2650       tet_result( TET_FAIL );
2651     }
2652   }
2653
2654   tet_result( TET_PASS );
2655 }
2656
2657 static void UtcDaliTextViewMergeLine02()
2658 {
2659   ToolkitTestApplication application;
2660
2661   tet_infoline("UtcDaliTextViewMergeLine02 : ");
2662
2663   Toolkit::Internal::TextView::RelayoutData relayoutData01;
2664   Toolkit::Internal::TextView::RelayoutData relayoutData02;
2665   TextViewProcessor::TextLayoutInfo& textLayoutInfo01( relayoutData01.mTextLayoutInfo );
2666   TextViewProcessor::TextLayoutInfo& textLayoutInfo02( relayoutData02.mTextLayoutInfo );
2667
2668   std::string text01( "Hello world\n" );
2669   std::string text02( "hello world" );
2670   MarkupProcessor::StyledTextArray styledText01;
2671   MarkupProcessor::StyledTextArray styledText02;
2672   MarkupProcessor::GetStyledTextArray( text01, styledText01 );
2673   MarkupProcessor::GetStyledTextArray( text02, styledText02 );
2674
2675   TextViewProcessor::CreateTextInfo( styledText01,
2676                                      DEFAULT_LAYOUT_PARAMETERS,
2677                                      relayoutData01 );
2678
2679   TextViewProcessor::LineLayoutInfo lineLayoutInfo01;
2680
2681   lineLayoutInfo01 = *textLayoutInfo01.mLinesLayoutInfo.begin();
2682
2683   TextViewProcessor::CreateTextInfo( styledText02,
2684                                      DEFAULT_LAYOUT_PARAMETERS,
2685                                      relayoutData02 );
2686
2687   TextViewProcessor::LineLayoutInfo lineLayoutInfo02;
2688
2689   lineLayoutInfo02 = *textLayoutInfo02.mLinesLayoutInfo.begin();
2690
2691   bool assert1 = false;
2692
2693   try
2694   {
2695     MergeLine( lineLayoutInfo01,
2696                lineLayoutInfo02 );
2697   }
2698   catch( Dali::DaliException& e )
2699   {
2700     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2701     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeLine(). ERROR: A line can't be merged to another line which finishes with a new line character.\"", TEST_LOCATION );
2702     assert1 = true;
2703   }
2704
2705   if( assert1 )
2706   {
2707     tet_result( TET_PASS );
2708   }
2709   else
2710   {
2711     tet_result( TET_FAIL );
2712   }
2713 }
2714
2715 void UtcDaliTextViewRemoveCharactersFromWord()
2716 {
2717   ToolkitTestApplication application;
2718
2719   tet_infoline("UtcDaliTextViewMergeWord02 : ");
2720
2721   struct RemoveCharactersFromWordTest removeCharactersFromWordTests[] =
2722   {
2723     {
2724       std::string( "Delete 0 characters." ),
2725       std::string( "Hello" ),
2726       3,
2727       0,
2728       std::string( "Hello" ),
2729     },
2730     {
2731       std::string( "Delete within the same group of characters. Starting from the beginning" ),
2732       std::string( "Hello" ),
2733       0,
2734       3,
2735       std::string( "lo" ),
2736     },
2737     {
2738       std::string( "Delete within the same group of characters. Somewhere in the middle" ),
2739       std::string( "Hello" ),
2740       2,
2741       2,
2742       std::string( "Heo" ),
2743     },
2744     {
2745       std::string( "Delete within the same group of characters. Starting somewhere in the middle to the end" ),
2746       std::string( "Hello" ),
2747       3,
2748       2,
2749       std::string( "Hel" ),
2750     },
2751     {
2752       std::string( "Delete within the same group of characters. Finish just before a new one." ),
2753       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2754       1,
2755       2,
2756       std::string( "<font size='10'>H</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2757     },
2758     {
2759       std::string( "Delete starting in one group of characters and finishing in a different one. No merge of groups." ),
2760       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2761       2,
2762       3,
2763       std::string( "<font size='10'>He</font><font size='20'>Wo</font><font size='30'>rld</font>" ),
2764     },
2765     {
2766       std::string( "Delete within the same group of characters. Starting just after a different one." ),
2767       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2768       7,
2769       2,
2770       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>d</font>" ),
2771     },
2772     {
2773       std::string( "Delete whole group of characters. No merge" ),
2774       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2775       3,
2776       4,
2777       std::string( "<font size='10'>Hel</font><font size='30'>rld</font>" ),
2778     },
2779     {
2780       std::string( "Delete whole group of characters and part of the adjacent ones. No merge" ),
2781       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2782       2,
2783       6,
2784       std::string( "<font size='10'>He</font><font size='30'>ld</font>" ),
2785     },
2786     {
2787       std::string( "Delete whole group of characters. Merge" ),
2788       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='10'>rld</font>" ),
2789       3,
2790       4,
2791       std::string( "<font size='10'>Helrld</font>" ),
2792     },
2793     {
2794       std::string( "Delete whole group of characters and part of the adjacent ones. Merge" ),
2795       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='10'>rld</font>" ),
2796       2,
2797       6,
2798       std::string( "<font size='10'>Held</font>" ),
2799     },
2800   };
2801   const std::size_t numberOfTests( 11 );
2802
2803   for( std::size_t index = 0; index < numberOfTests; ++index )
2804   {
2805     const RemoveCharactersFromWordTest& test = removeCharactersFromWordTests[index];
2806
2807     if( !TestRemoveCharactersFromWord( test.description, test.input, test.position, test.numberOfCharacters, test.result, TEST_LOCATION ) )
2808     {
2809       tet_result( TET_FAIL );
2810     }
2811   }
2812
2813   tet_result( TET_PASS );
2814 }
2815
2816 static void UtcDaliTextViewRemoveWordsFromGroup()
2817 {
2818   // Note: Currently RemoveWordsFromWordGroup() function is only used to remove a number of words from the beginning, or
2819   //       from a given index to the end. RemoveWordsFromWordGroup() doesn't merge words (if a white space is removed) so
2820   //       tehere isn't any TET case to cover these cases. To be done if needed.
2821
2822   ToolkitTestApplication application;
2823
2824   tet_infoline("UtcDaliTextViewRemoveWordsFromGroup : ");
2825   struct RemoveWordsFromGroupTest removeWordsFromGroupTests[] =
2826   {
2827     {
2828       std::string( "Delete 0 words." ),
2829       std::string( "Hello world, hello world" ),
2830       3,
2831       0,
2832       std::string( "Hello world, hello world" ),
2833     },
2834     {
2835       std::string( "Delete some words in the middle. Don't merge words" ),
2836       std::string( "<font size='10'>Hel</font><font size='20'>lo wo</font><font size='30'>rld, hello world</font>" ),
2837       1,
2838       4,
2839       std::string( "<font size='10'>Hel</font><font size='20'>lo</font><font size='30'> world</font>" ),
2840     },
2841     {
2842       std::string( "Delete words up to the end" ),
2843       std::string( "<font size='10'>Hel</font><font size='20'>lo wo</font><font size='30'>rld, hello world</font>" ),
2844       5,
2845       2,
2846       std::string( "<font size='10'>Hel</font><font size='20'>lo wo</font><font size='30'>rld, hello</font>" ),
2847     },
2848     {
2849       std::string( "Delete words from the beginning." ),
2850       std::string( "Hello world, hello world" ),
2851       0,
2852       3,
2853       std::string( " hello world" ),
2854     },
2855   };
2856   const std::size_t numberOfTests( 4 );
2857
2858   for( std::size_t index = 0; index < numberOfTests; ++index )
2859   {
2860     const RemoveWordsFromGroupTest& test = removeWordsFromGroupTests[index];
2861
2862     if( !TestRemoveWordsFromGroup( test.description, test.input, test.wordIndex, test.numberOfWords, test.result, TEST_LOCATION ) )
2863     {
2864       tet_result( TET_FAIL );
2865     }
2866   }
2867
2868   tet_result( TET_PASS );
2869 }
2870
2871 static void UtcDaliTextViewRemoveGroupsFromLine()
2872 {
2873   // Note: Currently RemoveWordGroupsFromLine() function is only used to remove a number of group of words from the beginning, or
2874   //       from a given index to the end. RemoveWordGroupsFromLine() doesn't merge groups of words (if a whole group of words is removed) so
2875   //       tehere isn't any TET case to cover these cases. To be done if needed.
2876
2877   ToolkitTestApplication application;
2878
2879   tet_infoline("UtcDaliTextViewRemoveGroupsFromLine : ");
2880   struct RemoveGroupsFromLineTest removeGroupsFromLineTests[] =
2881   {
2882     {
2883       std::string( "Delete 0 groups of words." ),
2884       std::string( "Hello hello, שלום עולם hello hello" ),
2885       1,
2886       0,
2887       2.f,
2888       std::string( "Hello hello, שלום עולם hello hello" ),
2889     },
2890     {
2891       std::string( "Delete from the middle to the end." ),
2892       std::string( "Hello hello, שלום עולם hello hello" ),
2893       1,
2894       2,
2895       0.f,
2896       std::string( "Hello hello, " ),
2897     },
2898     {
2899       std::string( "Delete from the beginning to the middle." ),
2900       std::string( "Hello hello, שלום עולם hello hello" ),
2901       0,
2902       2,
2903       6.f,
2904       std::string( "hello hello" ),
2905     },
2906   };
2907   const std::size_t numberOfTests( 3 );
2908
2909   for( std::size_t index = 0; index < numberOfTests; ++index )
2910   {
2911     const RemoveGroupsFromLineTest& test = removeGroupsFromLineTests[index];
2912
2913     if( !TestRemoveGroupsFromLine( test.description, test.input, test.groupIndex, test.numberOfGroups, test.lineHeightOffset, test.result, TEST_LOCATION ) )
2914     {
2915       tet_result( TET_FAIL );
2916     }
2917   }
2918
2919   tet_result( TET_PASS );
2920 }