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