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