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