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