83d39a827219a0adc30a05ab2ed4a63bb3f15b66
[platform/core/uifw/dali-toolkit.git] / automated-tests / TET / 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, true );
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, true );
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, true );
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, true );
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, true );
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, true );
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, true );
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                                                                                     true ),
806                                      relayoutData );
807
808   // Get the input line
809   TextViewProcessor::LineLayoutInfo inputLineLayout;
810
811   if( !inputLayout.mLinesLayoutInfo.empty() )
812   {
813     inputLineLayout = *inputLayout.mLinesLayoutInfo.begin();
814   }
815
816   // Create layout info for the first part of the result (after split the line)
817
818   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
819   TextViewProcessor::TextLayoutInfo& firstResultLayout( firstRelayoutData.mTextLayoutInfo );
820
821   MarkupProcessor::StyledTextArray firstResultStyledText;
822   MarkupProcessor::GetStyledTextArray( firstResult, firstResultStyledText, true );
823
824   TextViewProcessor::CreateTextInfo( firstResultStyledText,
825                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
826                                                                                     Toolkit::TextView::Original,
827                                                                                     Toolkit::TextView::Original,
828                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
829                                                                                     Toolkit::TextView::Center,
830                                                                                     PointSize( lineHeightOffset ),
831                                                                                     std::string( "..." ),
832                                                                                     true ),
833                                      firstRelayoutData );
834
835   // Get the first result line
836   TextViewProcessor::LineLayoutInfo firstResultLineLayout;
837
838   if( !firstResultLayout.mLinesLayoutInfo.empty() )
839   {
840     firstResultLineLayout = *firstResultLayout.mLinesLayoutInfo.begin();
841   }
842
843   // Create layout info for the last part of the result (after split the line)
844
845   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
846   TextViewProcessor::TextLayoutInfo& lastResultLayout( lastRelayoutData.mTextLayoutInfo );
847
848   MarkupProcessor::StyledTextArray lastResultStyledText;
849   MarkupProcessor::GetStyledTextArray( lastResult, lastResultStyledText, true );
850
851   TextViewProcessor::CreateTextInfo( lastResultStyledText,
852                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
853                                                                                     Toolkit::TextView::Original,
854                                                                                     Toolkit::TextView::Original,
855                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
856                                                                                     Toolkit::TextView::Center,
857                                                                                     PointSize( lineHeightOffset ),
858                                                                                     std::string( "..."),
859                                                                                     true ),
860                                      lastRelayoutData );
861
862   // Get the last result line
863   TextViewProcessor::LineLayoutInfo lastResultLineLayout;
864
865   if( !lastResultLayout.mLinesLayoutInfo.empty() )
866   {
867     lastResultLineLayout = *lastResultLayout.mLinesLayoutInfo.begin();
868   }
869
870   // Split the line.
871
872   TextViewProcessor::LineLayoutInfo lastLineLayoutInfo;
873
874   TextViewProcessor::TextInfoIndices indices( 0, groupPosition, wordPosition, position );
875   SplitLine( indices,
876              PointSize( lineHeightOffset ),
877              inputLineLayout,
878              lastLineLayoutInfo );
879
880   // Test results
881   if( !TestEqual( inputLineLayout, firstResultLineLayout ) )
882   {
883     tet_printf( "Fail. different layout info. %s", location );
884     return false;
885   }
886
887   if( !TestEqual( lastLineLayoutInfo, lastResultLineLayout ) )
888   {
889     tet_printf( "Fail. different layout info. %s", location );
890     return false;
891   }
892
893   return true;
894 }
895
896 /**
897  * Merges the \e inputFirst word and the \e inputLast word, and checks the results with \e result.
898  *
899  * If the test fails it prints a short description and the line where this function was called.
900  *
901  * @param description Short description of the experiment. i.e. "Merge two words with same style".
902  * @param inputFirst The first part of the word.
903  * @param inputLast The last part of the word.
904  * @param result The merged word.
905  * @param location Where this function has been called.
906  *
907  * @return \e true if the experiment is successful. Otherwise returns \e false.
908  */
909 bool TestMergeWords( const std::string& description, const std::string& inputFirst, const std::string& inputLast, const std::string& result, const char* location )
910 {
911   tet_printf( "%s", description.c_str() );
912
913   // Create layout info for the inputFirst word.
914   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
915   TextViewProcessor::TextLayoutInfo& inputFirstLayout( firstRelayoutData.mTextLayoutInfo );
916
917   MarkupProcessor::StyledTextArray inputFirstStyledText;
918   MarkupProcessor::GetStyledTextArray( inputFirst, inputFirstStyledText, true );
919
920   TextViewProcessor::CreateTextInfo( inputFirstStyledText,
921                                      DEFAULT_LAYOUT_PARAMETERS,
922                                      firstRelayoutData );
923
924   // Get the input word
925   TextViewProcessor::WordLayoutInfo inputFirstWordLayout;
926
927   if( !inputFirstLayout.mLinesLayoutInfo.empty() )
928   {
929     const TextViewProcessor::LineLayoutInfo& line( *inputFirstLayout.mLinesLayoutInfo.begin() );
930     if( !line.mWordGroupsLayoutInfo.empty() )
931     {
932       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
933       if( !group.mWordsLayoutInfo.empty() )
934       {
935         inputFirstWordLayout = *( *( *inputFirstLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
936       }
937     }
938   }
939
940   // Create layout info for the inputLast word.
941   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
942   TextViewProcessor::TextLayoutInfo& inputLastLayout( lastRelayoutData.mTextLayoutInfo );
943
944   MarkupProcessor::StyledTextArray inputLastStyledText;
945   MarkupProcessor::GetStyledTextArray( inputLast, inputLastStyledText, true );
946
947   TextViewProcessor::CreateTextInfo( inputLastStyledText,
948                                      DEFAULT_LAYOUT_PARAMETERS,
949                                      lastRelayoutData );
950
951   // Get the input word
952   TextViewProcessor::WordLayoutInfo inputLastWordLayout;
953
954   if( !inputLastLayout.mLinesLayoutInfo.empty() )
955   {
956     const TextViewProcessor::LineLayoutInfo& line( *inputLastLayout.mLinesLayoutInfo.begin() );
957     if( !line.mWordGroupsLayoutInfo.empty() )
958     {
959       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
960       if( !group.mWordsLayoutInfo.empty() )
961       {
962         inputLastWordLayout = *( *( *inputLastLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
963       }
964     }
965   }
966
967   // Create layout info for the result word.
968   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
969   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
970
971   MarkupProcessor::StyledTextArray resultStyledText;
972   MarkupProcessor::GetStyledTextArray( result, resultStyledText, true );
973
974   TextViewProcessor::CreateTextInfo( resultStyledText,
975                                      DEFAULT_LAYOUT_PARAMETERS,
976                                      resultRelayoutData );
977
978   // Get the result word
979   TextViewProcessor::WordLayoutInfo resultWordLayout;
980
981   if( !resultLayout.mLinesLayoutInfo.empty() )
982   {
983     const TextViewProcessor::LineLayoutInfo& line( *resultLayout.mLinesLayoutInfo.begin() );
984     if( !line.mWordGroupsLayoutInfo.empty() )
985     {
986       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
987       if( !group.mWordsLayoutInfo.empty() )
988       {
989         resultWordLayout = *( *( *resultLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
990       }
991     }
992   }
993
994   MergeWord( inputFirstWordLayout,
995              inputLastWordLayout );
996
997   if( !TestEqual( inputFirstWordLayout, resultWordLayout ) )
998   {
999     tet_printf( "Fail. different layout info. %s", location );
1000     return false;
1001   }
1002
1003   return true;
1004 }
1005
1006 /**
1007  * Merges the \e inputFirst group of words and the \e inputLast group of words, and checks the results with \e result.
1008  *
1009  * If the test fails it prints a short description and the line where this function was called.
1010  *
1011  * @param description Short description of the experiment.
1012  * @param inputFirst The first part of the group of words.
1013  * @param inputLast The last part of the group of words.
1014  * @param result The merged group of word.
1015  * @param location Where this function has been called.
1016  *
1017  * @return \e true if the experiment is successful. Otherwise returns \e false.
1018  */
1019 bool TestMergeGroupsOfWords( const std::string& description, const std::string& inputFirst, const std::string& inputLast, const std::string& result, const char* location )
1020 {
1021   tet_printf( "%s", description.c_str() );
1022
1023   // Create layout info for the inputFirst group of word.
1024   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
1025   TextViewProcessor::TextLayoutInfo& inputFirstLayout( firstRelayoutData.mTextLayoutInfo );
1026
1027   MarkupProcessor::StyledTextArray inputFirstStyledText;
1028   MarkupProcessor::GetStyledTextArray( inputFirst, inputFirstStyledText, true );
1029
1030   TextViewProcessor::CreateTextInfo( inputFirstStyledText,
1031                                      DEFAULT_LAYOUT_PARAMETERS,
1032                                      firstRelayoutData );
1033
1034   // Get the input group of words.
1035   TextViewProcessor::WordGroupLayoutInfo inputFirstWordGroupLayout;
1036
1037   if( !inputFirstLayout.mLinesLayoutInfo.empty() )
1038   {
1039     const TextViewProcessor::LineLayoutInfo& line( *inputFirstLayout.mLinesLayoutInfo.begin() );
1040     if( !line.mWordGroupsLayoutInfo.empty() )
1041     {
1042       inputFirstWordGroupLayout = *( *inputFirstLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
1043     }
1044   }
1045
1046   // Create layout info for the inputLast group of words.
1047   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
1048   TextViewProcessor::TextLayoutInfo& inputLastLayout( lastRelayoutData.mTextLayoutInfo );
1049
1050   MarkupProcessor::StyledTextArray inputLastStyledText;
1051   MarkupProcessor::GetStyledTextArray( inputLast, inputLastStyledText, true );
1052
1053   TextViewProcessor::CreateTextInfo( inputLastStyledText,
1054                                      DEFAULT_LAYOUT_PARAMETERS,
1055                                      lastRelayoutData );
1056
1057   // Get the input group of words
1058   TextViewProcessor::WordGroupLayoutInfo inputLastWordGroupLayout;
1059
1060   if( !inputLastLayout.mLinesLayoutInfo.empty() )
1061   {
1062     const TextViewProcessor::LineLayoutInfo& line( *inputLastLayout.mLinesLayoutInfo.begin() );
1063     if( !line.mWordGroupsLayoutInfo.empty() )
1064     {
1065       inputLastWordGroupLayout = *( *inputLastLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
1066     }
1067   }
1068
1069   // Create layout info for the result group of words.
1070   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1071   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1072
1073   MarkupProcessor::StyledTextArray resultStyledText;
1074   MarkupProcessor::GetStyledTextArray( result, resultStyledText, true );
1075
1076   TextViewProcessor::CreateTextInfo( resultStyledText,
1077                                      DEFAULT_LAYOUT_PARAMETERS,
1078                                      resultRelayoutData );
1079
1080   // Get the result word
1081   TextViewProcessor::WordGroupLayoutInfo resultWordGroupLayout;
1082
1083   if( !resultLayout.mLinesLayoutInfo.empty() )
1084   {
1085     const TextViewProcessor::LineLayoutInfo& line( *resultLayout.mLinesLayoutInfo.begin() );
1086     if( !line.mWordGroupsLayoutInfo.empty() )
1087     {
1088       resultWordGroupLayout = *( *resultLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
1089     }
1090   }
1091
1092   MergeWordGroup( inputFirstWordGroupLayout,
1093                   inputLastWordGroupLayout );
1094
1095   if( !TestEqual( inputFirstWordGroupLayout, resultWordGroupLayout ) )
1096   {
1097     tet_printf( "Fail. different layout info. %s", location );
1098     return false;
1099   }
1100
1101   return true;
1102 }
1103
1104 /**
1105  * Merges the \e inputFirst line and the \e inputLast line, and checks the results with \e result.
1106  *
1107  * If the test fails it prints a short description and the line where this function was called.
1108  *
1109  * @param description Short description of the experiment.
1110  * @param inputFirst The first part of the line.
1111  * @param inputLast The last part of the line.
1112  * @param lineHeightOffset Offset between lines.
1113  * @param result The merged line.
1114  * @param location Where this function has been called.
1115  *
1116  * @return \e true if the experiment is successful. Otherwise returns \e false.
1117  */
1118 bool TestMergeLines( const std::string& description, const std::string& inputFirst, const std::string& inputLast, const float lineHeightOffset, const std::string& result, const char* location )
1119 {
1120   tet_printf( "%s", description.c_str() );
1121
1122   // Create layout info for the inputFirst line.
1123   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
1124   TextViewProcessor::TextLayoutInfo& inputFirstLayout( firstRelayoutData.mTextLayoutInfo );
1125
1126   MarkupProcessor::StyledTextArray inputFirstStyledText;
1127   MarkupProcessor::GetStyledTextArray( inputFirst, inputFirstStyledText, true );
1128
1129   TextViewProcessor::CreateTextInfo( inputFirstStyledText,
1130                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1131                                                                                     Toolkit::TextView::Original,
1132                                                                                     Toolkit::TextView::Original,
1133                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1134                                                                                     Toolkit::TextView::Center,
1135                                                                                     PointSize( lineHeightOffset ),
1136                                                                                     std::string( "..." ),
1137                                                                                     true ),
1138                                      firstRelayoutData );
1139
1140   // Get the input word
1141   TextViewProcessor::LineLayoutInfo inputFirstLineLayout;
1142
1143   if( !inputFirstLayout.mLinesLayoutInfo.empty() )
1144   {
1145     inputFirstLineLayout = *inputFirstLayout.mLinesLayoutInfo.begin();
1146   }
1147
1148   // Create layout info for the inputLast line.
1149   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
1150   TextViewProcessor::TextLayoutInfo& inputLastLayout( lastRelayoutData.mTextLayoutInfo );
1151
1152   MarkupProcessor::StyledTextArray inputLastStyledText;
1153   MarkupProcessor::GetStyledTextArray( inputLast, inputLastStyledText, true );
1154
1155   TextViewProcessor::CreateTextInfo( inputLastStyledText,
1156                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1157                                                                                     Toolkit::TextView::Original,
1158                                                                                     Toolkit::TextView::Original,
1159                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1160                                                                                     Toolkit::TextView::Center,
1161                                                                                     PointSize( lineHeightOffset ),
1162                                                                                     std::string( "..." ),
1163                                                                                     true ),
1164                                      lastRelayoutData );
1165
1166   // Get the input word
1167   TextViewProcessor::LineLayoutInfo inputLastLineLayout;
1168
1169   if( !inputLastLayout.mLinesLayoutInfo.empty() )
1170   {
1171     inputLastLineLayout = *inputLastLayout.mLinesLayoutInfo.begin();
1172   }
1173
1174   // Create layout info for the result word.
1175   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1176   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1177
1178   MarkupProcessor::StyledTextArray resultStyledText;
1179   MarkupProcessor::GetStyledTextArray( result, resultStyledText, true );
1180
1181   TextViewProcessor::CreateTextInfo( resultStyledText,
1182                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1183                                                                                     Toolkit::TextView::Original,
1184                                                                                     Toolkit::TextView::Original,
1185                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1186                                                                                     Toolkit::TextView::Center,
1187                                                                                     PointSize( lineHeightOffset ),
1188                                                                                     std::string( "..." ),
1189                                                                                     true ),
1190                                      resultRelayoutData );
1191
1192   // Get the result word
1193   TextViewProcessor::LineLayoutInfo resultLineLayout;
1194
1195   if( !resultLayout.mLinesLayoutInfo.empty() )
1196   {
1197     resultLineLayout = *resultLayout.mLinesLayoutInfo.begin();
1198   }
1199
1200   MergeLine( inputFirstLineLayout,
1201              inputLastLineLayout );
1202
1203   if( !TestEqual( inputFirstLineLayout, resultLineLayout ) )
1204   {
1205     tet_printf( "Fail. different layout info. %s", location );
1206     return false;
1207   }
1208
1209   return true;
1210 }
1211
1212 /**
1213  * Removes from the \e input word the \e numberOfCharacters characters starting from the given \e position and checks the results with \e result.
1214  *
1215  * If the test fails it prints a short description and the line where this function was called.
1216  *
1217  * @param description Short description of the experiment. i.e. "Remove a whole group of characters. Merge".
1218  * @param input The input word.
1219  * @param position Where to start to remove characters
1220  * @param numberOfCharacters The number of characters to remove.
1221  * @param result The word without the removed characters.
1222  * @param location Where this function has been called.
1223  *
1224  * @return \e true if the experiment is successful. Otherwise returns \e false.
1225  */
1226 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 )
1227 {
1228   tet_printf( "%s", description.c_str() );
1229
1230   // Create layout info for the input word.
1231   Toolkit::Internal::TextView::RelayoutData relayoutData;
1232   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
1233
1234   MarkupProcessor::StyledTextArray inputStyledText;
1235   MarkupProcessor::GetStyledTextArray( input, inputStyledText, true );
1236
1237   TextViewProcessor::CreateTextInfo( inputStyledText,
1238                                      DEFAULT_LAYOUT_PARAMETERS,
1239                                      relayoutData );
1240
1241   // Get the input word
1242   TextViewProcessor::WordLayoutInfo inputWordLayout;
1243
1244   if( !inputLayout.mLinesLayoutInfo.empty() )
1245   {
1246     const TextViewProcessor::LineLayoutInfo& line( *inputLayout.mLinesLayoutInfo.begin() );
1247     if( !line.mWordGroupsLayoutInfo.empty() )
1248     {
1249       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
1250       if( !group.mWordsLayoutInfo.empty() )
1251       {
1252         inputWordLayout = *( *( *inputLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
1253       }
1254     }
1255   }
1256
1257   // Create layout info for the result word.
1258   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1259   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1260
1261   MarkupProcessor::StyledTextArray resultStyledText;
1262   MarkupProcessor::GetStyledTextArray( result, resultStyledText, true );
1263
1264   TextViewProcessor::CreateTextInfo( resultStyledText,
1265                                      DEFAULT_LAYOUT_PARAMETERS,
1266                                      resultRelayoutData );
1267
1268   // Get the result word
1269   TextViewProcessor::WordLayoutInfo resultWordLayout;
1270
1271   if( !resultLayout.mLinesLayoutInfo.empty() )
1272   {
1273     const TextViewProcessor::LineLayoutInfo& line( *resultLayout.mLinesLayoutInfo.begin() );
1274     if( !line.mWordGroupsLayoutInfo.empty() )
1275     {
1276       const TextViewProcessor::WordGroupLayoutInfo& group( *line.mWordGroupsLayoutInfo.begin() );
1277       if( !group.mWordsLayoutInfo.empty() )
1278       {
1279         resultWordLayout = *( *( *resultLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
1280       }
1281     }
1282   }
1283
1284   RemoveCharactersFromWord( position,
1285                             numberOfCharacters,
1286                             inputWordLayout );
1287
1288   if( !TestEqual( inputWordLayout, resultWordLayout ) )
1289   {
1290     tet_printf( "Fail. different layout info. %s", location );
1291     return false;
1292   }
1293
1294   return true;
1295 }
1296
1297 /**
1298  * 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.
1299  *
1300  * If the test fails it prints a short description and the line where this function was called.
1301  *
1302  * @param description Short description of the experiment.
1303  * @param input The input group of words.
1304  * @param wordIndex Where to start to remove words.
1305  * @param numberOfWords The number of words to remove.
1306  * @param result The group of words without the removed words.
1307  * @param location Where this function has been called.
1308  *
1309  * @return \e true if the experiment is successful. Otherwise returns \e false.
1310  */
1311 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 )
1312 {
1313   tet_printf( "%s", description.c_str() );
1314
1315   // Create layout info for the input group of words.
1316   Toolkit::Internal::TextView::RelayoutData relayoutData;
1317   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
1318
1319   MarkupProcessor::StyledTextArray inputStyledText;
1320   MarkupProcessor::GetStyledTextArray( input, inputStyledText, true );
1321
1322   TextViewProcessor::CreateTextInfo( inputStyledText,
1323                                      DEFAULT_LAYOUT_PARAMETERS,
1324                                      relayoutData );
1325
1326   // Get the input group of words
1327   TextViewProcessor::WordGroupLayoutInfo inputWordGroupLayout;
1328
1329   if( !inputLayout.mLinesLayoutInfo.empty() )
1330   {
1331     const TextViewProcessor::LineLayoutInfo& line( *inputLayout.mLinesLayoutInfo.begin() );
1332     if( !line.mWordGroupsLayoutInfo.empty() )
1333     {
1334       inputWordGroupLayout = *( *inputLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
1335     }
1336   }
1337
1338   // Create layout info for the result group of words.
1339   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1340   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1341
1342   MarkupProcessor::StyledTextArray resultStyledText;
1343   MarkupProcessor::GetStyledTextArray( result, resultStyledText, true );
1344
1345   TextViewProcessor::CreateTextInfo( resultStyledText,
1346                                      DEFAULT_LAYOUT_PARAMETERS,
1347                                      resultRelayoutData );
1348
1349   // Get the result group of words.
1350   TextViewProcessor::WordGroupLayoutInfo resultWordGroupLayout;
1351
1352   if( !resultLayout.mLinesLayoutInfo.empty() )
1353   {
1354     const TextViewProcessor::LineLayoutInfo& line( *resultLayout.mLinesLayoutInfo.begin() );
1355     if( !line.mWordGroupsLayoutInfo.empty() )
1356     {
1357       resultWordGroupLayout = *( *resultLayout.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
1358     }
1359   }
1360
1361   RemoveWordsFromWordGroup( wordIndex,
1362                             numberOfWords,
1363                             inputWordGroupLayout );
1364
1365   if( !TestEqual( inputWordGroupLayout, resultWordGroupLayout ) )
1366   {
1367     tet_printf( "Fail. different layout info. %s", location );
1368     return false;
1369   }
1370
1371   return true;
1372 }
1373
1374
1375 /**
1376  * 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.
1377  *
1378  * If the test fails it prints a short description and the line where this function was called.
1379  *
1380  * @param description Short description of the experiment.
1381  * @param input The input line.
1382  * @param groupIndex Where to start to remove groups of words
1383  * @param numberOfGroups The number of groups of words to remove.
1384  * @param lineHeightOffset Offset between lines.
1385  * @param result The line without the removed groups of words.
1386  * @param location Where this function has been called.
1387  *
1388  * @return \e true if the experiment is successful. Otherwise returns \e false.
1389  */
1390 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 )
1391 {
1392   tet_printf( "%s", description.c_str() );
1393
1394   // Create layout info for the input line.
1395   Toolkit::Internal::TextView::RelayoutData relayoutData;
1396   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
1397
1398   MarkupProcessor::StyledTextArray inputStyledText;
1399   MarkupProcessor::GetStyledTextArray( input, inputStyledText, true );
1400
1401   TextViewProcessor::CreateTextInfo( inputStyledText,
1402                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1403                                                                                     Toolkit::TextView::Original,
1404                                                                                     Toolkit::TextView::Original,
1405                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1406                                                                                     Toolkit::TextView::Center,
1407                                                                                     PointSize( lineHeightOffset ),
1408                                                                                     std::string( "..." ),
1409                                                                                     true ),
1410                                      relayoutData );
1411
1412   // Get the input line
1413   TextViewProcessor::LineLayoutInfo inputLineLayout;
1414
1415   if( !inputLayout.mLinesLayoutInfo.empty() )
1416   {
1417     inputLineLayout = *inputLayout.mLinesLayoutInfo.begin();
1418   }
1419
1420   // Create layout info for the result line.
1421   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1422   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1423
1424   MarkupProcessor::StyledTextArray resultStyledText;
1425   MarkupProcessor::GetStyledTextArray( result, resultStyledText, true );
1426
1427   TextViewProcessor::CreateTextInfo( resultStyledText,
1428                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1429                                                                                     Toolkit::TextView::Original,
1430                                                                                     Toolkit::TextView::Original,
1431                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1432                                                                                     Toolkit::TextView::Center,
1433                                                                                     PointSize( lineHeightOffset ),
1434                                                                                     std::string( "..." ),
1435                                                                                     true ),
1436                                      resultRelayoutData );
1437
1438   // Get the result line
1439   TextViewProcessor::LineLayoutInfo resultLineLayout;
1440
1441   if( !resultLayout.mLinesLayoutInfo.empty() )
1442   {
1443     resultLineLayout = *resultLayout.mLinesLayoutInfo.begin();
1444   }
1445
1446   RemoveWordGroupsFromLine( groupIndex,
1447                             numberOfGroups,
1448                             PointSize( lineHeightOffset ),
1449                             inputLineLayout );
1450
1451   if( !TestEqual( inputLineLayout, resultLineLayout ) )
1452   {
1453     tet_printf( "Fail. different layout info. %s", location );
1454     return false;
1455   }
1456
1457   return true;
1458 }
1459
1460 /**
1461  * Tests inserts, removes and updates operation in the given \e input text and checks with the given \e result.
1462  *
1463  * If the test fails it prints a short description and the line where this function was called.
1464  *
1465  * @param description Short description of the experiment.
1466  * @param operation Type of update operation (insert, remove, replace)
1467  * @param input The input text.
1468  * @param position Where to insert, remove or replace text.
1469  * @param numberOfCharacters Number of characters to remove or replace.
1470  * @param inputText Inserted or updated text.
1471  * @param lineHeightOffset Offset between lines.
1472  * @param result Expected result.
1473  * @param location Where this function has been called.
1474  *
1475  * @return \e true if the experiment is successful. Otherwise returns \e false.
1476  */
1477 bool TestUpdateTextInfo( const std::string& description,
1478                          const UpdateTextInfoOperation operation,
1479                          const std::string& input,
1480                          const std::size_t position,
1481                          const std::size_t numberOfCharacters,
1482                          const std::string& inputText,
1483                          const float lineHeightOffset,
1484                          const std::string& result,
1485                          const char* location )
1486 {
1487   tet_printf( "%s", description.c_str() );
1488
1489   // Create layout info for the input.
1490   Toolkit::Internal::TextView::RelayoutData relayoutData;
1491   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
1492
1493   MarkupProcessor::StyledTextArray inputStyledText;
1494   MarkupProcessor::GetStyledTextArray( input, inputStyledText, true );
1495
1496   TextViewProcessor::CreateTextInfo( inputStyledText,
1497                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1498                                                                                     Toolkit::TextView::Original,
1499                                                                                     Toolkit::TextView::Original,
1500                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1501                                                                                     Toolkit::TextView::Center,
1502                                                                                     PointSize( lineHeightOffset ),
1503                                                                                     std::string( "..." ),
1504                                                                                     true ),
1505                                      relayoutData );
1506
1507   // Create layout info for the result.
1508   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1509   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1510
1511   MarkupProcessor::StyledTextArray resultStyledText;
1512   MarkupProcessor::GetStyledTextArray( result, resultStyledText, true );
1513
1514   TextViewProcessor::CreateTextInfo( resultStyledText,
1515                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1516                                                                                     Toolkit::TextView::Original,
1517                                                                                     Toolkit::TextView::Original,
1518                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1519                                                                                     Toolkit::TextView::Center,
1520                                                                                     PointSize( lineHeightOffset ),
1521                                                                                     std::string( "..." ),
1522                                                                                     true ),
1523                                      resultRelayoutData );
1524
1525   // Choose operation and call appropiate UpdateTextInfo() method.
1526   const Toolkit::Internal::TextView::LayoutParameters layoutParameters( Toolkit::TextView::SplitByNewLineChar,
1527                                                                         Toolkit::TextView::Original,
1528                                                                         Toolkit::TextView::Original,
1529                                                                         static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1530                                                                         Toolkit::TextView::Center,
1531                                                                         PointSize( lineHeightOffset ),
1532                                                                         std::string( "..." ),
1533                                                                         true );
1534
1535   switch( operation )
1536   {
1537     case Insert:
1538     {
1539       MarkupProcessor::StyledTextArray inputStyledText;
1540       MarkupProcessor::GetStyledTextArray( inputText, inputStyledText, true );
1541
1542       TextViewProcessor::UpdateTextInfo( position,
1543                                          inputStyledText,
1544                                          layoutParameters,
1545                                          relayoutData );
1546       break;
1547     }
1548     case Remove:
1549     {
1550       TextViewProcessor::UpdateTextInfo( position,
1551                                          numberOfCharacters,
1552                                          layoutParameters,
1553                                          relayoutData,
1554                                          TextViewProcessor::CLEAR_TEXT );
1555       break;
1556     }
1557     case Replace:
1558     {
1559       MarkupProcessor::StyledTextArray inputStyledText;
1560       MarkupProcessor::GetStyledTextArray( inputText, inputStyledText, true );
1561
1562       TextViewProcessor::UpdateTextInfo( position,
1563                                          numberOfCharacters,
1564                                          inputStyledText,
1565                                          layoutParameters,
1566                                          relayoutData );
1567       break;
1568     }
1569     default:
1570     {
1571       tet_printf( "TestUpdateTextInfo: unknown update operation. %s", location );
1572       return false;
1573     }
1574   }
1575
1576   if( !TestEqual( inputLayout, resultLayout ) )
1577   {
1578     tet_printf( "Fail. different layout info. %s", location );
1579
1580     std::cout << "          result : "; Print( inputLayout );
1581     std::cout << " expected result : "; Print( resultLayout );
1582     return false;
1583   }
1584
1585   return true;
1586 }
1587
1588 } // namespace
1589
1590 static void Startup();
1591 static void Cleanup();
1592
1593 extern "C" {
1594   void (*tet_startup)() = Startup;
1595   void (*tet_cleanup)() = Cleanup;
1596 }
1597
1598 enum {
1599   POSITIVE_TC_IDX = 0x01,
1600   NEGATIVE_TC_IDX,
1601 };
1602
1603 #define MAX_NUMBER_OF_TESTS 10000
1604 extern "C" {
1605   struct tet_testlist tet_testlist[MAX_NUMBER_OF_TESTS];
1606 }
1607
1608 // Add test functionality for all APIs in the class (Positive and Negative)
1609 TEST_FUNCTION( UtcDaliTextViewCreateTextInfo, POSITIVE_TC_IDX );                     // Tests data structures are built well.
1610 TEST_FUNCTION( UtcDaliTextViewUpdateTextInfo, POSITIVE_TC_IDX );                     // Tests update operations within a whole text (insert, remove, replace).
1611 TEST_FUNCTION( UtcDaliTextViewSplitWord, POSITIVE_TC_IDX );                          // Tests the split word operation.
1612 TEST_FUNCTION( UtcDaliTextViewSplitWordGroup, POSITIVE_TC_IDX );                     // Tests the split group of words operation.
1613 TEST_FUNCTION( UtcDaliTextViewSplitLine, POSITIVE_TC_IDX );                          // Tests the split line operation.
1614 TEST_FUNCTION( UtcDaliTextViewMergeWord01, POSITIVE_TC_IDX );                        // Tests the merge word operation.
1615 TEST_FUNCTION( UtcDaliTextViewMergeWord02, NEGATIVE_TC_IDX );                        // Tests invalid inputs in the merge word operation.
1616 TEST_FUNCTION( UtcDaliTextViewMergeGroup01, POSITIVE_TC_IDX );                       // Tests the merge group of words operation.
1617 TEST_FUNCTION( UtcDaliTextViewMergeGroup02, NEGATIVE_TC_IDX );                       // Tests invalid inputs in the merge group of words operation.
1618 TEST_FUNCTION( UtcDaliTextViewMergeLine01, POSITIVE_TC_IDX );                        // Tests the merge line operation.
1619 TEST_FUNCTION( UtcDaliTextViewMergeLine02, NEGATIVE_TC_IDX );                        // Tests invalid inputs in the merge line operation.
1620 TEST_FUNCTION( UtcDaliTextViewRemoveCharactersFromWord, POSITIVE_TC_IDX );           // Tests the remove characters from a word operation.
1621 TEST_FUNCTION( UtcDaliTextViewRemoveWordsFromGroup, POSITIVE_TC_IDX );               // Tests the remove words from a group of words operation.
1622 TEST_FUNCTION( UtcDaliTextViewRemoveGroupsFromLine, POSITIVE_TC_IDX );               // Tests the remove groups of words from a line operation.
1623
1624 // Called only once before first test is run.
1625 static void Startup()
1626 {
1627 }
1628
1629 // Called only once after last test is run
1630 static void Cleanup()
1631 {
1632 }
1633
1634 static void UtcDaliTextViewCreateTextInfo()
1635 {
1636   ToolkitTestApplication application;
1637
1638   tet_infoline("UtcDaliTextViewCreateTextInfo : ");
1639
1640   // Metrics for characters
1641
1642   // Font size = 10
1643   //     size : [9.48351, 9.48351]
1644   //  advance : 9.48351
1645   //  bearing : 8.53516
1646   // ascender : 8.53516
1647
1648   // Font size = 12
1649   //     size : [11.3802, 11.3802]
1650   //  advance : 11.3802
1651   //  bearing : 10.2422
1652   // ascender : 10.2422
1653
1654   // Font size = 14
1655   //     size : [13.2769, 13.2769]
1656   //  advance : 13.2769
1657   //  bearing : 11.9492
1658   // ascender : 11.9492
1659
1660   const float WIDTH_10( 9.48351f );
1661   const float HEIGHT_10( 9.48351f );
1662   const float ADVANCE_10( 9.48351f );
1663   const float BEARING_10( 8.53516f );
1664   const float ASCENDER_10( 8.53516f );
1665
1666   const float WIDTH_12( 11.3802f );
1667   const float HEIGHT_12( 11.3802f );
1668   const float ADVANCE_12( 11.3802f );
1669   const float BEARING_12( 10.2422f );
1670   const float ASCENDER_12( 10.2422f );
1671
1672
1673   // Generate a text.
1674   Toolkit::Internal::TextView::RelayoutData relayoutData;
1675   TextViewProcessor::TextLayoutInfo& textLayoutInfo( relayoutData.mTextLayoutInfo );
1676
1677   std::string text( "Hel<font size='10'>lo wo</font>rld!\n"
1678                     "\n" );
1679
1680   MarkupProcessor::StyledTextArray styledText;
1681   MarkupProcessor::GetStyledTextArray( text, styledText, true );
1682
1683   TextViewProcessor::CreateTextInfo( styledText,
1684                                      DEFAULT_LAYOUT_PARAMETERS,
1685                                      relayoutData );
1686
1687
1688   // Build the text info with metric values.
1689
1690   // Characters
1691
1692   TextViewProcessor::CharacterLayoutInfo layoutInfo10; // ( [lo wo])
1693   layoutInfo10.mHeight = HEIGHT_10;
1694   layoutInfo10.mAdvance = ADVANCE_10;
1695   layoutInfo10.mBearing = BEARING_10;
1696   layoutInfo10.mSize = Size( WIDTH_10, HEIGHT_10 );
1697   layoutInfo10.mAscender = ASCENDER_10;
1698   TextViewProcessor::CharacterLayoutInfo layoutInfo12; // ( [Hel], [rld!] and [CR])
1699   layoutInfo12.mHeight = HEIGHT_12;
1700   layoutInfo12.mAdvance = ADVANCE_12;
1701   layoutInfo12.mBearing = BEARING_12;
1702   layoutInfo12.mSize = Size( WIDTH_12, HEIGHT_12 );
1703   layoutInfo12.mAscender = ASCENDER_12;
1704
1705   TextStyle style10;
1706   style10.SetFontPointSize( PointSize( 10.f ) );
1707   TextStyle style12;
1708   style12.SetFontPointSize( PointSize( 0.f ) ); // point size is set to zero because is a default point size.
1709
1710   layoutInfo12.mStyledText.mStyle = style12;
1711   layoutInfo10.mStyledText.mStyle = style10;
1712
1713   // Words
1714
1715   TextViewProcessor::WordLayoutInfo wordLayout1, wordLayout2, wordLayout3, wordLayout4;
1716
1717   // Hello
1718   wordLayout1.mSize = Size( 3.f * WIDTH_12 + 2.f * WIDTH_10, HEIGHT_12 );
1719   wordLayout1.mAscender = ASCENDER_12;
1720   wordLayout1.mType = TextViewProcessor::NoSeparator;
1721
1722   layoutInfo12.mStyledText.mText = Text( "H" );
1723   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // H
1724   layoutInfo12.mStyledText.mText = Text( "e" );
1725   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // e
1726   layoutInfo12.mStyledText.mText = Text( "l" );
1727   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // l
1728   layoutInfo10.mStyledText.mText = Text( "l" );
1729   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo10 ); // l
1730   layoutInfo10.mStyledText.mText = Text( "o" );
1731   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo10 ); // o
1732
1733   // (white space)
1734   wordLayout2.mSize = Size( WIDTH_10, HEIGHT_10 );
1735   wordLayout2.mAscender = ASCENDER_10;
1736   wordLayout2.mType = TextViewProcessor::WordSeparator;
1737   layoutInfo10.mStyledText.mText = Text( " " );
1738   wordLayout2.mCharactersLayoutInfo.push_back( layoutInfo10 ); // (white space)
1739
1740   // world!
1741   wordLayout3.mSize = Size( 2.f * WIDTH_10 + 4.f * WIDTH_12, HEIGHT_12 );
1742   wordLayout3.mAscender = ASCENDER_12;
1743   wordLayout3.mType = TextViewProcessor::NoSeparator;
1744   layoutInfo10.mStyledText.mText = Text( "w" );
1745   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo10 ); // w
1746   layoutInfo10.mStyledText.mText = Text( "o" );
1747   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo10 ); // o
1748   layoutInfo12.mStyledText.mText = Text( "r" );
1749   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // r
1750   layoutInfo12.mStyledText.mText = Text( "l" );
1751   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // l
1752   layoutInfo12.mStyledText.mText = Text( "d" );
1753   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // d
1754   layoutInfo12.mStyledText.mText = Text( "!" );
1755   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // !
1756
1757   // (new line character)
1758   wordLayout4.mSize = Size( 0.f, HEIGHT_12 );
1759   wordLayout4.mAscender = ASCENDER_12;
1760   wordLayout4.mType = TextViewProcessor::LineSeparator;
1761   layoutInfo12.mStyledText.mText = Text( "\n" );
1762   layoutInfo12.mSize.width = 0.f;
1763   wordLayout4.mCharactersLayoutInfo.push_back( layoutInfo12 ); // (new line char)
1764
1765   // Groups
1766
1767   TextViewProcessor::WordGroupLayoutInfo groupLayout1, groupLayout2;
1768
1769   groupLayout1.mSize = Size( 5.f * WIDTH_10 + 7.f * WIDTH_12, HEIGHT_12 );
1770   groupLayout1.mAscender = ASCENDER_12;
1771   groupLayout1.mDirection = TextViewProcessor::LTR;
1772   groupLayout1.mNumberOfCharacters = 13;
1773   groupLayout1.mWordsLayoutInfo.push_back( wordLayout1 );
1774   groupLayout1.mWordsLayoutInfo.push_back( wordLayout2 );
1775   groupLayout1.mWordsLayoutInfo.push_back( wordLayout3 );
1776   groupLayout1.mWordsLayoutInfo.push_back( wordLayout4 );
1777
1778   groupLayout2.mSize = Size( 0.f, HEIGHT_12 );
1779   groupLayout2.mAscender = ASCENDER_12;
1780   groupLayout2.mDirection = TextViewProcessor::LTR;
1781   groupLayout2.mNumberOfCharacters = 1;
1782   groupLayout2.mWordsLayoutInfo.push_back( wordLayout4 );
1783
1784   // Lines
1785
1786   TextViewProcessor::LineLayoutInfo lineLayout1, lineLayout2, lineLayout3;
1787
1788   lineLayout1.mSize = Size( 5.f * WIDTH_10 + 7.f * WIDTH_12, HEIGHT_12 );
1789   lineLayout1.mAscender = ASCENDER_12;
1790   lineLayout1.mNumberOfCharacters = 13;
1791   lineLayout1.mWordGroupsLayoutInfo.push_back( groupLayout1 );
1792
1793   lineLayout2.mSize = Size( 0.f, HEIGHT_12 );
1794   lineLayout2.mAscender = ASCENDER_12;
1795   lineLayout2.mNumberOfCharacters = 1;
1796   lineLayout2.mWordGroupsLayoutInfo.push_back( groupLayout2 );
1797
1798   lineLayout3.mSize = Size( 0.f, HEIGHT_12 );
1799
1800   // Text (layout)
1801   TextViewProcessor::TextLayoutInfo textLayout;
1802
1803   textLayout.mWholeTextSize = Size( 5.f * WIDTH_10 + 7.f * WIDTH_12, 3.f * HEIGHT_12 );
1804   textLayout.mMaxWordWidth = 2.f * WIDTH_10 + 4.f * WIDTH_12;
1805   textLayout.mNumberOfCharacters = 14;
1806   textLayout.mLinesLayoutInfo.push_back( lineLayout1 );
1807   textLayout.mLinesLayoutInfo.push_back( lineLayout2 );
1808   textLayout.mLinesLayoutInfo.push_back( lineLayout3 );
1809
1810   if(!TestEqual( textLayout, textLayoutInfo ))
1811   {
1812     std::cout << "Layout fails" << std::endl;
1813     Print(textLayout); std::cout << std::endl;
1814     Print(textLayoutInfo); std::cout << std::endl;
1815   }
1816
1817   DALI_TEST_CHECK( TestEqual( textLayout, textLayoutInfo ) );
1818 }
1819
1820 static void UtcDaliTextViewSplitWord()
1821 {
1822   ToolkitTestApplication application;
1823
1824   tet_infoline("UtcDaliTextViewSplitWord : ");
1825
1826   struct SplitWordTest splitWordTests[] =
1827   {
1828     {
1829       std::string( "Split word, position 0." ),
1830       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1831       0,
1832       std::string( "" ),
1833       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1834     },
1835     {
1836       std::string( "Split word, position 8." ),
1837       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1838       8,
1839       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1840       std::string( "" ),
1841     },
1842     {
1843       std::string( "Split word, position 2." ),
1844       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1845       2,
1846       std::string( "<font size='10'>He</font>" ),
1847       std::string( "<font size='12'>ll</font><font size='10'>oooo</font>" ),
1848     },
1849     {
1850       std::string( "Split word, position 3." ),
1851       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1852       3,
1853       std::string( "<font size='10'>He</font><font size='12'>l</font>" ),
1854       std::string( "<font size='12'>l</font><font size='10'>oooo</font>" ),
1855     },
1856     {
1857       std::string( "Split word, position 4." ),
1858       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1859       4,
1860       std::string( "<font size='10'>He</font><font size='12'>ll</font>" ),
1861       std::string( "<font size='10'>oooo</font>" ),
1862     },
1863   };
1864   const std::size_t numberOfTests( 5 );
1865
1866   for( std::size_t index = 0; index < numberOfTests; ++index )
1867   {
1868     const SplitWordTest& test = splitWordTests[index];
1869
1870     if( !TestSplitWord( test.description, test.input, test.position, test.firstResult, test.lastResult, TEST_LOCATION ) )
1871     {
1872       tet_result( TET_FAIL );
1873     }
1874   }
1875
1876   tet_result( TET_PASS );
1877 }
1878
1879 static void UtcDaliTextViewUpdateTextInfo()
1880 {
1881   ToolkitTestApplication application;
1882
1883   tet_infoline("UtcDaliTextViewUpdateTextInfo : ");
1884
1885   struct UpdateTextInfoTest updateTextInfoTest[] =
1886   {
1887     // Remove operations
1888
1889     {
1890       std::string( "Remove from new line character to first character next line." ),
1891       Remove,
1892       std::string("Hello world\nhello world."),
1893       11,
1894       2,
1895       std::string(""),
1896       0.f,
1897       std::string("Hello worldello world."),
1898     },
1899     {
1900       std::string( "Replace style from new line character to first character next line." ),
1901       Replace,
1902       std::string("Hello world\nhello world."),
1903       11,
1904       2,
1905       std::string("<b>\nh</b>"),
1906       0.f,
1907       std::string("Hello world<b>\nh</b>ello world."),
1908     },
1909     {
1910       std::string( "Remove from the beginning to the middle of last word." ),
1911       Remove,
1912       std::string("Hello world, hello world."),
1913       0,
1914       22,
1915       std::string(), // Not used.
1916       0.f,
1917       std::string("ld."),
1918     },
1919     {
1920       std::string( "Remove from the beginning to the middle of the text." ),
1921       Remove,
1922       std::string("Hello world hello world."),
1923       0,
1924       12,
1925       std::string(), // Not used.
1926       0.f,
1927       std::string("hello world."),
1928     },
1929     // Remove within the same word:
1930     // * within the same group of characters.
1931     {
1932       std::string( "Remove within the same word, within the same group of characters" ),
1933       Remove,
1934       std::string("Hello <font size='30'>world\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 (merge adjacent group of characters)
1942     {
1943       std::string( "Remove within the same word, whole group of characters (merge adjacent group of characters)" ),
1944       Remove,
1945       std::string("Hello <font size='30'>w<font size='20'>orl</font>d\nhello</font> world"),
1946       7,
1947       3,
1948       std::string(), // Not used.
1949       0.f,
1950       std::string( "Hello <font size='30'>wd\nhello</font> world" )
1951     },
1952     // * whole group of characters (don't merge adjacent gtoup of characters)
1953     {
1954       std::string( "Remove within the same word, whole group of characters (don't merge adjacent gtoup of characters)" ),
1955       Remove,
1956       std::string("Hello <font size='30'>w</font>orl<font size='10'>d\nhello</font> world"),
1957       7,
1958       3,
1959       std::string(), // Not used.
1960       0.f,
1961       std::string( "Hello <font size='30'>w</font><font size='10'>d\nhello</font> world" )
1962     },
1963     // * Remove whole word (merge words)
1964     {
1965       std::string( "Remove within the same word, whole word (merge words)" ),
1966       Remove,
1967       std::string("Hello <font size='30'>w</font>orl<font size='10'>d\nhello</font> world"),
1968       5,
1969       1,
1970       std::string(), // Not used.
1971       0.f,
1972       std::string( "Hello<font size='30'>w</font>orl<font size='10'>d\nhello</font> world" )
1973     },
1974     // * Remove whole word (don't merge words)
1975     {
1976       std::string( "Remove within the same word, whole word (don't merge words)" ),
1977       Remove,
1978       std::string("Hello <font size='30'>w</font>orl<font size='10'>d\nhello</font> world"),
1979       6,
1980       5,
1981       std::string(), // Not used.
1982       0.f,
1983       std::string( "Hello <font size='10'>\nhello</font> world" )
1984     },
1985     // * Remove whole word (merge lines)
1986     {
1987       std::string( "Remove within the same word, whole word (merge lines)" ),
1988       Remove,
1989       std::string("Hello <font size='30'>w</font>orl<font size='10'>d\nhello</font> world"),
1990       11,
1991       1,
1992       std::string(), // Not used.
1993       0.f,
1994       std::string( "Hello <font size='30'>w</font>orl<font size='10'>dhello</font> world" )
1995     },
1996     // * Remove whole group of words
1997     /* TODO check this when RTL text is working
1998     {
1999       std::string( "Remove within the same line, whole group of words (merge groups)" ),
2000       Remove,
2001       std::string("Hello world, שלום עולם, hello world"),
2002       10,
2003       15,
2004       std::string(), // Not used.
2005       0.f,
2006       std::string( "Hello worlello world" )
2007     },
2008     */
2009     // * Remove whole line
2010     {
2011       std::string( "Remove whole line" ),
2012       Remove,
2013       std::string("Hello world, hello world\n"
2014                   "Hello world, hello world\n"
2015                   "Hello world, hello world\n"
2016                   "Hello world, hello world\n"),
2017       25,
2018       25,
2019       std::string(), // Not used.
2020       0.f,
2021       std::string("Hello world, hello world\n"
2022                   "Hello world, hello world\n"
2023                   "Hello world, hello world\n"),
2024     },
2025     {
2026       std::string( "Remove whole line" ),
2027       Remove,
2028       std::string("Hello world, hello world\n"
2029                   "H"),
2030       25,
2031       1,
2032       std::string(), // Not used.
2033       0.f,
2034       std::string("Hello world, hello world\n"),
2035     },
2036
2037
2038     // Insert operations
2039     {
2040       std::string( "insert some text" ),
2041       Insert,
2042       std::string("inpuext"),
2043       4,
2044       0,             // Not used
2045       std::string( "t t" ),
2046       0.f,
2047       std::string( "input text" )
2048     },
2049     {
2050       std::string( "Insert text at the end" ),
2051       Insert,
2052       std::string("touch "),
2053       6,
2054       0,
2055       std::string("me\nhello"),
2056       0.f,
2057       std::string("touch me\nhello")
2058     },
2059
2060     // Replace operations.
2061     {
2062       std::string( "Replace style from the beginning to some point in the middle of the text." ),
2063       Replace,
2064       std::string( "Hello <font color='green'>world</font>" ),
2065       0,
2066       7,
2067       std::string( "<font color='red'>Hello w</font>" ),
2068       0.f,
2069       std::string( "<font color='red'>Hello w</font><font color='green'>orld</font>" )
2070     },
2071     {
2072       std::string( "Replace style from the middle of the text to the end." ),
2073       Replace,
2074       std::string( "Touch me\nhello" ),
2075       6,
2076       8,
2077       std::string( "<b>me\nhello</b>" ),
2078       0.f,
2079       std::string( "Touch <b>me\nhello</b>" )
2080     },
2081     {
2082       std::string( "Remove characters from text. Previous next test:Replace style from the middle of the text 1." ),
2083       Remove,
2084       std::string( "Touch me\nhello\nworld" ),
2085       6,
2086       8,
2087       std::string( "" ),
2088       0.f,
2089       std::string( "Touch \nworld" )
2090     },
2091     {
2092       std::string( "Insert styled text in the middle of a text. Previous: Replace style from the middle of the text 1." ),
2093       Insert,
2094       std::string( "Touch \nworld" ),
2095       6,
2096       0,
2097       std::string( "<b>me\nhello</b>" ),
2098       0.f,
2099       std::string( "Touch <b>me\nhello</b>\nworld" )
2100     },
2101     {
2102       std::string( "Replace style from the middle of the text 1." ),
2103       Replace,
2104       std::string( "Touch me\nhello\nworld" ),
2105       6,
2106       8,
2107       std::string( "<b>me\nhello</b>" ),
2108       0.f,
2109       std::string( "Touch <b>me\nhello</b>\nworld" )
2110     },
2111     {
2112       std::string( "Remove characters from text. Previous next test:Replace style from the middle of the text 2." ),
2113       Remove,
2114       std::string( "Touch me\nhello\nworld" ),
2115       6,
2116       9,
2117       std::string( "" ),
2118       0.f,
2119       std::string( "Touch world" )
2120     },
2121     {
2122       std::string( "Replace style from the middle of the text 2." ),
2123       Replace,
2124       std::string( "Touch me\nhello\nworld" ),
2125       6,
2126       9,
2127       std::string( "<b>me\nhello\n</b>" ),
2128       0.f,
2129       std::string( "Touch <b>me\nhello\n</b>world" )
2130     },
2131   };
2132   const std::size_t numberOfTests( 21 );
2133
2134   for( std::size_t index = 0; index < numberOfTests; ++index )
2135   {
2136     const UpdateTextInfoTest& test = updateTextInfoTest[index];
2137
2138     if( !TestUpdateTextInfo( test.description, test.operation, test.input, test.position, test.numberOfCharacters, test.inputText, test.lineHeightOffset, test.result, TEST_LOCATION ) )
2139     {
2140       tet_result( TET_FAIL );
2141     }
2142   }
2143
2144   tet_result( TET_PASS );
2145 }
2146
2147 static void UtcDaliTextViewSplitWordGroup()
2148 {
2149   ToolkitTestApplication application;
2150
2151   tet_infoline("UtcDaliTextViewSplitWordGroup : ");
2152
2153   struct SplitWordGroupTest splitWordGroupTests[] =
2154   {
2155     {
2156       std::string( "Split word group, wordPosition 0, position 0." ),
2157       std::string( "<u><font size='10'>He<font size='12'>ll</font>oooo wooorld</font></u>" ),
2158       0,
2159       0,
2160       std::string( "" ),
2161       std::string( "<u><font size='10'>He<font size='12'>ll</font>oooo wooorld</font></u>" ),
2162     },
2163     {
2164       std::string( "Split word group, wordPosition 2, position 8." ),
2165       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font>" ),
2166       2,
2167       7,
2168       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font>" ),
2169       std::string( "" ),
2170     },
2171     {
2172       std::string( "Split word group, wordPosition 0, position 2." ),
2173       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font>" ),
2174       0,
2175       2,
2176       std::string( "<font size='10'>He</font>" ),
2177       std::string( "<font size='12'>ll</font><font size='10'>oooo wooorld</font>" ),
2178     },
2179     {
2180       std::string( "Split word group, wordPosition 0, position 3." ),
2181       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font>" ),
2182       0,
2183       3,
2184       std::string( "<font size='10'>He</font><font size='12'>l</font>" ),
2185       std::string( "<font size='12'>l</font><font size='10'>oooo wooorld</font>" ),
2186     },
2187     {
2188       std::string( "Split word group, wordPosition 0, position 4." ),
2189       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font>" ),
2190       0,
2191       4,
2192       std::string( "<font size='10'>He</font><font size='12'>ll</font>" ),
2193       std::string( "<font size='10'>oooo wooorld</font>" ),
2194     },
2195     {
2196       std::string( "Split word group, wordPosition 1, position 0." ),
2197       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font>" ),
2198       1,
2199       0,
2200       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
2201       std::string( "<font size='10'> wooorld</font>" ),
2202     },
2203   };
2204   const std::size_t numberOfTests( 6 );
2205
2206   for( std::size_t index = 0; index < numberOfTests; ++index )
2207   {
2208     const SplitWordGroupTest& test = splitWordGroupTests[index];
2209
2210     if( !TestSplitWordGroup( test.description, test.input, test.wordPosition, test.position, test.firstResult, test.lastResult, TEST_LOCATION ) )
2211     {
2212       tet_result( TET_FAIL );
2213     }
2214   }
2215
2216   tet_result( TET_PASS );
2217 }
2218
2219 static void UtcDaliTextViewSplitLine()
2220 {
2221   ToolkitTestApplication application;
2222
2223   tet_infoline("UtcDaliTextViewSplitLine : ");
2224
2225   struct SplitLineTest splitLineTests[] =
2226   {
2227     {
2228       std::string( "Split line, groupPosition 0, wordPosition 0, position 0." ),
2229       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2230       0,
2231       0,
2232       0,
2233       3.f,
2234       std::string( "" ),
2235       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2236     },
2237     {
2238       std::string( "Split line, groupPosition 2, wordPosition 2, position 4." ),
2239       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2240       2,
2241       2,
2242       4,
2243       0.f,
2244       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2245       std::string( "" ),
2246     },
2247     /* TODO check when RTL is working.
2248     {
2249       std::string( "Split line, groupPosition 1, wordPosition 2, position 0." ),
2250       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2251       1,
2252       2,
2253       0,
2254       0.f,
2255       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום" ),
2256       std::string( " עולם text text" ),
2257     },
2258     {
2259       std::string( "Split line, groupPosition 1, wordPosition 0, position 0." ),
2260       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2261       1,
2262       0,
2263       0,
2264       0.f,
2265       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> " ),
2266       std::string( "שלום עולם text text" ),
2267     },
2268     */
2269     {
2270       std::string( "Split line, groupPosition 2, wordPosition 0, position 0." ),
2271       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
2272       2,
2273       0,
2274       0,
2275       6.f,
2276       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם " ),
2277       std::string( "text text" ),
2278     },
2279   };
2280   const std::size_t numberOfTests( 3 );
2281
2282   for( std::size_t index = 0; index < numberOfTests; ++index )
2283   {
2284     const SplitLineTest& test = splitLineTests[index];
2285
2286     if( !TestSplitLine( test.description, test.input, test.groupPosition, test.wordPosition, test.position, test.lineHeightOffset, test.firstResult, test.lastResult, TEST_LOCATION ) )
2287     {
2288       tet_result( TET_FAIL );
2289     }
2290   }
2291
2292   tet_result( TET_PASS );
2293 }
2294
2295 static void UtcDaliTextViewMergeWord01()
2296 {
2297   ToolkitTestApplication application;
2298
2299   tet_infoline("UtcDaliTextViewMergeWord01 : ");
2300
2301   struct MergeWordsTest mergeWordsTests[] =
2302   {
2303     {
2304       std::string( "Merge words with same style." ),
2305       std::string( "Hel" ),
2306       std::string( "lo" ),
2307       std::string( "Hello" ),
2308     },
2309     {
2310       std::string( "Merge words with different styles." ),
2311       std::string( "<font size='10>Hel</font>" ),
2312       std::string( "<font size='20'>lo</font>" ),
2313       std::string( "<font size='10'>Hel</font><font size='20'>lo</font>" )
2314     },
2315   };
2316   const std::size_t numberOfTests( 2 );
2317
2318   for( std::size_t index = 0; index < numberOfTests; ++index )
2319   {
2320     const MergeWordsTest& test = mergeWordsTests[index];
2321
2322     if( !TestMergeWords( test.description, test.inputFirst, test.inputLast, test.result, TEST_LOCATION ) )
2323     {
2324       tet_result( TET_FAIL );
2325     }
2326   }
2327
2328   tet_result( TET_PASS );
2329 }
2330
2331 static void UtcDaliTextViewMergeWord02()
2332 {
2333   // Negative test.
2334   // It test white spaces and new line characters can't be merged to other words.
2335
2336   ToolkitTestApplication application;
2337
2338   tet_infoline("UtcDaliTextViewMergeWord02 : ");
2339
2340   // Generate three words
2341
2342   Toolkit::Internal::TextView::RelayoutData relayoutData01;
2343   Toolkit::Internal::TextView::RelayoutData relayoutData02;
2344   Toolkit::Internal::TextView::RelayoutData relayoutData03;
2345   TextViewProcessor::TextLayoutInfo& textLayoutInfo01( relayoutData01.mTextLayoutInfo );
2346   TextViewProcessor::TextLayoutInfo& textLayoutInfo02( relayoutData02.mTextLayoutInfo );
2347   TextViewProcessor::TextLayoutInfo& textLayoutInfo03( relayoutData03.mTextLayoutInfo );
2348
2349   std::string text01( " " );
2350   std::string text02( "\n" );
2351   std::string text03( "a" );
2352   MarkupProcessor::StyledTextArray styledText01;
2353   MarkupProcessor::StyledTextArray styledText02;
2354   MarkupProcessor::StyledTextArray styledText03;
2355   MarkupProcessor::GetStyledTextArray( text01, styledText01, true );
2356   MarkupProcessor::GetStyledTextArray( text02, styledText02, true );
2357   MarkupProcessor::GetStyledTextArray( text03, styledText03, true );
2358
2359   TextViewProcessor::CreateTextInfo( styledText01,
2360                                      DEFAULT_LAYOUT_PARAMETERS,
2361                                      relayoutData01 );
2362
2363   TextViewProcessor::WordLayoutInfo wordLayoutInfo01;
2364
2365   wordLayoutInfo01 = *( *( *textLayoutInfo01.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
2366
2367   TextViewProcessor::CreateTextInfo( styledText02,
2368                                      DEFAULT_LAYOUT_PARAMETERS,
2369                                      relayoutData02 );
2370
2371   TextViewProcessor::WordLayoutInfo wordLayoutInfo02;
2372
2373   wordLayoutInfo02 = *( *( *textLayoutInfo02.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
2374
2375   TextViewProcessor::CreateTextInfo( styledText03,
2376                                      DEFAULT_LAYOUT_PARAMETERS,
2377                                      relayoutData03 );
2378
2379   TextViewProcessor::WordLayoutInfo wordLayoutInfo03;
2380
2381   wordLayoutInfo03 = *( *( *textLayoutInfo03.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
2382
2383   // Test MergeWord() asserts if white spaces or new line chars are merged.
2384   bool assert1 = false;
2385   bool assert2 = false;
2386   bool assert3 = false;
2387   bool assert4 = false;
2388   bool assert5 = false;
2389   bool assert6 = false;
2390
2391   try
2392   {
2393     MergeWord( wordLayoutInfo01,
2394                wordLayoutInfo02 );
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     assert1 = true;
2401   }
2402   try
2403   {
2404     MergeWord( wordLayoutInfo01,
2405                wordLayoutInfo03 );
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     assert2 = true;
2412   }
2413   try
2414   {
2415     MergeWord( wordLayoutInfo02,
2416                wordLayoutInfo01 );
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     assert3 = true;
2423   }
2424   try
2425   {
2426     MergeWord( wordLayoutInfo02,
2427                wordLayoutInfo03 );
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     assert4 = true;
2434   }
2435   try
2436   {
2437     MergeWord( wordLayoutInfo03,
2438                wordLayoutInfo01 );
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     assert5 = true;
2445   }
2446   try
2447   {
2448     MergeWord( wordLayoutInfo03,
2449                wordLayoutInfo02 );
2450   }
2451   catch( Dali::DaliException& e )
2452   {
2453     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2454     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new line characters can't be merged with other words.\"", TEST_LOCATION );
2455     assert6 = true;
2456   }
2457
2458   if( assert1 && assert2 && assert3 && assert4 && assert5 && assert6 )
2459   {
2460     tet_result( TET_PASS );
2461   }
2462   else
2463   {
2464     tet_result( TET_FAIL );
2465   }
2466 }
2467
2468 static void UtcDaliTextViewMergeGroup01()
2469 {
2470   ToolkitTestApplication application;
2471
2472   tet_infoline("UtcDaliTextViewMergeGroup01 : ");
2473
2474   struct MergeWordGroupsTest mergeWordGroupssTests[] =
2475   {
2476     {
2477       std::string( "Merge a void first group." ),
2478       std::string( "" ),
2479       std::string( "Hello world" ),
2480       std::string( "Hello world" ),
2481     },
2482     {
2483       std::string( "Merge a void last group." ),
2484       std::string( "Hello world" ),
2485       std::string( "" ),
2486       std::string( "Hello world" ),
2487     },
2488     {
2489       std::string( "Merge groups and merge last and first words." ),
2490       std::string( "Hello wor" ),
2491       std::string( "ld, hello world" ),
2492       std::string( "Hello world, hello world" ),
2493     },
2494     {
2495       std::string( "Merge groups and don't merge last and first words." ),
2496       std::string( "Hello world, " ),
2497       std::string( "hello world" ),
2498       std::string( "Hello world, hello world" )
2499     },
2500   };
2501   const std::size_t numberOfTests( 4 );
2502
2503   for( std::size_t index = 0; index < numberOfTests; ++index )
2504   {
2505     const MergeWordGroupsTest& test = mergeWordGroupssTests[index];
2506
2507     if( !TestMergeGroupsOfWords( test.description, test.inputFirst, test.inputLast, test.result, TEST_LOCATION ) )
2508     {
2509       tet_result( TET_FAIL );
2510     }
2511   }
2512
2513   tet_result(TET_PASS);
2514 }
2515
2516 static void UtcDaliTextViewMergeGroup02()
2517 {
2518   ToolkitTestApplication application;
2519
2520   tet_infoline("UtcDaliTextViewMergeGroup02 : ");
2521
2522   Toolkit::Internal::TextView::RelayoutData relayoutData01;
2523   Toolkit::Internal::TextView::RelayoutData relayoutData02;
2524   Toolkit::Internal::TextView::RelayoutData relayoutData03;
2525   TextViewProcessor::TextLayoutInfo& textLayoutInfo01( relayoutData01.mTextLayoutInfo );
2526   TextViewProcessor::TextLayoutInfo& textLayoutInfo02( relayoutData02.mTextLayoutInfo );
2527   TextViewProcessor::TextLayoutInfo& textLayoutInfo03( relayoutData03.mTextLayoutInfo );
2528
2529   std::string text01( "Hello \n" );
2530   std::string text02( "world" );
2531   std::string text03( "السلام عليكم" );
2532   MarkupProcessor::StyledTextArray styledText01;
2533   MarkupProcessor::StyledTextArray styledText02;
2534   MarkupProcessor::StyledTextArray styledText03;
2535   MarkupProcessor::GetStyledTextArray( text01, styledText01, true );
2536   MarkupProcessor::GetStyledTextArray( text02, styledText02, true );
2537   MarkupProcessor::GetStyledTextArray( text03, styledText03, true );
2538
2539   TextViewProcessor::CreateTextInfo( styledText01,
2540                                      DEFAULT_LAYOUT_PARAMETERS,
2541                                      relayoutData01 );
2542
2543   TextViewProcessor::WordGroupLayoutInfo wordGroupLayoutInfo01;
2544
2545   wordGroupLayoutInfo01 = *( *textLayoutInfo01.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
2546
2547   TextViewProcessor::CreateTextInfo( styledText02,
2548                                      DEFAULT_LAYOUT_PARAMETERS,
2549                                      relayoutData02 );
2550
2551   TextViewProcessor::WordGroupLayoutInfo wordGroupLayoutInfo02;
2552
2553   wordGroupLayoutInfo02 = *( *textLayoutInfo02.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
2554
2555   TextViewProcessor::CreateTextInfo( styledText03,
2556                                      DEFAULT_LAYOUT_PARAMETERS,
2557                                      relayoutData03 );
2558
2559   TextViewProcessor::WordGroupLayoutInfo wordGroupLayoutInfo03;
2560
2561   wordGroupLayoutInfo03 = *( *textLayoutInfo03.mLinesLayoutInfo.begin() ).mWordGroupsLayoutInfo.begin();
2562
2563   bool assert1 = false;
2564   bool assert2 = false;
2565
2566   try
2567   {
2568     MergeWordGroup( wordGroupLayoutInfo01,
2569                     wordGroupLayoutInfo02 );
2570   }
2571   catch( Dali::DaliException& e )
2572   {
2573     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2574     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 );
2575     assert1 = true;
2576   }
2577
2578   try
2579   {
2580     MergeWordGroup( wordGroupLayoutInfo03,
2581                     wordGroupLayoutInfo02 );
2582   }
2583   catch( Dali::DaliException& e )
2584   {
2585     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2586     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWordGroup(). ERROR: groups with different direction can't be merged.\"", TEST_LOCATION );
2587     assert2 = true;
2588   }
2589
2590   if( assert1 && assert2 )
2591   {
2592     tet_result( TET_PASS );
2593   }
2594   else
2595   {
2596     tet_result( TET_FAIL );
2597   }
2598 }
2599
2600 static void UtcDaliTextViewMergeLine01()
2601 {
2602   ToolkitTestApplication application;
2603
2604   tet_infoline("UtcDaliTextViewMergeLine01 : ");
2605
2606   struct MergeLinesTest mergeLinesTests[] =
2607   {
2608     {
2609       std::string( "Merge a void first line." ),
2610       std::string( "" ),
2611       std::string( "Hello world, this is a whole line" ),
2612       2.f,
2613       std::string( "Hello world, this is a whole line" )
2614     },
2615     {
2616       std::string( "Merge a void last line." ),
2617       std::string( "Hello world, this is a whole line" ),
2618       std::string( "" ),
2619       0.f,
2620       std::string( "Hello world, this is a whole line" )
2621     },
2622     /* TODO: check when RTL text is working.
2623     {
2624       std::string( "Merge lines and merge last and first groups" ),
2625       std::string( "Hello world, שלום" ),
2626       std::string( " עולם, hello world." ),
2627       6.f,
2628       std::string( "Hello world, שלום עולם, hello world." )
2629     },
2630     {
2631       std::string( "Merge lines and don't merge last and first words." ),
2632       std::string( "Hello world, " ),
2633       std::string( "שלום עולם, hello world." ),
2634       3.f,
2635       std::string( "Hello world, שלום עולם, hello world." )
2636     },
2637     */
2638     {
2639       std::string( "Merge lines. Don't merge words" ),
2640       std::string( "Hello world," ),
2641       std::string( " this is a whole line" ),
2642       0.f,
2643       std::string( "Hello world, this is a whole line" )
2644     },
2645     {
2646       std::string( "Merge lines. Merge words" ),
2647       std::string( "Hello world, th" ),
2648       std::string( "is is a whole line" ),
2649       0.f,
2650       std::string( "Hello world, this is a whole line" )
2651     },
2652   };
2653   const std::size_t numberOfTests( 4 );
2654
2655   for( std::size_t index = 0; index < numberOfTests; ++index )
2656   {
2657     const MergeLinesTest& test = mergeLinesTests[index];
2658
2659     if( !TestMergeLines( test.description, test.inputFirst, test.inputLast, test.lineHeightOffset, test.result, TEST_LOCATION ) )
2660     {
2661       tet_result( TET_FAIL );
2662     }
2663   }
2664
2665   tet_result( TET_PASS );
2666 }
2667
2668 static void UtcDaliTextViewMergeLine02()
2669 {
2670   ToolkitTestApplication application;
2671
2672   tet_infoline("UtcDaliTextViewMergeLine02 : ");
2673
2674   Toolkit::Internal::TextView::RelayoutData relayoutData01;
2675   Toolkit::Internal::TextView::RelayoutData relayoutData02;
2676   TextViewProcessor::TextLayoutInfo& textLayoutInfo01( relayoutData01.mTextLayoutInfo );
2677   TextViewProcessor::TextLayoutInfo& textLayoutInfo02( relayoutData02.mTextLayoutInfo );
2678
2679   std::string text01( "Hello world\n" );
2680   std::string text02( "hello world" );
2681   MarkupProcessor::StyledTextArray styledText01;
2682   MarkupProcessor::StyledTextArray styledText02;
2683   MarkupProcessor::GetStyledTextArray( text01, styledText01, true );
2684   MarkupProcessor::GetStyledTextArray( text02, styledText02, true );
2685
2686   TextViewProcessor::CreateTextInfo( styledText01,
2687                                      DEFAULT_LAYOUT_PARAMETERS,
2688                                      relayoutData01 );
2689
2690   TextViewProcessor::LineLayoutInfo lineLayoutInfo01;
2691
2692   lineLayoutInfo01 = *textLayoutInfo01.mLinesLayoutInfo.begin();
2693
2694   TextViewProcessor::CreateTextInfo( styledText02,
2695                                      DEFAULT_LAYOUT_PARAMETERS,
2696                                      relayoutData02 );
2697
2698   TextViewProcessor::LineLayoutInfo lineLayoutInfo02;
2699
2700   lineLayoutInfo02 = *textLayoutInfo02.mLinesLayoutInfo.begin();
2701
2702   bool assert1 = false;
2703
2704   try
2705   {
2706     MergeLine( lineLayoutInfo01,
2707                lineLayoutInfo02 );
2708   }
2709   catch( Dali::DaliException& e )
2710   {
2711     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2712     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 );
2713     assert1 = true;
2714   }
2715
2716   if( assert1 )
2717   {
2718     tet_result( TET_PASS );
2719   }
2720   else
2721   {
2722     tet_result( TET_FAIL );
2723   }
2724 }
2725
2726 void UtcDaliTextViewRemoveCharactersFromWord()
2727 {
2728   ToolkitTestApplication application;
2729
2730   tet_infoline("UtcDaliTextViewMergeWord02 : ");
2731
2732   struct RemoveCharactersFromWordTest removeCharactersFromWordTests[] =
2733   {
2734     {
2735       std::string( "Delete 0 characters." ),
2736       std::string( "Hello" ),
2737       3,
2738       0,
2739       std::string( "Hello" ),
2740     },
2741     {
2742       std::string( "Delete within the same group of characters. Starting from the beginning" ),
2743       std::string( "Hello" ),
2744       0,
2745       3,
2746       std::string( "lo" ),
2747     },
2748     {
2749       std::string( "Delete within the same group of characters. Somewhere in the middle" ),
2750       std::string( "Hello" ),
2751       2,
2752       2,
2753       std::string( "Heo" ),
2754     },
2755     {
2756       std::string( "Delete within the same group of characters. Starting somewhere in the middle to the end" ),
2757       std::string( "Hello" ),
2758       3,
2759       2,
2760       std::string( "Hel" ),
2761     },
2762     {
2763       std::string( "Delete within the same group of characters. Finish just before a new one." ),
2764       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2765       1,
2766       2,
2767       std::string( "<font size='10'>H</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2768     },
2769     {
2770       std::string( "Delete starting in one group of characters and finishing in a different one. No merge of groups." ),
2771       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2772       2,
2773       3,
2774       std::string( "<font size='10'>He</font><font size='20'>Wo</font><font size='30'>rld</font>" ),
2775     },
2776     {
2777       std::string( "Delete within the same group of characters. Starting just after a different one." ),
2778       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2779       7,
2780       2,
2781       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>d</font>" ),
2782     },
2783     {
2784       std::string( "Delete whole group of characters. No merge" ),
2785       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2786       3,
2787       4,
2788       std::string( "<font size='10'>Hel</font><font size='30'>rld</font>" ),
2789     },
2790     {
2791       std::string( "Delete whole group of characters and part of the adjacent ones. No merge" ),
2792       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2793       2,
2794       6,
2795       std::string( "<font size='10'>He</font><font size='30'>ld</font>" ),
2796     },
2797     {
2798       std::string( "Delete whole group of characters. Merge" ),
2799       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='10'>rld</font>" ),
2800       3,
2801       4,
2802       std::string( "<font size='10'>Helrld</font>" ),
2803     },
2804     {
2805       std::string( "Delete whole group of characters and part of the adjacent ones. Merge" ),
2806       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='10'>rld</font>" ),
2807       2,
2808       6,
2809       std::string( "<font size='10'>Held</font>" ),
2810     },
2811   };
2812   const std::size_t numberOfTests( 11 );
2813
2814   for( std::size_t index = 0; index < numberOfTests; ++index )
2815   {
2816     const RemoveCharactersFromWordTest& test = removeCharactersFromWordTests[index];
2817
2818     if( !TestRemoveCharactersFromWord( test.description, test.input, test.position, test.numberOfCharacters, test.result, TEST_LOCATION ) )
2819     {
2820       tet_result( TET_FAIL );
2821     }
2822   }
2823
2824   tet_result( TET_PASS );
2825 }
2826
2827 static void UtcDaliTextViewRemoveWordsFromGroup()
2828 {
2829   // Note: Currently RemoveWordsFromWordGroup() function is only used to remove a number of words from the beginning, or
2830   //       from a given index to the end. RemoveWordsFromWordGroup() doesn't merge words (if a white space is removed) so
2831   //       tehere isn't any TET case to cover these cases. To be done if needed.
2832
2833   ToolkitTestApplication application;
2834
2835   tet_infoline("UtcDaliTextViewRemoveWordsFromGroup : ");
2836   struct RemoveWordsFromGroupTest removeWordsFromGroupTests[] =
2837   {
2838     {
2839       std::string( "Delete 0 words." ),
2840       std::string( "Hello world, hello world" ),
2841       3,
2842       0,
2843       std::string( "Hello world, hello world" ),
2844     },
2845     {
2846       std::string( "Delete some words in the middle. Don't merge words" ),
2847       std::string( "<font size='10'>Hel</font><font size='20'>lo wo</font><font size='30'>rld, hello world</font>" ),
2848       1,
2849       4,
2850       std::string( "<font size='10'>Hel</font><font size='20'>lo</font><font size='30'> world</font>" ),
2851     },
2852     {
2853       std::string( "Delete words up to the end" ),
2854       std::string( "<font size='10'>Hel</font><font size='20'>lo wo</font><font size='30'>rld, hello world</font>" ),
2855       5,
2856       2,
2857       std::string( "<font size='10'>Hel</font><font size='20'>lo wo</font><font size='30'>rld, hello</font>" ),
2858     },
2859     {
2860       std::string( "Delete words from the beginning." ),
2861       std::string( "Hello world, hello world" ),
2862       0,
2863       3,
2864       std::string( " hello world" ),
2865     },
2866   };
2867   const std::size_t numberOfTests( 4 );
2868
2869   for( std::size_t index = 0; index < numberOfTests; ++index )
2870   {
2871     const RemoveWordsFromGroupTest& test = removeWordsFromGroupTests[index];
2872
2873     if( !TestRemoveWordsFromGroup( test.description, test.input, test.wordIndex, test.numberOfWords, test.result, TEST_LOCATION ) )
2874     {
2875       tet_result( TET_FAIL );
2876     }
2877   }
2878
2879   tet_result( TET_PASS );
2880 }
2881
2882 static void UtcDaliTextViewRemoveGroupsFromLine()
2883 {
2884   // Note: Currently RemoveWordGroupsFromLine() function is only used to remove a number of group of words from the beginning, or
2885   //       from a given index to the end. RemoveWordGroupsFromLine() doesn't merge groups of words (if a whole group of words is removed) so
2886   //       tehere isn't any TET case to cover these cases. To be done if needed.
2887
2888   ToolkitTestApplication application;
2889
2890   tet_infoline("UtcDaliTextViewRemoveGroupsFromLine : ");
2891   struct RemoveGroupsFromLineTest removeGroupsFromLineTests[] =
2892   {
2893     {
2894       std::string( "Delete 0 groups of words." ),
2895       std::string( "Hello hello, שלום עולם hello hello" ),
2896       1,
2897       0,
2898       2.f,
2899       std::string( "Hello hello, שלום עולם hello hello" ),
2900     },
2901     {
2902       std::string( "Delete from the middle to the end." ),
2903       std::string( "Hello hello, שלום עולם hello hello" ),
2904       1,
2905       2,
2906       0.f,
2907       std::string( "Hello hello, " ),
2908     },
2909     {
2910       std::string( "Delete from the beginning to the middle." ),
2911       std::string( "Hello hello, שלום עולם hello hello" ),
2912       0,
2913       2,
2914       6.f,
2915       std::string( "hello hello" ),
2916     },
2917   };
2918   const std::size_t numberOfTests( 3 );
2919
2920   for( std::size_t index = 0; index < numberOfTests; ++index )
2921   {
2922     const RemoveGroupsFromLineTest& test = removeGroupsFromLineTests[index];
2923
2924     if( !TestRemoveGroupsFromLine( test.description, test.input, test.groupIndex, test.numberOfGroups, test.lineHeightOffset, test.result, TEST_LOCATION ) )
2925     {
2926       tet_result( TET_FAIL );
2927     }
2928   }
2929
2930   tet_result( TET_PASS );
2931 }