e625f72d4f436f1568c3c766c0099053da883335
[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-processor-dbg.h>
27 #include <dali-toolkit/internal/controls/text-view/text-view-paragraph-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 SplitParagraphTest
64 {
65   std::string description;
66   std::string input;
67   std::size_t wordIndex;
68   std::size_t characterIndex;
69   float       lineHeightOffset;
70   std::string firstResult;
71   std::string lastResult;
72 };
73
74 struct MergeWordsTest
75 {
76   std::string description;
77   std::string inputFirst;
78   std::string inputLast;
79   std::string result;
80 };
81
82 struct MergeParagraphsTest
83 {
84   std::string description;
85   std::string inputFirst;
86   std::string inputLast;
87   float       lineHeightOffset;
88   std::string result;
89 };
90
91 struct RemoveCharactersFromWordTest
92 {
93   std::string description;
94   std::string input;
95   std::size_t position;
96   std::size_t numberOfCharacters;
97   std::string result;
98 };
99
100 struct RemoveWordsFromParagraphTest
101 {
102   std::string description;
103   std::string input;
104   std::size_t wordIndex;
105   std::size_t numberOfWords;
106   float       lineHeightOffset;
107   std::string result;
108 };
109
110 enum UpdateTextInfoOperation
111 {
112   Insert,
113   Remove,
114   Replace
115 };
116
117 struct UpdateTextInfoTest
118 {
119   std::string             description;
120   UpdateTextInfoOperation operation;
121   std::string             input;
122   std::size_t             position;
123   std::size_t             numberOfCharacters;
124   std::string             inputText;
125   float                   lineHeightOffset;
126   std::string             result;
127 };
128
129 // Useful Print functions when something goes wrong.
130
131 void Print( const TextViewProcessor::CharacterLayoutInfo& character )
132 {
133   std::cout << "             height : " << character.mHeight << std::endl;
134   std::cout << "            advance : " << character.mAdvance << std::endl;
135   std::cout << "            bearing : " << character.mBearing << std::endl;
136   std::cout << "          mPosition : " << character.mPosition << std::endl;
137   std::cout << "              mSize : " << character.mSize << std::endl;
138   std::cout << "          mAscender : " << character.mAscender << std::endl;
139
140   TextActor textActor = TextActor::DownCast( character.mGlyphActor );
141   if( textActor )
142   {
143     std::cout << "[" << textActor.GetText() << "]";
144   }
145   else
146   {
147     std::cout << "{" << character.mStyledText.mText.GetText() << "}";
148   }
149 }
150
151 void Print( const TextViewProcessor::WordLayoutInfo& word )
152 {
153   std::cout << "[";
154   std::cout << "              mSize : " << word.mSize << std::endl;
155   std::cout << "          mAscender : " << word.mAscender << std::endl;
156   std::cout << "              mType : " << word.mType << std::endl;
157   std::cout << "mNumberOfCharacters : " << word.mCharactersLayoutInfo.size() << std::endl;
158   std::cout << "[";
159   for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator it = word.mCharactersLayoutInfo.begin(), endIt = word.mCharactersLayoutInfo.end(); it != endIt; ++it )
160   {
161     Print( *it );
162   }
163   std::cout << "]"; std::cout << std::endl;
164   std::cout << "]"; std::cout << std::endl;
165 }
166
167 void Print( const TextViewProcessor::ParagraphLayoutInfo& paragraph )
168 {
169   std::cout << "<";
170   std::cout << "              mSize : " << paragraph.mSize << std::endl;
171   std::cout << "          mAscender : " << paragraph.mAscender << std::endl;
172   std::cout << "mNumberOfCharacters : " << paragraph.mNumberOfCharacters << std::endl;
173   for( TextViewProcessor::WordLayoutInfoContainer::const_iterator it = paragraph.mWordsLayoutInfo.begin(), endIt = paragraph.mWordsLayoutInfo.end(); it != endIt; ++it )
174   {
175     Print( *it );
176   }
177   std::cout << ">" << std::endl;
178 }
179
180 void Print( const TextViewProcessor::TextLayoutInfo& text )
181 {
182   std::cout << "||";
183   for( TextViewProcessor::ParagraphLayoutInfoContainer::const_iterator it = text.mParagraphsLayoutInfo.begin(), endIt = text.mParagraphsLayoutInfo.end(); it != endIt; ++it )
184   {
185     Print( *it );
186   }
187   std::cout << "||" << std::endl;
188 }
189
190 std::string GetText( const TextViewProcessor::CharacterLayoutInfo& character )
191 {
192   return character.mStyledText.mText.GetText();
193 }
194
195 std::string GetText( const TextViewProcessor::WordLayoutInfo& word )
196 {
197   std::string text;
198
199   for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator it = word.mCharactersLayoutInfo.begin(), endIt = word.mCharactersLayoutInfo.end(); it != endIt; ++it )
200   {
201     text += GetText( *it );
202   }
203
204   return text;
205 }
206
207 std::string GetText( const TextViewProcessor::ParagraphLayoutInfo& paragraph )
208 {
209   std::string text;
210
211   for( TextViewProcessor::WordLayoutInfoContainer::const_iterator it = paragraph.mWordsLayoutInfo.begin(), endIt = paragraph.mWordsLayoutInfo.end(); it != endIt; ++it )
212   {
213     text += GetText( *it );
214   }
215
216   return text;
217 }
218
219 // Test functions used to check if two data structures are equal.
220
221 bool TestEqual( float x, float y )
222 {
223   return ( fabsf( x - y ) < 0.001f );
224 }
225
226 bool TestEqual( const TextViewProcessor::CharacterLayoutInfo& character1,
227                 const TextViewProcessor::CharacterLayoutInfo& character2 )
228 {
229   if( !TestEqual( character1.mHeight, character2.mHeight ) )
230   {
231     return false;
232   }
233   if( !TestEqual( character1.mAdvance, character2.mAdvance ) )
234   {
235     return false;
236   }
237   if( !TestEqual( character1.mBearing, character2.mBearing ) )
238   {
239     return false;
240   }
241
242   if( !TestEqual( character1.mPosition.x, character2.mPosition.x ) )
243   {
244     return false;
245   }
246   if( !TestEqual( character1.mPosition.y, character2.mPosition.y ) )
247   {
248     return false;
249   }
250
251   if( !TestEqual( character1.mSize.x, character2.mSize.x ) )
252   {
253     return false;
254   }
255   if( !TestEqual( character1.mSize.y, character2.mSize.y ) )
256   {
257     return false;
258   }
259
260   if( !TestEqual( character1.mAscender, character2.mAscender ) )
261   {
262     return false;
263   }
264
265   if( character1.mGlyphActor && !character2.mGlyphActor )
266   {
267     return false;
268   }
269
270   if( !character1.mGlyphActor && character2.mGlyphActor )
271   {
272     return false;
273   }
274
275   std::string text1;
276   std::string text2;
277   TextStyle style1;
278   TextStyle style2;
279
280   TextActor textActor1 = TextActor::DownCast( character1.mGlyphActor );
281   TextActor textActor2 = TextActor::DownCast( character2.mGlyphActor );
282   if( textActor1 )
283   {
284     text1 = textActor1.GetText();
285     style1 = textActor1.GetTextStyle();
286
287     text2 = textActor2.GetText();
288     style2 = textActor2.GetTextStyle();
289   }
290
291   if( text1 != text2 )
292   {
293     return false;
294   }
295
296   if( style1 != style2 )
297   {
298     return false;
299   }
300
301   text1 = character1.mStyledText.mText.GetText();
302   style1 = character1.mStyledText.mStyle;
303
304   text2 = character2.mStyledText.mText.GetText();
305   style2 = character2.mStyledText.mStyle;
306
307   if( text1 != text2 )
308   {
309     return false;
310   }
311
312   if( style1 != style2 )
313   {
314     std::cout << "  style1 : " << std::endl;
315     TextViewProcessor::dbgPrint( style1 );
316
317     std::cout << "  style2 : " << std::endl;
318     TextViewProcessor::dbgPrint( style2 );
319     return false;
320   }
321
322   return true;
323 }
324
325 bool TestEqual( const TextViewProcessor::WordLayoutInfo& word1,
326                 const TextViewProcessor::WordLayoutInfo& word2 )
327 {
328   if( !TestEqual( word1.mSize.x, word2.mSize.x ) )
329   {
330     return false;
331   }
332   if( !TestEqual( word1.mSize.y, word2.mSize.y ) )
333   {
334     return false;
335   }
336
337   if( !TestEqual( word1.mAscender, word2.mAscender ) )
338   {
339     return false;
340   }
341
342   if( word1.mType != word2.mType )
343   {
344     return false;
345   }
346
347   if( word1.mCharactersLayoutInfo.size() != word2.mCharactersLayoutInfo.size() )
348   {
349     return false;
350   }
351
352   for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator it1 = word1.mCharactersLayoutInfo.begin(), endIt1 = word1.mCharactersLayoutInfo.end(),
353          it2 = word2.mCharactersLayoutInfo.begin(), endIt2 = word2.mCharactersLayoutInfo.end();
354        ( it1 != endIt1 ) && ( it2 != endIt2 );
355        ++it1, ++it2 )
356   {
357     if( !TestEqual( *it1, *it2 ) )
358     {
359       return false;
360     }
361   }
362
363   return true;
364 }
365
366 bool TestEqual( const TextViewProcessor::ParagraphLayoutInfo& paragraph1,
367                 const TextViewProcessor::ParagraphLayoutInfo& paragraph2 )
368 {
369   if( !TestEqual( paragraph1.mSize.x, paragraph2.mSize.x ) )
370   {
371     return false;
372   }
373   if( !TestEqual( paragraph1.mSize.y, paragraph2.mSize.y ) )
374   {
375     return false;
376   }
377
378   if( !TestEqual( paragraph1.mAscender, paragraph2.mAscender ) )
379   {
380     return false;
381   }
382
383   if( paragraph1.mNumberOfCharacters != paragraph2.mNumberOfCharacters )
384   {
385     return false;
386   }
387
388   if( paragraph1.mWordsLayoutInfo.size() != paragraph2.mWordsLayoutInfo.size() )
389   {
390     return false;
391   }
392
393   for( TextViewProcessor::WordLayoutInfoContainer::const_iterator it1 = paragraph1.mWordsLayoutInfo.begin(), endIt1 = paragraph1.mWordsLayoutInfo.end(),
394          it2 = paragraph2.mWordsLayoutInfo.begin(), endIt2 = paragraph2.mWordsLayoutInfo.end();
395        ( it1 != endIt1 ) && ( it2 != endIt2 );
396        ++it1, ++it2 )
397   {
398     if( !TestEqual( *it1, *it2 ) )
399     {
400       return false;
401     }
402   }
403
404   return true;
405 }
406
407 bool TestEqual( const TextViewProcessor::TextLayoutInfo& text1,
408                 const TextViewProcessor::TextLayoutInfo& text2 )
409 {
410   if( !TestEqual( text1.mWholeTextSize.x, text2.mWholeTextSize.x ) )
411   {
412     return false;
413   }
414   if( !TestEqual( text1.mWholeTextSize.y, text2.mWholeTextSize.y ) )
415   {
416     return false;
417   }
418
419   if( !TestEqual( text1.mMaxWordWidth, text2.mMaxWordWidth ) )
420   {
421     return false;
422   }
423
424   if( text1.mNumberOfCharacters != text2.mNumberOfCharacters )
425   {
426     return false;
427   }
428
429   if( text1.mParagraphsLayoutInfo.size() != text2.mParagraphsLayoutInfo.size() )
430   {
431     return false;
432   }
433
434   for( TextViewProcessor::ParagraphLayoutInfoContainer::const_iterator it1 = text1.mParagraphsLayoutInfo.begin(), endIt1 = text1.mParagraphsLayoutInfo.end(),
435          it2 = text2.mParagraphsLayoutInfo.begin(), endIt2 = text2.mParagraphsLayoutInfo.end();
436        ( it1 != endIt1 ) && ( it2 != endIt2 );
437        ++it1, ++it2 )
438   {
439     if( !TestEqual( *it1, *it2 ) )
440     {
441       return false;
442     }
443   }
444
445   return true;
446 }
447
448 /**
449  * Splits the \e input word in two by the given \e position and checks the results with \e firstResult and \e lastResult.
450  *
451  * If the test fails it prints a short description and the line where this function was called.
452  *
453  * @param description Short description of the experiment. i.e. "Split the word from the beginning. (position 0)".
454  * @param input The input word.
455  * @param position Where to split the word.
456  * @param firstResult First part of the split word.
457  * @param lastResult Last part of the split word.
458  * @param location Where this function has been called.
459  *
460  * @return \e true if the experiment is successful. Otherwise returns \e false.
461  */
462 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 )
463 {
464   tet_printf( "%s\n", description.c_str() );
465
466   // Create layout info for the input word.
467   Toolkit::Internal::TextView::RelayoutData relayoutData;
468   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
469
470   MarkupProcessor::StyledTextArray inputStyledText;
471   MarkupProcessor::GetStyledTextArray( input, inputStyledText, true );
472
473   TextViewProcessor::CreateTextInfo( inputStyledText,
474                                      DEFAULT_LAYOUT_PARAMETERS,
475                                      relayoutData );
476
477   // Get the input word
478   TextViewProcessor::WordLayoutInfo inputWordLayout;
479
480   if( !inputLayout.mParagraphsLayoutInfo.empty() )
481   {
482     const TextViewProcessor::ParagraphLayoutInfo& paragraph( *inputLayout.mParagraphsLayoutInfo.begin() );
483     if( !paragraph.mWordsLayoutInfo.empty() )
484     {
485       inputWordLayout = *( *inputLayout.mParagraphsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
486     }
487   }
488
489   // Create layout info for the first part of the result (after split the word)
490
491   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
492   TextViewProcessor::TextLayoutInfo& firstResultLayout( firstRelayoutData.mTextLayoutInfo );
493
494   MarkupProcessor::StyledTextArray firstResultStyledText;
495   MarkupProcessor::GetStyledTextArray( firstResult, firstResultStyledText, true );
496
497   TextViewProcessor::CreateTextInfo( firstResultStyledText,
498                                      DEFAULT_LAYOUT_PARAMETERS,
499                                      firstRelayoutData );
500
501   // Get the first result word
502   TextViewProcessor::WordLayoutInfo firstResultWordLayout;
503
504   if( !firstResultLayout.mParagraphsLayoutInfo.empty() )
505   {
506    const TextViewProcessor::ParagraphLayoutInfo& paragraph( *firstResultLayout.mParagraphsLayoutInfo.begin() );
507     if( !paragraph.mWordsLayoutInfo.empty() )
508     {
509       firstResultWordLayout = *( *firstResultLayout.mParagraphsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
510     }
511   }
512
513   // Create layout info for the last part of the result (after split the word)
514
515   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
516   TextViewProcessor::TextLayoutInfo& lastResultLayout( lastRelayoutData.mTextLayoutInfo );
517
518   MarkupProcessor::StyledTextArray lastResultStyledText;
519   MarkupProcessor::GetStyledTextArray( lastResult, lastResultStyledText, true );
520
521   TextViewProcessor::CreateTextInfo( lastResultStyledText,
522                                      DEFAULT_LAYOUT_PARAMETERS,
523                                      lastRelayoutData );
524
525   // Get the last result word
526   TextViewProcessor::WordLayoutInfo lastResultWordLayout;
527
528   if( !lastResultLayout.mParagraphsLayoutInfo.empty() )
529   {
530     const TextViewProcessor::ParagraphLayoutInfo& paragraph( *lastResultLayout.mParagraphsLayoutInfo.begin() );
531     if( !paragraph.mWordsLayoutInfo.empty() )
532     {
533       lastResultWordLayout = *( *lastResultLayout.mParagraphsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
534     }
535   }
536
537   // Split the word.
538
539   TextViewProcessor::WordLayoutInfo lastWordLayoutInfo;
540
541   SplitWord( position,
542              inputWordLayout,
543              lastWordLayoutInfo );
544
545   // Test results
546   if( !TestEqual( inputWordLayout, firstResultWordLayout ) )
547   {
548     tet_printf( "Fail. different layout info. %s\n", location );
549     return false;
550   }
551
552   if( !TestEqual( lastWordLayoutInfo, lastResultWordLayout ) )
553   {
554     tet_printf( "Fail. different layout info. %s\n", location );
555     return false;
556   }
557
558   return true;
559 }
560
561 /**
562  * Splits the \e input paragraph in two by the given \e wordIndex and \e characterIndex and checks the results with \e firstResult and \e lastResult.
563  *
564  * If the test fails it prints a short description and the line where this function was called.
565  *
566  * @param description Short description of the experiment. i.e. "Split the paragraph from the beginning. (wordIndex 0 and characterIndex 0)".
567  * @param input The input word.
568  * @param wordIndex Index to the word within the paragraph where to split it.
569  * @param characterIndex Where to split the word.
570  * @param lineHeightOffset Offset between lines.
571  * @param firstResult First part of the split paragraph.
572  * @param lastResult Last part of the split paragraph.
573  * @param location Where this function has been called.
574  *
575  * @return \e true if the experiment is successful. Otherwise returns \e false.
576  */
577 bool TestSplitParagraph( const std::string& description,
578                          const std::string& input,
579                          size_t wordIndex,
580                          size_t characterIndex,
581                          float lineHeightOffset,
582                          const std::string& firstResult,
583                          const std::string& lastResult,
584                          const char* location )
585 {
586   tet_printf( "%s\n", description.c_str() );
587
588   // Create layout info for the input paragraph.
589   Toolkit::Internal::TextView::RelayoutData relayoutData;
590   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
591
592   MarkupProcessor::StyledTextArray inputStyledText;
593   MarkupProcessor::GetStyledTextArray( input, inputStyledText, true );
594
595   TextViewProcessor::CreateTextInfo( inputStyledText,
596                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
597                                                                                     Toolkit::TextView::Original,
598                                                                                     Toolkit::TextView::Original,
599                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
600                                                                                     Toolkit::TextView::Center,
601                                                                                     PointSize( lineHeightOffset ),
602                                                                                     std::string( "..." ),
603                                                                                     true ),
604                                      relayoutData );
605
606   // Get the input paragraph
607   TextViewProcessor::ParagraphLayoutInfo inputParagraphLayout;
608
609   if( !inputLayout.mParagraphsLayoutInfo.empty() )
610   {
611     inputParagraphLayout = *inputLayout.mParagraphsLayoutInfo.begin();
612   }
613
614   // Create layout info for the first part of the result (after split the paragraph)
615
616   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
617   TextViewProcessor::TextLayoutInfo& firstResultLayout( firstRelayoutData.mTextLayoutInfo );
618
619   MarkupProcessor::StyledTextArray firstResultStyledText;
620   MarkupProcessor::GetStyledTextArray( firstResult, firstResultStyledText, true );
621
622   TextViewProcessor::CreateTextInfo( firstResultStyledText,
623                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
624                                                                                     Toolkit::TextView::Original,
625                                                                                     Toolkit::TextView::Original,
626                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
627                                                                                     Toolkit::TextView::Center,
628                                                                                     PointSize( lineHeightOffset ),
629                                                                                     std::string( "..." ),
630                                                                                     true ),
631                                      firstRelayoutData );
632
633   // Get the first result paragraph
634   TextViewProcessor::ParagraphLayoutInfo firstResultParagraphLayout;
635
636   if( !firstResultLayout.mParagraphsLayoutInfo.empty() )
637   {
638     firstResultParagraphLayout = *firstResultLayout.mParagraphsLayoutInfo.begin();
639   }
640
641   // Create layout info for the last part of the result (after split the paragraph)
642
643   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
644   TextViewProcessor::TextLayoutInfo& lastResultLayout( lastRelayoutData.mTextLayoutInfo );
645
646   MarkupProcessor::StyledTextArray lastResultStyledText;
647   MarkupProcessor::GetStyledTextArray( lastResult, lastResultStyledText, true );
648
649   TextViewProcessor::CreateTextInfo( lastResultStyledText,
650                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
651                                                                                     Toolkit::TextView::Original,
652                                                                                     Toolkit::TextView::Original,
653                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
654                                                                                     Toolkit::TextView::Center,
655                                                                                     PointSize( lineHeightOffset ),
656                                                                                     std::string( "..."),
657                                                                                     true ),
658                                      lastRelayoutData );
659
660   // Get the last result paragraph
661   TextViewProcessor::ParagraphLayoutInfo lastResultParagraphLayout;
662
663   if( !lastResultLayout.mParagraphsLayoutInfo.empty() )
664   {
665     lastResultParagraphLayout = *lastResultLayout.mParagraphsLayoutInfo.begin();
666   }
667
668   // Split the paragraph.
669
670   TextViewProcessor::ParagraphLayoutInfo lastParagraphLayoutInfo;
671
672   TextViewProcessor::TextInfoIndices indices( 0, wordIndex, characterIndex );
673
674   SplitParagraph( indices,
675                   PointSize( lineHeightOffset ),
676                   inputParagraphLayout,
677                   lastParagraphLayoutInfo );
678
679   // Test results
680   if( !TestEqual( inputParagraphLayout, firstResultParagraphLayout ) )
681   {
682     tet_printf( "Fail. different first layout info. %s\n", location );
683     return false;
684   }
685
686   if( !TestEqual( lastParagraphLayoutInfo, lastResultParagraphLayout ) )
687   {
688     tet_printf( "Fail. different last layout info. %s\n", location );
689     return false;
690   }
691
692   return true;
693 }
694
695 /**
696  * Merges the \e inputFirst word and the \e inputLast word, and checks the results with \e result.
697  *
698  * If the test fails it prints a short description and the line where this function was called.
699  *
700  * @param description Short description of the experiment. i.e. "Merge two words with same style".
701  * @param inputFirst The first part of the word.
702  * @param inputLast The last part of the word.
703  * @param result The merged word.
704  * @param location Where this function has been called.
705  *
706  * @return \e true if the experiment is successful. Otherwise returns \e false.
707  */
708 bool TestMergeWords( const std::string& description, const std::string& inputFirst, const std::string& inputLast, const std::string& result, const char* location )
709 {
710   tet_printf( "%s\n", description.c_str() );
711
712   // Create layout info for the inputFirst word.
713   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
714   TextViewProcessor::TextLayoutInfo& inputFirstLayout( firstRelayoutData.mTextLayoutInfo );
715
716   MarkupProcessor::StyledTextArray inputFirstStyledText;
717   MarkupProcessor::GetStyledTextArray( inputFirst, inputFirstStyledText, true );
718
719   TextViewProcessor::CreateTextInfo( inputFirstStyledText,
720                                      DEFAULT_LAYOUT_PARAMETERS,
721                                      firstRelayoutData );
722
723   // Get the input word
724   TextViewProcessor::WordLayoutInfo inputFirstWordLayout;
725
726   if( !inputFirstLayout.mParagraphsLayoutInfo.empty() )
727   {
728     const TextViewProcessor::ParagraphLayoutInfo& paragraph( *inputFirstLayout.mParagraphsLayoutInfo.begin() );
729     if( !paragraph.mWordsLayoutInfo.empty() )
730     {
731       inputFirstWordLayout = *( *inputFirstLayout.mParagraphsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
732     }
733   }
734
735   // Create layout info for the inputLast word.
736   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
737   TextViewProcessor::TextLayoutInfo& inputLastLayout( lastRelayoutData.mTextLayoutInfo );
738
739   MarkupProcessor::StyledTextArray inputLastStyledText;
740   MarkupProcessor::GetStyledTextArray( inputLast, inputLastStyledText, true );
741
742   TextViewProcessor::CreateTextInfo( inputLastStyledText,
743                                      DEFAULT_LAYOUT_PARAMETERS,
744                                      lastRelayoutData );
745
746   // Get the input word
747   TextViewProcessor::WordLayoutInfo inputLastWordLayout;
748
749   if( !inputLastLayout.mParagraphsLayoutInfo.empty() )
750   {
751     const TextViewProcessor::ParagraphLayoutInfo& paragraph( *inputLastLayout.mParagraphsLayoutInfo.begin() );
752     if( !paragraph.mWordsLayoutInfo.empty() )
753     {
754       inputLastWordLayout = *( *inputLastLayout.mParagraphsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
755     }
756   }
757
758   // Create layout info for the result word.
759   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
760   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
761
762   MarkupProcessor::StyledTextArray resultStyledText;
763   MarkupProcessor::GetStyledTextArray( result, resultStyledText, true );
764
765   TextViewProcessor::CreateTextInfo( resultStyledText,
766                                      DEFAULT_LAYOUT_PARAMETERS,
767                                      resultRelayoutData );
768
769   // Get the result word
770   TextViewProcessor::WordLayoutInfo resultWordLayout;
771
772   if( !resultLayout.mParagraphsLayoutInfo.empty() )
773   {
774     const TextViewProcessor::ParagraphLayoutInfo& paragraph( *resultLayout.mParagraphsLayoutInfo.begin() );
775     if( !paragraph.mWordsLayoutInfo.empty() )
776     {
777       resultWordLayout = *( *resultLayout.mParagraphsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
778     }
779   }
780
781   MergeWord( inputFirstWordLayout,
782              inputLastWordLayout );
783
784   if( !TestEqual( inputFirstWordLayout, resultWordLayout ) )
785   {
786     tet_printf( "Fail. different layout info. %s\n", location );
787     return false;
788   }
789
790   return true;
791 }
792
793 /**
794  * Merges the \e inputFirst paragraph and the \e inputLast paragraph, and checks the results with \e result.
795  *
796  * If the test fails it prints a short description and the line where this function was called.
797  *
798  * @param description Short description of the experiment.
799  * @param inputFirst The first part of the paragraph.
800  * @param inputLast The last part of the paragraph.
801  * @param lineHeightOffset Offset between lines.
802  * @param result The merged paragraph.
803  * @param location Where this function has been called.
804  *
805  * @return \e true if the experiment is successful. Otherwise returns \e false.
806  */
807 bool TestMergeParagraphs( const std::string& description, const std::string& inputFirst, const std::string& inputLast, const float lineHeightOffset, const std::string& result, const char* location )
808 {
809   tet_printf( "%s\n", description.c_str() );
810
811   // Create layout info for the inputFirst paragraph.
812   Toolkit::Internal::TextView::RelayoutData firstRelayoutData;
813   TextViewProcessor::TextLayoutInfo& inputFirstLayout( firstRelayoutData.mTextLayoutInfo );
814
815   MarkupProcessor::StyledTextArray inputFirstStyledText;
816   MarkupProcessor::GetStyledTextArray( inputFirst, inputFirstStyledText, true );
817
818   TextViewProcessor::CreateTextInfo( inputFirstStyledText,
819                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
820                                                                                     Toolkit::TextView::Original,
821                                                                                     Toolkit::TextView::Original,
822                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
823                                                                                     Toolkit::TextView::Center,
824                                                                                     PointSize( lineHeightOffset ),
825                                                                                     std::string( "..." ),
826                                                                                     true ),
827                                      firstRelayoutData );
828
829   // Get the input word
830   TextViewProcessor::ParagraphLayoutInfo inputFirstParagraphLayout;
831
832   if( !inputFirstLayout.mParagraphsLayoutInfo.empty() )
833   {
834     inputFirstParagraphLayout = *inputFirstLayout.mParagraphsLayoutInfo.begin();
835   }
836
837   // Create layout info for the inputLast paragraph.
838   Toolkit::Internal::TextView::RelayoutData lastRelayoutData;
839   TextViewProcessor::TextLayoutInfo& inputLastLayout( lastRelayoutData.mTextLayoutInfo );
840
841   MarkupProcessor::StyledTextArray inputLastStyledText;
842   MarkupProcessor::GetStyledTextArray( inputLast, inputLastStyledText, true );
843
844   TextViewProcessor::CreateTextInfo( inputLastStyledText,
845                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
846                                                                                     Toolkit::TextView::Original,
847                                                                                     Toolkit::TextView::Original,
848                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
849                                                                                     Toolkit::TextView::Center,
850                                                                                     PointSize( lineHeightOffset ),
851                                                                                     std::string( "..." ),
852                                                                                     true ),
853                                      lastRelayoutData );
854
855   // Get the input word
856   TextViewProcessor::ParagraphLayoutInfo inputLastParagraphLayout;
857
858   if( !inputLastLayout.mParagraphsLayoutInfo.empty() )
859   {
860     inputLastParagraphLayout = *inputLastLayout.mParagraphsLayoutInfo.begin();
861   }
862
863   // Create layout info for the result word.
864   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
865   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
866
867   MarkupProcessor::StyledTextArray resultStyledText;
868   MarkupProcessor::GetStyledTextArray( result, resultStyledText, true );
869
870   TextViewProcessor::CreateTextInfo( resultStyledText,
871                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
872                                                                                     Toolkit::TextView::Original,
873                                                                                     Toolkit::TextView::Original,
874                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
875                                                                                     Toolkit::TextView::Center,
876                                                                                     PointSize( lineHeightOffset ),
877                                                                                     std::string( "..." ),
878                                                                                     true ),
879                                      resultRelayoutData );
880
881   // Get the result word
882   TextViewProcessor::ParagraphLayoutInfo resultParagraphLayout;
883
884   if( !resultLayout.mParagraphsLayoutInfo.empty() )
885   {
886     resultParagraphLayout = *resultLayout.mParagraphsLayoutInfo.begin();
887   }
888
889   MergeParagraph( inputFirstParagraphLayout,
890                   inputLastParagraphLayout );
891
892   if( !TestEqual( inputFirstParagraphLayout, resultParagraphLayout ) )
893   {
894     tet_printf( "Fail. different layout info. %s\n", location );
895     return false;
896   }
897
898   return true;
899 }
900
901 /**
902  * Removes from the \e input word the \e numberOfCharacters characters starting from the given \e position and checks the results with \e result.
903  *
904  * If the test fails it prints a short description and the line where this function was called.
905  *
906  * @param description Short description of the experiment. i.e. "Remove a whole word. Merge".
907  * @param input The input word.
908  * @param position Where to start to remove characters
909  * @param numberOfCharacters The number of characters to remove.
910  * @param result The word without the removed characters.
911  * @param location Where this function has been called.
912  *
913  * @return \e true if the experiment is successful. Otherwise returns \e false.
914  */
915 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 )
916 {
917   tet_printf( "%s\n", description.c_str() );
918
919   // Create layout info for the input word.
920   Toolkit::Internal::TextView::RelayoutData relayoutData;
921   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
922
923   MarkupProcessor::StyledTextArray inputStyledText;
924   MarkupProcessor::GetStyledTextArray( input, inputStyledText, true );
925
926   TextViewProcessor::CreateTextInfo( inputStyledText,
927                                      DEFAULT_LAYOUT_PARAMETERS,
928                                      relayoutData );
929
930   // Get the input word
931   TextViewProcessor::WordLayoutInfo inputWordLayout;
932
933   if( !inputLayout.mParagraphsLayoutInfo.empty() )
934   {
935     const TextViewProcessor::ParagraphLayoutInfo& paragraph( *inputLayout.mParagraphsLayoutInfo.begin() );
936     if( !paragraph.mWordsLayoutInfo.empty() )
937     {
938       inputWordLayout = *( *inputLayout.mParagraphsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
939     }
940   }
941
942   // Create layout info for the result word.
943   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
944   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
945
946   MarkupProcessor::StyledTextArray resultStyledText;
947   MarkupProcessor::GetStyledTextArray( result, resultStyledText, true );
948
949   TextViewProcessor::CreateTextInfo( resultStyledText,
950                                      DEFAULT_LAYOUT_PARAMETERS,
951                                      resultRelayoutData );
952
953   // Get the result word
954   TextViewProcessor::WordLayoutInfo resultWordLayout;
955
956   if( !resultLayout.mParagraphsLayoutInfo.empty() )
957   {
958     const TextViewProcessor::ParagraphLayoutInfo& paragraph( *resultLayout.mParagraphsLayoutInfo.begin() );
959     if( !paragraph.mWordsLayoutInfo.empty() )
960     {
961       resultWordLayout = *( *resultLayout.mParagraphsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
962     }
963   }
964
965   RemoveCharactersFromWord( position,
966                             numberOfCharacters,
967                             inputWordLayout );
968
969   if( !TestEqual( inputWordLayout, resultWordLayout ) )
970   {
971     tet_printf( "Fail. different layout info. %s\n", location );
972     return false;
973   }
974
975   return true;
976 }
977
978 /**
979  * Removes from the \e input paragraph the \e numberOfWords words starting from the given \e wordIndex and checks the results with \e result.
980  *
981  * If the test fails it prints a short description and the line where this function was called.
982  *
983  * @param description Short description of the experiment.
984  * @param input The input paragraph.
985  * @param wordIndex Index within the paragraph where to start to remove words.
986  * @param numberOfWords The number of words to remove.
987  * @param lineHeightOffset Offset between lines.
988  * @param result The paragraph without the removed words.
989  * @param location Where this function has been called.
990  *
991  * @return \e true if the experiment is successful. Otherwise returns \e false.
992  */
993 bool TestRemoveWordsFromParagraph( const std::string& description, const std::string& input, const std::size_t wordIndex, const std::size_t numberOfWords, const float lineHeightOffset, const std::string& result, const char* location )
994 {
995   tet_printf( "%s\n", description.c_str() );
996
997   // Create layout info for the input paragraph.
998   Toolkit::Internal::TextView::RelayoutData relayoutData;
999   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
1000
1001   MarkupProcessor::StyledTextArray inputStyledText;
1002   MarkupProcessor::GetStyledTextArray( input, inputStyledText, true );
1003
1004   TextViewProcessor::CreateTextInfo( inputStyledText,
1005                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1006                                                                                     Toolkit::TextView::Original,
1007                                                                                     Toolkit::TextView::Original,
1008                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1009                                                                                     Toolkit::TextView::Center,
1010                                                                                     PointSize( lineHeightOffset ),
1011                                                                                     std::string( "..." ),
1012                                                                                     true ),
1013                                      relayoutData );
1014
1015   // Get the input paragraph
1016   TextViewProcessor::ParagraphLayoutInfo inputParagraphLayout;
1017
1018   if( !inputLayout.mParagraphsLayoutInfo.empty() )
1019   {
1020     inputParagraphLayout = *inputLayout.mParagraphsLayoutInfo.begin();
1021   }
1022
1023   // Create layout info for the result paragraph.
1024   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1025   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1026
1027   MarkupProcessor::StyledTextArray resultStyledText;
1028   MarkupProcessor::GetStyledTextArray( result, resultStyledText, true );
1029
1030   TextViewProcessor::CreateTextInfo( resultStyledText,
1031                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1032                                                                                     Toolkit::TextView::Original,
1033                                                                                     Toolkit::TextView::Original,
1034                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1035                                                                                     Toolkit::TextView::Center,
1036                                                                                     PointSize( lineHeightOffset ),
1037                                                                                     std::string( "..." ),
1038                                                                                     true ),
1039                                      resultRelayoutData );
1040
1041   // Get the result paragraph
1042   TextViewProcessor::ParagraphLayoutInfo resultParagraphLayout;
1043
1044   if( !resultLayout.mParagraphsLayoutInfo.empty() )
1045   {
1046     resultParagraphLayout = *resultLayout.mParagraphsLayoutInfo.begin();
1047   }
1048
1049   RemoveWordsFromParagraph( wordIndex,
1050                             numberOfWords,
1051                             lineHeightOffset,
1052                             inputParagraphLayout );
1053
1054   if( !TestEqual( inputParagraphLayout, resultParagraphLayout ) )
1055   {
1056     tet_printf( "Fail. different layout info. %s\n", location );
1057     tet_printf( "            input : [%s]\n", input.c_str() );
1058     tet_printf( "           result : [%s]\n", GetText( resultParagraphLayout ).c_str() );
1059     tet_printf( "  expected result : [%s]\n\n", result.c_str() );
1060
1061     Print(inputParagraphLayout); std::cout << std::endl << std::endl;
1062     Print(resultParagraphLayout); std::cout << std::endl;
1063     return false;
1064   }
1065
1066   return true;
1067 }
1068
1069 /**
1070  * Tests inserts, removes and updates operation in the given \e input text and checks with the given \e result.
1071  *
1072  * If the test fails it prints a short description and the line where this function was called.
1073  *
1074  * @param description Short description of the experiment.
1075  * @param operation Type of update operation (insert, remove, replace)
1076  * @param input The input text.
1077  * @param position Where to insert, remove or replace text.
1078  * @param numberOfCharacters Number of characters to remove or replace.
1079  * @param inputText Inserted or updated text.
1080  * @param lineHeightOffset Offset between lines.
1081  * @param result Expected result.
1082  * @param location Where this function has been called.
1083  *
1084  * @return \e true if the experiment is successful. Otherwise returns \e false.
1085  */
1086 bool TestUpdateTextInfo( const std::string& description,
1087                          UpdateTextInfoOperation operation,
1088                          const std::string& input,
1089                          std::size_t position,
1090                          std::size_t numberOfCharacters,
1091                          const std::string& inputText,
1092                          float lineHeightOffset,
1093                          const std::string& result,
1094                          const char* location )
1095 {
1096   tet_printf( "%s\n", description.c_str() );
1097
1098   // Create layout info for the input.
1099   Toolkit::Internal::TextView::RelayoutData relayoutData;
1100   TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo );
1101
1102   MarkupProcessor::StyledTextArray inputStyledText;
1103   MarkupProcessor::GetStyledTextArray( input, inputStyledText, true );
1104
1105   TextViewProcessor::CreateTextInfo( inputStyledText,
1106                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1107                                                                                     Toolkit::TextView::Original,
1108                                                                                     Toolkit::TextView::Original,
1109                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1110                                                                                     Toolkit::TextView::Center,
1111                                                                                     PointSize( lineHeightOffset ),
1112                                                                                     std::string( "..." ),
1113                                                                                     true ),
1114                                      relayoutData );
1115
1116   // Create layout info for the result.
1117   Toolkit::Internal::TextView::RelayoutData resultRelayoutData;
1118   TextViewProcessor::TextLayoutInfo& resultLayout( resultRelayoutData.mTextLayoutInfo );
1119
1120   MarkupProcessor::StyledTextArray resultStyledText;
1121   MarkupProcessor::GetStyledTextArray( result, resultStyledText, true );
1122
1123   TextViewProcessor::CreateTextInfo( resultStyledText,
1124                                      Toolkit::Internal::TextView::LayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1125                                                                                     Toolkit::TextView::Original,
1126                                                                                     Toolkit::TextView::Original,
1127                                                                                     static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1128                                                                                     Toolkit::TextView::Center,
1129                                                                                     PointSize( lineHeightOffset ),
1130                                                                                     std::string( "..." ),
1131                                                                                     true ),
1132                                      resultRelayoutData );
1133
1134   // Choose operation and call appropiate UpdateTextInfo() method.
1135   const Toolkit::Internal::TextView::LayoutParameters layoutParameters( Toolkit::TextView::SplitByNewLineChar,
1136                                                                         Toolkit::TextView::Original,
1137                                                                         Toolkit::TextView::Original,
1138                                                                         static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1139                                                                         Toolkit::TextView::Center,
1140                                                                         PointSize( lineHeightOffset ),
1141                                                                         std::string( "..." ),
1142                                                                         true );
1143
1144   switch( operation )
1145   {
1146     case Insert:
1147     {
1148       MarkupProcessor::StyledTextArray inputStyledText;
1149       MarkupProcessor::GetStyledTextArray( inputText, inputStyledText, true );
1150
1151       TextViewProcessor::UpdateTextInfo( position,
1152                                          inputStyledText,
1153                                          layoutParameters,
1154                                          relayoutData );
1155       break;
1156     }
1157     case Remove:
1158     {
1159       TextViewProcessor::UpdateTextInfo( position,
1160                                          numberOfCharacters,
1161                                          layoutParameters,
1162                                          relayoutData,
1163                                          TextViewProcessor::CLEAR_TEXT );
1164       break;
1165     }
1166     case Replace:
1167     {
1168       MarkupProcessor::StyledTextArray inputStyledText;
1169       MarkupProcessor::GetStyledTextArray( inputText, inputStyledText, true );
1170
1171       TextViewProcessor::UpdateTextInfo( position,
1172                                          numberOfCharacters,
1173                                          inputStyledText,
1174                                          layoutParameters,
1175                                          relayoutData );
1176       break;
1177     }
1178     default:
1179     {
1180       tet_printf( "TestUpdateTextInfo: unknown update operation. %s\n", location );
1181       return false;
1182     }
1183   }
1184
1185   if( !TestEqual( inputLayout, resultLayout ) )
1186   {
1187     tet_printf( "Fail. different layout info. %s\n", location );
1188
1189     // std::cout << "          result : "; Print( inputLayout );
1190     // std::cout << " expected result : "; Print( resultLayout );
1191     return false;
1192   }
1193
1194   return true;
1195 }
1196
1197 } // namespace
1198
1199
1200 int UtcDaliTextViewCreateTextInfo(void)
1201 {
1202   ToolkitTestApplication application;
1203
1204   tet_infoline("UtcDaliTextViewCreateTextInfo : ");
1205
1206   // Metrics for characters
1207
1208   // Font size = 10
1209   //     size : [9.48351, 9.48351]
1210   //  advance : 9.48351
1211   //  bearing : 8.53516
1212   // ascender : 8.53516
1213
1214   // Font size = 12
1215   //     size : [11.3802, 11.3802]
1216   //  advance : 11.3802
1217   //  bearing : 10.2422
1218   // ascender : 10.2422
1219
1220   // Font size = 14
1221   //     size : [13.2769, 13.2769]
1222   //  advance : 13.2769
1223   //  bearing : 11.9492
1224   // ascender : 11.9492
1225
1226   const float WIDTH_10( 9.48351f );
1227   const float HEIGHT_10( 9.48351f );
1228   const float ADVANCE_10( 9.48351f );
1229   const float BEARING_10( 8.53516f );
1230   const float ASCENDER_10( 8.53516f );
1231
1232   const float WIDTH_12( 11.3802f );
1233   const float HEIGHT_12( 11.3802f );
1234   const float ADVANCE_12( 11.3802f );
1235   const float BEARING_12( 10.2422f );
1236   const float ASCENDER_12( 10.2422f );
1237
1238
1239   // Generate a text.
1240   Toolkit::Internal::TextView::RelayoutData relayoutData;
1241   TextViewProcessor::TextLayoutInfo& textLayoutInfo( relayoutData.mTextLayoutInfo );
1242
1243   std::string text( "Hel<font size='10'>lo wo</font>rld!\n"
1244                     "\n" );
1245
1246   MarkupProcessor::StyledTextArray styledText;
1247   MarkupProcessor::GetStyledTextArray( text, styledText, true );
1248
1249   TextViewProcessor::CreateTextInfo( styledText,
1250                                      DEFAULT_LAYOUT_PARAMETERS,
1251                                      relayoutData );
1252
1253
1254   // Build the text info with metric values.
1255
1256   // Characters
1257
1258   TextViewProcessor::CharacterLayoutInfo layoutInfo10; // ( [lo wo])
1259   layoutInfo10.mHeight = HEIGHT_10;
1260   layoutInfo10.mAdvance = ADVANCE_10;
1261   layoutInfo10.mBearing = BEARING_10;
1262   layoutInfo10.mSize = Size( WIDTH_10, HEIGHT_10 );
1263   layoutInfo10.mAscender = ASCENDER_10;
1264   TextViewProcessor::CharacterLayoutInfo layoutInfo12; // ( [Hel], [rld!] and [CR])
1265   layoutInfo12.mHeight = HEIGHT_12;
1266   layoutInfo12.mAdvance = ADVANCE_12;
1267   layoutInfo12.mBearing = BEARING_12;
1268   layoutInfo12.mSize = Size( WIDTH_12, HEIGHT_12 );
1269   layoutInfo12.mAscender = ASCENDER_12;
1270
1271   TextStyle style10;
1272   style10.SetFontName( "" );
1273   style10.SetFontPointSize( PointSize( 10.f ) );
1274   TextStyle style12;
1275   style12.SetFontName( "" );
1276
1277   layoutInfo12.mStyledText.mStyle = style12;
1278   layoutInfo10.mStyledText.mStyle = style10;
1279
1280   // Words
1281
1282   TextViewProcessor::WordLayoutInfo wordLayout1, wordLayout2, wordLayout3, wordLayout4;
1283
1284   // Hello
1285   wordLayout1.mSize = Size( 3.f * WIDTH_12 + 2.f * WIDTH_10, HEIGHT_12 );
1286   wordLayout1.mAscender = ASCENDER_12;
1287   wordLayout1.mType = TextViewProcessor::NoSeparator;
1288
1289   layoutInfo12.mStyledText.mText = Text( "H" );
1290   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // H
1291   layoutInfo12.mStyledText.mText = Text( "e" );
1292   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // e
1293   layoutInfo12.mStyledText.mText = Text( "l" );
1294   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo12 ); // l
1295   layoutInfo10.mStyledText.mText = Text( "l" );
1296   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo10 ); // l
1297   layoutInfo10.mStyledText.mText = Text( "o" );
1298   wordLayout1.mCharactersLayoutInfo.push_back( layoutInfo10 ); // o
1299
1300   // (white space)
1301   wordLayout2.mSize = Size( WIDTH_10, HEIGHT_10 );
1302   wordLayout2.mAscender = ASCENDER_10;
1303   wordLayout2.mType = TextViewProcessor::WordSeparator;
1304   layoutInfo10.mStyledText.mText = Text( " " );
1305   wordLayout2.mCharactersLayoutInfo.push_back( layoutInfo10 ); // (white space)
1306
1307   // world!
1308   wordLayout3.mSize = Size( 2.f * WIDTH_10 + 4.f * WIDTH_12, HEIGHT_12 );
1309   wordLayout3.mAscender = ASCENDER_12;
1310   wordLayout3.mType = TextViewProcessor::NoSeparator;
1311   layoutInfo10.mStyledText.mText = Text( "w" );
1312   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo10 ); // w
1313   layoutInfo10.mStyledText.mText = Text( "o" );
1314   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo10 ); // o
1315   layoutInfo12.mStyledText.mText = Text( "r" );
1316   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // r
1317   layoutInfo12.mStyledText.mText = Text( "l" );
1318   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // l
1319   layoutInfo12.mStyledText.mText = Text( "d" );
1320   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // d
1321   layoutInfo12.mStyledText.mText = Text( "!" );
1322   wordLayout3.mCharactersLayoutInfo.push_back( layoutInfo12 ); // !
1323
1324   // (new paragraph character)
1325   wordLayout4.mSize = Size( 0.f, HEIGHT_12 );
1326   wordLayout4.mAscender = ASCENDER_12;
1327   wordLayout4.mType = TextViewProcessor::ParagraphSeparator;
1328   layoutInfo12.mStyledText.mText = Text( "\n" );
1329   layoutInfo12.mSize.width = 0.f;
1330   wordLayout4.mCharactersLayoutInfo.push_back( layoutInfo12 ); // (new paragraph char)
1331
1332   // Paragraphs
1333
1334   TextViewProcessor::ParagraphLayoutInfo paragraphLayout1, paragraphLayout2, paragraphLayout3;
1335
1336   paragraphLayout1.mSize = Size( 5.f * WIDTH_10 + 7.f * WIDTH_12, HEIGHT_12 );
1337   paragraphLayout1.mAscender = ASCENDER_12;
1338   paragraphLayout1.mNumberOfCharacters = 13;
1339   paragraphLayout1.mWordsLayoutInfo.push_back( wordLayout1 );
1340   paragraphLayout1.mWordsLayoutInfo.push_back( wordLayout2 );
1341   paragraphLayout1.mWordsLayoutInfo.push_back( wordLayout3 );
1342   paragraphLayout1.mWordsLayoutInfo.push_back( wordLayout4 );
1343
1344   paragraphLayout2.mSize = Size( 0.f, HEIGHT_12 );
1345   paragraphLayout2.mAscender = ASCENDER_12;
1346   paragraphLayout2.mNumberOfCharacters = 1;
1347   paragraphLayout2.mWordsLayoutInfo.push_back( wordLayout4 );
1348
1349   paragraphLayout3.mSize = Size( 0.f, HEIGHT_12 );
1350
1351   // Text (layout)
1352   TextViewProcessor::TextLayoutInfo textLayout;
1353
1354   textLayout.mWholeTextSize = Size( 5.f * WIDTH_10 + 7.f * WIDTH_12, 3.f * HEIGHT_12 );
1355   textLayout.mMaxWordWidth = 2.f * WIDTH_10 + 4.f * WIDTH_12;
1356   textLayout.mNumberOfCharacters = 14;
1357   textLayout.mParagraphsLayoutInfo.push_back( paragraphLayout1 );
1358   textLayout.mParagraphsLayoutInfo.push_back( paragraphLayout2 );
1359   textLayout.mParagraphsLayoutInfo.push_back( paragraphLayout3 );
1360
1361   if(!TestEqual( textLayout, textLayoutInfo ))
1362   {
1363     std::cout << "Layout fails" << std::endl;
1364     Print(textLayout); std::cout << std::endl;
1365     Print(textLayoutInfo); std::cout << std::endl;
1366   }
1367
1368   DALI_TEST_CHECK( TestEqual( textLayout, textLayoutInfo ) );
1369   END_TEST;
1370 }
1371
1372 int UtcDaliTextViewSplitWord(void)
1373 {
1374   ToolkitTestApplication application;
1375
1376   tet_infoline("UtcDaliTextViewSplitWord : ");
1377
1378   struct SplitWordTest splitWordTests[] =
1379   {
1380     {
1381       std::string( "Split word, position 0." ),
1382       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1383       0,
1384       std::string( "" ),
1385       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1386     },
1387     {
1388       std::string( "Split word, position 8." ),
1389       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1390       8,
1391       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1392       std::string( "" ),
1393     },
1394     {
1395       std::string( "Split word, position 2." ),
1396       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1397       2,
1398       std::string( "<font size='10'>He</font>" ),
1399       std::string( "<font size='12'>ll</font><font size='10'>oooo</font>" ),
1400     },
1401     {
1402       std::string( "Split word, position 3." ),
1403       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1404       3,
1405       std::string( "<font size='10'>He</font><font size='12'>l</font>" ),
1406       std::string( "<font size='12'>l</font><font size='10'>oooo</font>" ),
1407     },
1408     {
1409       std::string( "Split word, position 4." ),
1410       std::string( "<font size='10'>He<font size='12'>ll</font>oooo</font>" ),
1411       4,
1412       std::string( "<font size='10'>He</font><font size='12'>ll</font>" ),
1413       std::string( "<font size='10'>oooo</font>" ),
1414     },
1415   };
1416   const std::size_t numberOfTests( 5u );
1417
1418   for( std::size_t index = 0u; index < numberOfTests; ++index )
1419   {
1420     const SplitWordTest& test = splitWordTests[index];
1421
1422     if( !TestSplitWord( test.description, test.input, test.position, test.firstResult, test.lastResult, TEST_LOCATION ) )
1423     {
1424       tet_result( TET_FAIL );
1425     }
1426   }
1427
1428   tet_result( TET_PASS );
1429   END_TEST;
1430 }
1431
1432 int UtcDaliTextViewUpdateTextInfo(void)
1433 {
1434   ToolkitTestApplication application;
1435
1436   tet_infoline("UtcDaliTextViewUpdateTextInfo : ");
1437
1438   struct UpdateTextInfoTest updateTextInfoTest[] =
1439   {
1440     // Remove operations
1441
1442     {
1443       std::string( "Remove from new paragraph character to first character next paragraph." ),
1444       Remove,
1445       std::string("Hello world\nhello world."),
1446       11,
1447       2,
1448       std::string(""),
1449       0.f,
1450       std::string("Hello worldello world."),
1451     },
1452     {
1453       std::string( "Replace style from new paragraph character to first character next paragraph." ),
1454       Replace,
1455       std::string("Hello world\nhello world."),
1456       11,
1457       2,
1458       std::string("<b>\nh</b>"),
1459       0.f,
1460       std::string("Hello world<b>\nh</b>ello world."),
1461     },
1462     {
1463       std::string( "Remove from the beginning to the middle of last word." ),
1464       Remove,
1465       std::string("Hello world, hello world."),
1466       0,
1467       22,
1468       std::string(), // Not used.
1469       0.f,
1470       std::string("ld."),
1471     },
1472     {
1473       std::string( "Remove from the beginning to the middle of the text." ),
1474       Remove,
1475       std::string("Hello world hello world."),
1476       0,
1477       12,
1478       std::string(), // Not used.
1479       0.f,
1480       std::string("hello world."),
1481     },
1482     // Remove within the same word:
1483     // * within the same group of characters with same style.
1484     {
1485       std::string( "Remove within the same word, within the same group of characters with same style" ),
1486       Remove,
1487       std::string("Hello <font size='30'>world\nhello</font> world"),
1488       7,
1489       3,
1490       std::string(), // Not used.
1491       0.f,
1492       std::string( "Hello <font size='30'>wd\nhello</font> world" )
1493     },
1494     // * whole group of characters (merge adjacent group of characters)
1495     {
1496       std::string( "Remove within the same word, whole group of characters (merge adjacent group of characters)" ),
1497       Remove,
1498       std::string("Hello <font size='30'>w<font size='20'>orl</font>d\nhello</font> world"),
1499       7,
1500       3,
1501       std::string(), // Not used.
1502       0.f,
1503       std::string( "Hello <font size='30'>wd\nhello</font> world" )
1504     },
1505     // * whole group of characters (don't merge adjacent gtoup of characters)
1506     {
1507       std::string( "Remove within the same word, whole group of characters (don't merge adjacent gtoup of characters)" ),
1508       Remove,
1509       std::string("Hello <font size='30'>w</font>orl<font size='10'>d\nhello</font> world"),
1510       7,
1511       3,
1512       std::string(), // Not used.
1513       0.f,
1514       std::string( "Hello <font size='30'>w</font><font size='10'>d\nhello</font> world" )
1515     },
1516     // * Remove whole word (merge words)
1517     {
1518       std::string( "Remove within the same word, whole word (merge words)" ),
1519       Remove,
1520       std::string("Hello <font size='30'>w</font>orl<font size='10'>d\nhello</font> world"),
1521       5,
1522       1,
1523       std::string(), // Not used.
1524       0.f,
1525       std::string( "Hello<font size='30'>w</font>orl<font size='10'>d\nhello</font> world" )
1526     },
1527     // * Remove whole word (don't merge words)
1528     {
1529       std::string( "Remove within the same word, whole word (don't merge words)" ),
1530       Remove,
1531       std::string("Hello <font size='30'>w</font>orl<font size='10'>d\nhello</font> world"),
1532       6,
1533       5,
1534       std::string(), // Not used.
1535       0.f,
1536       std::string( "Hello <font size='10'>\nhello</font> world" )
1537     },
1538     // * Remove whole word (merge paragraphs)
1539     {
1540       std::string( "Remove within the same word, whole word (merge paragraphs)" ),
1541       Remove,
1542       std::string("Hello <font size='30'>w</font>orl<font size='10'>d\nhello</font> world"),
1543       11,
1544       1,
1545       std::string(), // Not used.
1546       0.f,
1547       std::string( "Hello <font size='30'>w</font>orl<font size='10'>dhello</font> world" )
1548     },
1549     // * Remove RTL text within LTR
1550     /* TODO check this when RTL text is working
1551     {
1552       std::string( "Remove within the same paragraph, RTL text within LTR." ),
1553       Remove,
1554       std::string("Hello world, שלום עולם, hello world"),
1555       10,
1556       15,
1557       std::string(), // Not used.
1558       0.f,
1559       std::string( "Hello worlello world" )
1560     },
1561     */
1562     // * Remove whole paragraph
1563     {
1564       std::string( "Remove whole paragraph" ),
1565       Remove,
1566       std::string("Hello world, hello world\n"
1567                   "Hello world, hello world\n"
1568                   "Hello world, hello world\n"
1569                   "Hello world, hello world\n"),
1570       25,
1571       25,
1572       std::string(), // Not used.
1573       0.f,
1574       std::string("Hello world, hello world\n"
1575                   "Hello world, hello world\n"
1576                   "Hello world, hello world\n"),
1577     },
1578     {
1579       std::string( "Remove whole paragraph" ),
1580       Remove,
1581       std::string("Hello world, hello world\n"
1582                   "H"),
1583       25,
1584       1,
1585       std::string(), // Not used.
1586       0.f,
1587       std::string("Hello world, hello world\n"),
1588     },
1589
1590
1591     // Insert operations
1592     {
1593       std::string( "insert some text" ),
1594       Insert,
1595       std::string("inpuext"),
1596       4,
1597       0,             // Not used
1598       std::string( "t t" ),
1599       0.f,
1600       std::string( "input text" )
1601     },
1602     {
1603       std::string( "Insert text at the end" ),
1604       Insert,
1605       std::string("touch "),
1606       6,
1607       0,
1608       std::string("me\nhello"),
1609       0.f,
1610       std::string("touch me\nhello")
1611     },
1612
1613     // Replace operations.
1614     {
1615       std::string( "Replace style from the beginning to some point in the middle of the text." ),
1616       Replace,
1617       std::string( "Hello <font color='green'>world</font>" ),
1618       0,
1619       7,
1620       std::string( "<font color='red'>Hello w</font>" ),
1621       0.f,
1622       std::string( "<font color='red'>Hello w</font><font color='green'>orld</font>" )
1623     },
1624     {
1625       std::string( "Replace style from the middle of the text to the end." ),
1626       Replace,
1627       std::string( "Touch me\nhello" ),
1628       6,
1629       8,
1630       std::string( "<b>me\nhello</b>" ),
1631       0.f,
1632       std::string( "Touch <b>me\nhello</b>" )
1633     },
1634     {
1635       std::string( "Remove characters from text. Previous next test:Replace style from the middle of the text 1." ),
1636       Remove,
1637       std::string( "Touch me\nhello\nworld" ),
1638       6,
1639       8,
1640       std::string( "" ),
1641       0.f,
1642       std::string( "Touch \nworld" )
1643     },
1644     {
1645       std::string( "Insert styled text in the middle of a text. Previous: Replace style from the middle of the text 1." ),
1646       Insert,
1647       std::string( "Touch \nworld" ),
1648       6,
1649       0,
1650       std::string( "<b>me\nhello</b>" ),
1651       0.f,
1652       std::string( "Touch <b>me\nhello</b>\nworld" )
1653     },
1654     {
1655       std::string( "Replace style from the middle of the text 1." ),
1656       Replace,
1657       std::string( "Touch me\nhello\nworld" ),
1658       6,
1659       8,
1660       std::string( "<b>me\nhello</b>" ),
1661       0.f,
1662       std::string( "Touch <b>me\nhello</b>\nworld" )
1663     },
1664     {
1665       std::string( "Remove characters from text. Previous next test:Replace style from the middle of the text 2." ),
1666       Remove,
1667       std::string( "Touch me\nhello\nworld" ),
1668       6,
1669       9,
1670       std::string( "" ),
1671       0.f,
1672       std::string( "Touch world" )
1673     },
1674     {
1675       std::string( "Replace style from the middle of the text 2." ),
1676       Replace,
1677       std::string( "Touch me\nhello\nworld" ),
1678       6,
1679       9,
1680       std::string( "<b>me\nhello\n</b>" ),
1681       0.f,
1682       std::string( "Touch <b>me\nhello\n</b>world" )
1683     },
1684   };
1685   const std::size_t numberOfTests( 21u );
1686
1687   for( std::size_t index = 0u; index < numberOfTests; ++index )
1688   {
1689     const UpdateTextInfoTest& test = updateTextInfoTest[index];
1690
1691     if( !TestUpdateTextInfo( test.description, test.operation, test.input, test.position, test.numberOfCharacters, test.inputText, test.lineHeightOffset, test.result, TEST_LOCATION ) )
1692     {
1693       tet_result( TET_FAIL );
1694     }
1695   }
1696
1697   tet_result( TET_PASS );
1698   END_TEST;
1699 }
1700
1701 int UtcDaliTextViewSplitParagraph(void)
1702 {
1703   ToolkitTestApplication application;
1704
1705   tet_infoline("UtcDaliTextViewSplitParagraph : ");
1706
1707   struct SplitParagraphTest splitParagraphTests[] =
1708   {
1709     {
1710       std::string( "Split paragraph, wordPosition 0, position 0." ),
1711       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
1712       0,
1713       0,
1714       3.f,
1715       std::string( "" ),
1716       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
1717     },
1718     {
1719       std::string( "Split paragraph, wordPosition 10, position 4." ),
1720       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
1721       10,
1722       4,
1723       0.f,
1724       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
1725       std::string( "" ),
1726     },
1727     {
1728      std::string( "Split paragraph, wordPosition 2, position 4." ),
1729       std::string("<font size='10'>Hello </font>wor<font size='12'>ld, hello wo</font>rld"),
1730       2,
1731       4,
1732       0.f,
1733       std::string("<font size='10'>Hello </font>wor<font size='12'>l</font>"),
1734       std::string("<font size='12'>d, hello wo</font>rld")
1735     }
1736     /* TODO RTL
1737     {
1738       std::string( "Split paragraph, wordPosition 6, position 0." ),
1739       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
1740       6,
1741       0,
1742       0.f,
1743       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום " ),
1744       std::string( "עולם text text" ),
1745     },
1746     {
1747       std::string( "Split paragraph, wordPosition 4, position 0." ),
1748       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
1749       4,
1750       0,
1751       0.f,
1752       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> " ),
1753       std::string( "שלום עולם text text" ),
1754     },
1755     {
1756       std::string( "Split paragraph2, wordPosition 8, position 0." ),
1757       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם text text" ),
1758       8,
1759       0,
1760       6.f,
1761       std::string( "<font size='10'>He<font size='12'>ll</font>oooo wooorld</font> שלום עולם " ),
1762       std::string( "text text" ),
1763     },
1764     */
1765   };
1766   const std::size_t numberOfTests( 3u );
1767
1768   for( std::size_t index = 0u; index < numberOfTests; ++index )
1769   {
1770     const SplitParagraphTest& test = splitParagraphTests[index];
1771
1772     if( !TestSplitParagraph( test.description,
1773                              test.input,
1774                              test.wordIndex,
1775                              test.characterIndex,
1776                              test.lineHeightOffset,
1777                              test.firstResult,
1778                              test.lastResult,
1779                              TEST_LOCATION ) )
1780     {
1781       tet_result( TET_FAIL );
1782     }
1783   }
1784
1785   tet_result( TET_PASS );
1786   END_TEST;
1787 }
1788
1789 int UtcDaliTextViewMergeWord01(void)
1790 {
1791   ToolkitTestApplication application;
1792
1793   tet_infoline("UtcDaliTextViewMergeWord01 : ");
1794
1795   struct MergeWordsTest mergeWordsTests[] =
1796   {
1797     {
1798       std::string( "Merge words with same style." ),
1799       std::string( "Hel" ),
1800       std::string( "lo" ),
1801       std::string( "Hello" ),
1802     },
1803     {
1804       std::string( "Merge words with different styles." ),
1805       std::string( "<font size='10>Hel</font>" ),
1806       std::string( "<font size='20'>lo</font>" ),
1807       std::string( "<font size='10'>Hel</font><font size='20'>lo</font>" )
1808     },
1809   };
1810   const std::size_t numberOfTests( 2u );
1811
1812   for( std::size_t index = 0u; index < numberOfTests; ++index )
1813   {
1814     const MergeWordsTest& test = mergeWordsTests[index];
1815
1816     if( !TestMergeWords( test.description, test.inputFirst, test.inputLast, test.result, TEST_LOCATION ) )
1817     {
1818       tet_result( TET_FAIL );
1819     }
1820   }
1821
1822   tet_result( TET_PASS );
1823   END_TEST;
1824 }
1825
1826 int UtcDaliTextViewMergeWord02(void)
1827 {
1828   // Negative test.
1829   // It test white spaces and new paragraph characters can't be merged to other words.
1830
1831   ToolkitTestApplication application;
1832
1833   tet_infoline("UtcDaliTextViewMergeWord02 : ");
1834
1835   // Generate three words
1836
1837   Toolkit::Internal::TextView::RelayoutData relayoutData01;
1838   Toolkit::Internal::TextView::RelayoutData relayoutData02;
1839   Toolkit::Internal::TextView::RelayoutData relayoutData03;
1840   TextViewProcessor::TextLayoutInfo& textLayoutInfo01( relayoutData01.mTextLayoutInfo );
1841   TextViewProcessor::TextLayoutInfo& textLayoutInfo02( relayoutData02.mTextLayoutInfo );
1842   TextViewProcessor::TextLayoutInfo& textLayoutInfo03( relayoutData03.mTextLayoutInfo );
1843
1844   std::string text01( " " );
1845   std::string text02( "\n" );
1846   std::string text03( "a" );
1847   MarkupProcessor::StyledTextArray styledText01;
1848   MarkupProcessor::StyledTextArray styledText02;
1849   MarkupProcessor::StyledTextArray styledText03;
1850   MarkupProcessor::GetStyledTextArray( text01, styledText01, true );
1851   MarkupProcessor::GetStyledTextArray( text02, styledText02, true );
1852   MarkupProcessor::GetStyledTextArray( text03, styledText03, true );
1853
1854   TextViewProcessor::CreateTextInfo( styledText01,
1855                                      DEFAULT_LAYOUT_PARAMETERS,
1856                                      relayoutData01 );
1857
1858   TextViewProcessor::WordLayoutInfo wordLayoutInfo01;
1859
1860   wordLayoutInfo01 = *( *textLayoutInfo01.mParagraphsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
1861
1862   TextViewProcessor::CreateTextInfo( styledText02,
1863                                      DEFAULT_LAYOUT_PARAMETERS,
1864                                      relayoutData02 );
1865
1866   TextViewProcessor::WordLayoutInfo wordLayoutInfo02;
1867
1868   wordLayoutInfo02 = *( *textLayoutInfo02.mParagraphsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
1869
1870   TextViewProcessor::CreateTextInfo( styledText03,
1871                                      DEFAULT_LAYOUT_PARAMETERS,
1872                                      relayoutData03 );
1873
1874   TextViewProcessor::WordLayoutInfo wordLayoutInfo03;
1875
1876   wordLayoutInfo03 = *( *textLayoutInfo03.mParagraphsLayoutInfo.begin() ).mWordsLayoutInfo.begin();
1877
1878   // Test MergeWord() asserts if white spaces or new paragraph chars are merged.
1879   bool assert1 = false;
1880   bool assert2 = false;
1881   bool assert3 = false;
1882   bool assert4 = false;
1883   bool assert5 = false;
1884   bool assert6 = false;
1885
1886   try
1887   {
1888     MergeWord( wordLayoutInfo01,
1889                wordLayoutInfo02 );
1890   }
1891   catch( Dali::DaliException& e )
1892   {
1893     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
1894     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new paragraph characters can't be merged with other words.\"", TEST_LOCATION );
1895     assert1 = true;
1896   }
1897   try
1898   {
1899     MergeWord( wordLayoutInfo01,
1900                wordLayoutInfo03 );
1901   }
1902   catch( Dali::DaliException& e )
1903   {
1904     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
1905     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new paragraph characters can't be merged with other words.\"", TEST_LOCATION );
1906     assert2 = true;
1907   }
1908   try
1909   {
1910     MergeWord( wordLayoutInfo02,
1911                wordLayoutInfo01 );
1912   }
1913   catch( Dali::DaliException& e )
1914   {
1915     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
1916     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new paragraph characters can't be merged with other words.\"", TEST_LOCATION );
1917     assert3 = true;
1918   }
1919   try
1920   {
1921     MergeWord( wordLayoutInfo02,
1922                wordLayoutInfo03 );
1923   }
1924   catch( Dali::DaliException& e )
1925   {
1926     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
1927     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new paragraph characters can't be merged with other words.\"", TEST_LOCATION );
1928     assert4 = true;
1929   }
1930   try
1931   {
1932     MergeWord( wordLayoutInfo03,
1933                wordLayoutInfo01 );
1934   }
1935   catch( Dali::DaliException& e )
1936   {
1937     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
1938     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new paragraph characters can't be merged with other words.\"", TEST_LOCATION );
1939     assert5 = true;
1940   }
1941   try
1942   {
1943     MergeWord( wordLayoutInfo03,
1944                wordLayoutInfo02 );
1945   }
1946   catch( Dali::DaliException& e )
1947   {
1948     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
1949     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeWord(). ERROR: White spaces or new paragraph characters can't be merged with other words.\"", TEST_LOCATION );
1950     assert6 = true;
1951   }
1952
1953   if( assert1 && assert2 && assert3 && assert4 && assert5 && assert6 )
1954   {
1955     tet_result( TET_PASS );
1956   }
1957   else
1958   {
1959     tet_result( TET_FAIL );
1960   }
1961   END_TEST;
1962 }
1963
1964 int UtcDaliTextViewMergeParagraph01(void)
1965 {
1966   ToolkitTestApplication application;
1967
1968   tet_infoline("UtcDaliTextViewMergeParagraph01 : ");
1969
1970   struct MergeParagraphsTest mergeParagraphsTests[] =
1971   {
1972     {
1973       std::string( "Merge a void first paragraph." ),
1974       std::string( "" ),
1975       std::string( "Hello world, this is a whole paragraph" ),
1976       2.f,
1977       std::string( "Hello world, this is a whole paragraph" )
1978     },
1979     {
1980       std::string( "Merge a void last paragraph." ),
1981       std::string( "Hello world, this is a whole paragraph" ),
1982       std::string( "" ),
1983       0.f,
1984       std::string( "Hello world, this is a whole paragraph" )
1985     },
1986     /* TODO RTL
1987     {
1988       std::string( "Merge paragraphs: last starting with RTL text and first ending with RTL" ),
1989       std::string( "Hello world, שלום" ),
1990       std::string( " עולם, hello world." ),
1991       6.f,
1992       std::string( "Hello world, שלום עולם, hello world." )
1993     },
1994     {
1995       std::string( "Merge paragraphs and don't merge last and first words." ),
1996       std::string( "Hello world, " ),
1997       std::string( "שלום עולם, hello world." ),
1998       3.f,
1999       std::string( "Hello world, שלום עולם, hello world." )
2000     },
2001     */
2002     {
2003       std::string( "Merge paragraphs. Don't merge words" ),
2004       std::string( "Hello world," ),
2005       std::string( " this is a whole paragraph" ),
2006       0.f,
2007       std::string( "Hello world, this is a whole paragraph" )
2008     },
2009     {
2010       std::string( "Merge paragraphs. Merge words" ),
2011       std::string( "Hello world, th" ),
2012       std::string( "is is a whole paragraph" ),
2013       0.f,
2014       std::string( "Hello world, this is a whole paragraph" )
2015     },
2016   };
2017   const std::size_t numberOfTests( 4u );
2018
2019   for( std::size_t index = 0u; index < numberOfTests; ++index )
2020   {
2021     const MergeParagraphsTest& test = mergeParagraphsTests[index];
2022
2023     if( !TestMergeParagraphs( test.description, test.inputFirst, test.inputLast, test.lineHeightOffset, test.result, TEST_LOCATION ) )
2024     {
2025       tet_result( TET_FAIL );
2026     }
2027   }
2028
2029   tet_result( TET_PASS );
2030   END_TEST;
2031 }
2032
2033 int UtcDaliTextViewMergeParagraph02(void)
2034 {
2035   ToolkitTestApplication application;
2036
2037   tet_infoline("UtcDaliTextViewMergeParagraph02 : ");
2038
2039   Toolkit::Internal::TextView::RelayoutData relayoutData01;
2040   Toolkit::Internal::TextView::RelayoutData relayoutData02;
2041   TextViewProcessor::TextLayoutInfo& textLayoutInfo01( relayoutData01.mTextLayoutInfo );
2042   TextViewProcessor::TextLayoutInfo& textLayoutInfo02( relayoutData02.mTextLayoutInfo );
2043
2044   std::string text01( "Hello world\n" );
2045   std::string text02( "hello world" );
2046   MarkupProcessor::StyledTextArray styledText01;
2047   MarkupProcessor::StyledTextArray styledText02;
2048   MarkupProcessor::GetStyledTextArray( text01, styledText01, true );
2049   MarkupProcessor::GetStyledTextArray( text02, styledText02, true );
2050
2051   TextViewProcessor::CreateTextInfo( styledText01,
2052                                      DEFAULT_LAYOUT_PARAMETERS,
2053                                      relayoutData01 );
2054
2055   TextViewProcessor::ParagraphLayoutInfo paragraphLayoutInfo01;
2056
2057   paragraphLayoutInfo01 = *textLayoutInfo01.mParagraphsLayoutInfo.begin();
2058
2059   TextViewProcessor::CreateTextInfo( styledText02,
2060                                      DEFAULT_LAYOUT_PARAMETERS,
2061                                      relayoutData02 );
2062
2063   TextViewProcessor::ParagraphLayoutInfo paragraphLayoutInfo02;
2064
2065   paragraphLayoutInfo02 = *textLayoutInfo02.mParagraphsLayoutInfo.begin();
2066
2067   bool assert1 = false;
2068
2069   try
2070   {
2071     MergeParagraph( paragraphLayoutInfo01,
2072                     paragraphLayoutInfo02 );
2073   }
2074   catch( Dali::DaliException& e )
2075   {
2076     tet_printf( "Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str() );
2077     DALI_TEST_EQUALS( e.mCondition, "!\"TextViewProcessor::MergeParagraph(). ERROR: A paragraph can't be merged to another paragraph which finishes with a new paragraph character.\"", TEST_LOCATION );
2078     assert1 = true;
2079   }
2080
2081   if( assert1 )
2082   {
2083     tet_result( TET_PASS );
2084   }
2085   else
2086   {
2087     tet_result( TET_FAIL );
2088   }
2089   END_TEST;
2090 }
2091
2092 int UtcDaliTextViewRemoveCharactersFromWord(void)
2093 {
2094   ToolkitTestApplication application;
2095
2096   tet_infoline("UtcDaliTextViewMergeWord02 : ");
2097
2098   struct RemoveCharactersFromWordTest removeCharactersFromWordTests[] =
2099   {
2100     {
2101       std::string( "Delete 0 characters." ),
2102       std::string( "Hello" ),
2103       3,
2104       0,
2105       std::string( "Hello" ),
2106     },
2107     {
2108       std::string( "Delete within the same group of characters. Starting from the beginning" ),
2109       std::string( "Hello" ),
2110       0,
2111       3,
2112       std::string( "lo" ),
2113     },
2114     {
2115       std::string( "Delete within the same group of characters. Somewhere in the middle" ),
2116       std::string( "Hello" ),
2117       2,
2118       2,
2119       std::string( "Heo" ),
2120     },
2121     {
2122       std::string( "Delete within the same group of characters. Starting somewhere in the middle to the end" ),
2123       std::string( "Hello" ),
2124       3,
2125       2,
2126       std::string( "Hel" ),
2127     },
2128     {
2129       std::string( "Delete within the same group of characters. Finish just before a new one." ),
2130       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2131       1,
2132       2,
2133       std::string( "<font size='10'>H</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2134     },
2135     {
2136       std::string( "Delete starting in one group of characters and finishing in a different one. No merge of groups." ),
2137       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2138       2,
2139       3,
2140       std::string( "<font size='10'>He</font><font size='20'>Wo</font><font size='30'>rld</font>" ),
2141     },
2142     {
2143       std::string( "Delete within the same group of characters. Starting just after a different one." ),
2144       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2145       7,
2146       2,
2147       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>d</font>" ),
2148     },
2149     {
2150       std::string( "Delete whole group of characters. No merge" ),
2151       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2152       3,
2153       4,
2154       std::string( "<font size='10'>Hel</font><font size='30'>rld</font>" ),
2155     },
2156     {
2157       std::string( "Delete whole group of characters and part of the adjacent ones. No merge" ),
2158       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='30'>rld</font>" ),
2159       2,
2160       6,
2161       std::string( "<font size='10'>He</font><font size='30'>ld</font>" ),
2162     },
2163     {
2164       std::string( "Delete whole group of characters. Merge" ),
2165       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='10'>rld</font>" ),
2166       3,
2167       4,
2168       std::string( "<font size='10'>Helrld</font>" ),
2169     },
2170     {
2171       std::string( "Delete whole group of characters and part of the adjacent ones. Merge" ),
2172       std::string( "<font size='10'>Hel</font><font size='20'>loWo</font><font size='10'>rld</font>" ),
2173       2,
2174       6,
2175       std::string( "<font size='10'>Held</font>" ),
2176     },
2177   };
2178   const std::size_t numberOfTests( 11u );
2179
2180   for( std::size_t index = 0u; index < numberOfTests; ++index )
2181   {
2182     const RemoveCharactersFromWordTest& test = removeCharactersFromWordTests[index];
2183
2184     if( !TestRemoveCharactersFromWord( test.description, test.input, test.position, test.numberOfCharacters, test.result, TEST_LOCATION ) )
2185     {
2186       tet_result( TET_FAIL );
2187     }
2188   }
2189
2190   tet_result( TET_PASS );
2191   END_TEST;
2192 }
2193
2194 int UtcDaliTextViewRemoveWordsFromParagraph(void)
2195 {
2196   // Note: Currently RemoveWordsFromParagraph() function is only used to remove a number of words from the beginning, or
2197   //       from a given index to the end.
2198
2199   ToolkitTestApplication application;
2200
2201   tet_infoline("UtcDaliTextViewRemoveWordsFromParagraph : ");
2202   struct RemoveWordsFromParagraphTest removeWordsFromParagraphTest[] =
2203   {
2204     {
2205       std::string( "Delete 0 words." ),
2206       std::string( "Hello hello, שלום עולם hello hello" ),
2207       0,
2208       0,
2209       2.f,
2210       std::string( "Hello hello, שלום עולם hello hello" ),
2211     },
2212     {
2213       std::string( "Delete from the middle to the end." ),
2214       std::string( "Hello hello, שלום עולם hello hello" ),
2215       4,
2216       7,
2217       0.f,
2218       std::string( "Hello hello, " ),
2219     },
2220     {
2221       std::string( "Delete from the beginning to the middle." ),
2222       std::string( "Hello hello, שלום עולם hello hello" ),
2223       0,
2224       8,
2225       6.f,
2226       std::string( "hello hello" ),
2227     },
2228   };
2229   const std::size_t numberOfTests( 3u );
2230
2231   for( std::size_t index = 0u; index < numberOfTests; ++index )
2232   {
2233     const RemoveWordsFromParagraphTest& test = removeWordsFromParagraphTest[index];
2234
2235     if( !TestRemoveWordsFromParagraph( test.description, test.input, test.wordIndex, test.numberOfWords, test.lineHeightOffset, test.result, TEST_LOCATION ) )
2236     {
2237       tet_result( TET_FAIL );
2238     }
2239   }
2240
2241   tet_result( TET_PASS );
2242   END_TEST;
2243 }