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